Back to index

wims  3.65+svn20090927
ObjectTracker.java
Go to the documentation of this file.
00001 package rene.zirkel.tools;
00002 
00003 // file: ObjectTracker.java
00004 
00005 import java.awt.Graphics;
00006 import java.awt.event.MouseEvent;
00007 import java.util.Enumeration;
00008 import java.util.Vector;
00009 
00010 import rene.util.xml.XmlTag;
00011 import rene.util.xml.XmlTree;
00012 import rene.util.xml.XmlWriter;
00013 import rene.zirkel.Zirkel;
00014 import rene.zirkel.ZirkelCanvas;
00015 import rene.zirkel.construction.Construction;
00016 import rene.zirkel.construction.ConstructionException;
00017 import rene.zirkel.construction.Selector;
00018 import rene.zirkel.constructors.*;
00019 import rene.zirkel.graphics.*;
00020 import rene.zirkel.objects.*;
00021 import rene.zirkel.structures.Coordinates;
00022 
00023 public class ObjectTracker extends ObjectConstructor
00024        implements TrackPainter, Runnable, Selector
00025 {      PointObject PM;
00026        ConstructionObject O,P;
00027        int PMax=16,PN;
00028        ConstructionObject PO[]=new ConstructionObject[PMax];
00029        Vector V=new Vector(),VPM=new Vector();
00030        Vector VO[]=new Vector[PMax];
00031        boolean Animate,Paint;
00032        public boolean Interactive=true;
00033        boolean Other=false;
00034        ZirkelCanvas ZC;
00035        
00036        public ObjectTracker ()
00037        {
00038        }
00039 
00040        public ObjectTracker (ConstructionObject p, PointObject pm, ConstructionObject o,
00041               ZirkelCanvas zc, boolean animate, boolean paint,
00042               ConstructionObject po[])
00043        {      P=p; PM=pm; O=o;
00044               if (P!=null && O!=null && (PM!=null || (O instanceof ExpressionObject)))
00045               {      Animate=animate;
00046                      Paint=paint;
00047                      if (PM!=null) PM.project(O);
00048                      zc.validate();
00049                      zc.repaint();
00050                      showStatus(zc);
00051                      PN=0;
00052                      for (int i=0; i<po.length; i++)
00053                      {      if (i>=PMax || po[i]==null) break;
00054                             PO[PN]=po[i];
00055                             VO[i]=new Vector();
00056                             PN++;
00057                      }
00058               }
00059        }
00060 
00061        public boolean isAdmissible (ZirkelCanvas zc, ConstructionObject o)
00062        {      if (O==null)
00063               {      if (o instanceof ExpressionObject && ((ExpressionObject)o).isSlider()) return true;
00064                      if (o instanceof PrimitiveLineObject) return true;
00065                      if (o instanceof PrimitiveCircleObject) return true;
00066                      if (o instanceof PointObject && ((PointObject)o).isPointOn()) return true;
00067                      return false;
00068               }
00069               else
00070               {      if (!(o instanceof PointObject)) return false;
00071                      if (!((MoveableObject)o).moveable()) return false;
00072                      if ((O instanceof CircleObject) && 
00073                             ((CircleObject)O).getP2()==o) return true;
00074                      if (zc.depends(O,o)) return false;
00075                      ConstructionObject bound=((PointObject)o).getBound();
00076                      if (bound!=null && bound!=O) return false;
00077                      return true;
00078               }
00079        }
00080        
00081        public void mousePressed (MouseEvent e, ZirkelCanvas zc)
00082        {      double x=zc.x(e.getX()),y=zc.y(e.getY());
00083               if (P==null) // no point selected yet
00084               {      P=zc.selectPoint(e.getX(),e.getY());
00085                      if (P==null) P=zc.selectLine(e.getX(),e.getY());
00086                      if (P!=null)
00087                      {      P.setSelected(true);
00088                             zc.repaint();
00089                      }
00090                      if (e.isShiftDown())
00091                      {      Other=true; PN=0;
00092                      }
00093                      else Other=false;
00094                      showStatus(zc);
00095               }
00096               else if (Other) // want more points to track
00097               {      ConstructionObject P=zc.selectPoint(e.getX(),e.getY());
00098                      if (P==null) P=zc.selectLine(e.getX(),e.getY());
00099                      if (P!=null)
00100                      {      P.setSelected(true);
00101                             zc.repaint();
00102                             PO[PN]=P;
00103                             VO[PN]=new Vector();
00104                             PN++;
00105                      }
00106                      if (!e.isShiftDown() || PN>=PMax) Other=false;
00107                      showStatus(zc);
00108               }             
00109               else if (O==null) // no object to track on yet
00110               {      O=zc.selectWithSelector(e.getX(),e.getY(),this);
00111                      if (O instanceof ExpressionObject)
00112                      {      zc.clearSelected();
00113                             zc.clearIndicated();
00114                             Animate=!e.isShiftDown();
00115                             Paint=true;
00116                             compute(zc);
00117                             ZC=zc;
00118                             if (Animate) zc.validate();
00119                             zc.repaint();
00120                      }
00121                      else if (O instanceof PointObject && ((PointObject)O).isPointOn())
00122                      {      PM=(PointObject)O;
00123                             O=PM.getBound();
00124                             zc.clearSelected();
00125                             zc.clearIndicated();
00126                             Animate=!e.isShiftDown();
00127                             Paint=true;
00128                             compute(zc);
00129                             ZC=zc;
00130                             if (Animate) zc.validate();
00131                             zc.repaint();
00132                      }
00133                      else
00134                      {      if (O!=null)
00135                             {      O.setSelected(true);
00136                                    zc.repaint();
00137                             }
00138                             showStatus(zc);
00139                      }
00140               }
00141               else if (PM==null && !(O instanceof ExpressionObject))
00142               {      ConstructionObject pm=
00143                             zc.selectWithSelector(e.getX(),e.getY(),this);
00144                      if (pm==null) return;
00145                      PM=(PointObject)pm;
00146                      zc.clearSelected();
00147                      zc.clearIndicated();
00148                      Animate=!e.isShiftDown();
00149                      Paint=true;
00150                      compute(zc);
00151                      ZC=zc;
00152                      if (Animate) zc.validate();
00153                      zc.repaint();
00154               }
00155               else if (!e.isControlDown() && !e.isShiftDown() && !e.isAltDown())
00156               {      if (!Running && Interactive && PM!=null && PM.nearto(e.getX(),e.getY(),zc))
00157                      {      Dragging=true;
00158                             zc.getConstruction().shouldSwitch(true);
00159                      }
00160                      else if (Animate)
00161                      {      if (Paint)
00162                             {      Paint=false;
00163                             }
00164                             else
00165                             {      Animate=false;
00166                                    Paint=true;
00167                                    if (Running) stop();
00168                                    showStatus(zc);
00169                             }
00170                      }
00171                      else
00172                      {      if (Running) return;
00173                             Paint=true;
00174                             Animate=true;
00175                             compute(zc);
00176                             zc.validate();
00177                             zc.repaint();
00178                             showStatus(zc);
00179                      }
00180               }
00181        }
00182        
00183        public void mouseMoved (MouseEvent e, ZirkelCanvas zc, boolean simple)
00184        {      if (PM!=null) return;
00185               if (P==null || Other)
00186                      zc.indicatePointsOrLines(e.getX(),e.getY());
00187               else if (O==null)
00188                      zc.indicateWithSelector(e.getX(),e.getY(),this);
00189               else
00190                      zc.indicateWithSelector(e.getX(),e.getY(),this);
00191        }
00192 
00193        public void mouseDragged (MouseEvent e, ZirkelCanvas zc)
00194        {      if (!Dragging || PM==null) return;
00195               double oldx=PM.getX(),oldy=PM.getY();
00196               PM.move(zc.x(e.getX()),zc.y(e.getY()));
00197               zc.dovalidate();
00198               if (P.valid()) zc.repaint();
00199        }
00200 
00201        public void mouseReleased (MouseEvent e, ZirkelCanvas zc)
00202        {      if (!Dragging || PM==null) return;
00203               zc.getConstruction().shouldSwitch(false);
00204               Dragging=false;
00205               zc.validate();
00206        }
00207 
00208        public void reset (ZirkelCanvas zc)
00209        {      zc.clearSelected();
00210               if (Running) stop();
00211               PM=null; P=O=null; V=new Vector(); PN=0;
00212               for (int i=0; i<PMax; i++) VO[i]=null;
00213               zc.repaint();
00214               showStatus(zc);
00215               Omit=1;
00216        }
00217 
00218        public void showStatus (ZirkelCanvas zc)
00219        {      if (P==null || Other) zc.showStatus(
00220                      Zirkel.name("message.objecttracker.select"));
00221               else if (O==null) zc.showStatus(
00222                      Zirkel.name("message.objecttracker.object"));
00223               else if (PM==null && !(O instanceof ExpressionObject)) zc.showStatus(
00224                      Zirkel.name("message.objecttracker.selectpoint"));
00225               else if (Running) zc.showStatus(
00226                      Zirkel.name("message.objecttracker.stop"));
00227               else zc.showStatus(
00228                      Zirkel.name("message.objecttracker.start"));
00229        }
00230 
00231        public Enumeration elements ()
00232        {      return V.elements();
00233        }
00234        
00235        public void paint (MyGraphics g, ZirkelCanvas zc)
00236        {      if (!isComplete()) return;
00237               if (P==null || !Paint) return;
00238               Coordinates C;
00239               Enumeration e=V.elements();
00240               double c0,r0,c,r;
00241               g.setColor(P);
00242               PolygonDrawer pd=new PolygonDrawer(g,P);
00243               if (e.hasMoreElements())
00244               {      C=(Coordinates)e.nextElement();
00245                      c0=zc.col(C.X); r0=zc.row(C.Y);
00246                      pd.startPolygon(c0,r0);
00247                      while (e.hasMoreElements())
00248                      {      C=(Coordinates)e.nextElement();
00249                             c=zc.col(C.X); r=zc.row(C.Y);
00250                             if (Math.abs(c0-c)<100 && Math.abs(r0-r)<100) 
00251                                    pd.drawTo(c,r);
00252                             else
00253                                    pd.finishPolygon();
00254                             c0=c; r0=r;
00255                      }
00256                      pd.finishPolygon();
00257               }
00258               for (int i=0; i<PN; i++)
00259               {      e=VO[i].elements();
00260                      g.setColor(PO[i]);
00261                      pd=new PolygonDrawer(g,PO[i]);
00262                      if (e.hasMoreElements())
00263                      {      C=(Coordinates)e.nextElement();
00264                             c0=zc.col(C.X); r0=zc.row(C.Y);
00265                             pd.startPolygon(c0,r0);
00266                             while (e.hasMoreElements())
00267                             {      C=(Coordinates)e.nextElement();
00268                                    c=zc.col(C.X); r=zc.row(C.Y);
00269                                    if (Math.abs(c0-c)<100 && Math.abs(r0-r)<100) 
00270                                           pd.drawTo(c,r);
00271                                    else
00272                                           pd.finishPolygon();
00273                                    c0=c; r0=r;
00274                             }
00275                      }
00276                      pd.finishPolygon();
00277               }
00278        }
00279 
00280        boolean Running=false,Stopped=false;
00281        
00282        public void validate (ZirkelCanvas zc)
00283        {      if (!isComplete()) return;
00284               if (O instanceof ExpressionObject && !((ExpressionObject)O).isSlider()) return;
00285               if (Running) return;
00286               if (PM!=null) 
00287               {      PM.project(O);
00288                      oldx=PM.getX();
00289                      oldy=PM.getY();
00290               }
00291               else if (O instanceof ExpressionObject)
00292               {      oldx=((ExpressionObject)O).getSliderPosition();
00293               }
00294               compute(zc);
00295               if (Animate)
00296               {      ZC=zc;
00297                      new Thread(this).start();
00298               }
00299               else
00300               {      if (PM!=null)
00301                      {      PM.move(oldx,oldy);
00302                      }
00303                      zc.dovalidate();
00304                      zc.repaint();
00305               }
00306        }
00307        
00308        double da=0;
00309        double oldx,oldy;
00310        double X,Y,DX,DY;
00311        double XO[]=new double[PMax],YO[]=new double[PMax],
00312               DXO[]=new double[PMax],DYO[]=new double[PMax];
00313        int Omit=1;
00314 
00315        public void animate (ZirkelCanvas zc)
00316        {      if (!isComplete()) return;
00317               zc.getConstruction().clearSwitches();
00318               zc.getConstruction().shouldSwitch(true);
00319               Enumeration e=VPM.elements();
00320               Enumeration ev=V.elements();
00321               long time=System.currentTimeMillis();
00322               int i=0;
00323               boolean start=false;
00324               Graphics ZCG=ZC.getGraphics();
00325               while (e.hasMoreElements())
00326               {      Coordinates c=(Coordinates)e.nextElement();
00327                      Coordinates cv=(Coordinates)ev.nextElement();
00328                      if (PM==null && !(O instanceof ExpressionObject)) break;
00329                      synchronized(zc)
00330                      {      if (PM!=null)
00331                                    PM.move(c.X,c.Y);
00332                             else if (O instanceof ExpressionObject) 
00333                                    ((ExpressionObject)O).setSliderPosition(c.X);
00334                             if (!start)
00335                             {      zc.resetSum();
00336                                    start=true;
00337                             }
00338                      }
00339                      zc.dovalidate();
00340                      i++;
00341                      if (i<Omit) continue;
00342                      i=0;
00343                      if (zc.isInside(cv.X,cv.Y))
00344                      {      if (P!=null && P.valid()) ZC.paint(ZCG);
00345                             try
00346                             {      long t=System.currentTimeMillis();
00347                                    int h=(int)(t-time);
00348                                    if (h<0) h=0;
00349                                    if (h>50) h=50;
00350                                    Thread.sleep(50-h);
00351                                    time=System.currentTimeMillis();
00352                             }
00353                             catch (Exception ex) {}
00354                      }
00355                      if (Stopped) break;
00356               }
00357               ZCG.dispose();
00358               zc.getConstruction().shouldSwitch(false);
00359               zc.getConstruction().clearSwitches();
00360        }
00361 
00362        public ConstructionObject getObject () { return O; }
00363        
00364        double mod (double x)
00365        {      if (x>=Math.PI) return x-2*Math.PI;
00366               if (x<-Math.PI) return x+2*Math.PI;
00367               return x;
00368        }
00369        
00370        public void run ()
00371        {      if (O instanceof ExpressionObject && !((ExpressionObject)O).isSlider()) return;
00372               if (V.size()==0) return;
00373               if (!Animate) return;
00374               Running=true; Stopped=false;
00375               showStatus(ZC);
00376               while (true)
00377               {      try
00378                      {      Thread.sleep(100);
00379                      }
00380                      catch (Exception ex) {}
00381                      if (ZC.I!=null) break;
00382               }
00383               while (true)
00384               {      if (PM!=null) PM.move(oldx,oldy);
00385                      else if (O instanceof ExpressionObject)
00386                      {      ((ExpressionObject)O).setSliderPosition(oldx);
00387                      }
00388                      animate(ZC);
00389                      if (Stopped) break;
00390               }
00391               if (PM!=null && !(O instanceof ExpressionObject))
00392               {      if (PM!=null) PM.move(oldx,oldy);
00393                      else if (O instanceof ExpressionObject)
00394                      {      ((ExpressionObject)O).setSliderPosition(oldx);
00395                      }
00396                      ZC.getConstruction().switchBack();
00397                      ZC.dovalidate();
00398                      ZC.repaint();
00399               }
00400               synchronized (this)
00401               {      notify();
00402               }
00403               Running=false;
00404               showStatus(ZC);
00405        }
00406        
00407        public void invalidate (ZirkelCanvas zc)
00408        {      stop();
00409        }
00410        
00411        public void stop ()
00412        {      if (!Running) return;
00413               Stopped=true;
00414               try { wait(); } catch (Exception e) {}
00415               ZC.repaint();
00416               showStatus(ZC);
00417        }
00418        
00419        public void save (XmlWriter xml)
00420        {      if (P==null || O==null || (PM==null && !(O instanceof ExpressionObject))) return;
00421               xml.startTagStart("Track");
00422               xml.printArg("track",P.getName());
00423               for (int i=0; i<PN; i++)
00424               {      xml.printArg("track"+i,PO[i].getName());
00425               }
00426               xml.printArg("on",O.getName());
00427               if (PM!=null) xml.printArg("move",PM.getName());
00428               if (Animate && Paint) xml.printArg("animate","true");
00429               else if (Animate && !Paint) xml.printArg("animate","nopaint");
00430               if (Omit>1) xml.printArg("omit",""+(Omit-1));
00431               xml.finishTagNewLine();
00432        }
00433        
00434        public void pause (boolean flag)
00435        {      if (flag)
00436               {      if (Running) stop();
00437               }
00438        }
00439 
00443        public synchronized void compute (ZirkelCanvas zc)
00444        {      if (!isComplete()) return;
00445               double x=0,y=0;
00446               if (PM!=null)
00447               {      x=PM.getX(); y=PM.getY();
00448               }
00449               else if (O instanceof ExpressionObject)
00450               {      x=((ExpressionObject)O).getSliderPosition();
00451               }
00452               zc.getConstruction().clearSwitches();
00453               zc.getConstruction().shouldSwitch(true);
00454               docompute(zc);
00455               zc.getConstruction().shouldSwitch(false);
00456               zc.getConstruction().clearSwitches();
00457               if (PM!=null) PM.move(x,y);
00458               else if (O instanceof ExpressionObject)
00459               {      ((ExpressionObject)O).setSliderPosition(x);
00460               }
00461               zc.dovalidate();
00462        }
00463        
00475        public synchronized void docompute (ZirkelCanvas zc)
00476        {      V=new Vector();
00477               for (int i=0; i<PN; i++) VO[i]=new Vector();
00478               VPM=new Vector();
00479               // Running on a circle:
00480               if (O instanceof PrimitiveCircleObject)
00481               {      zc.getConstruction().shouldSwitch(false);
00482                      PrimitiveCircleObject c=(PrimitiveCircleObject)O;
00483                      double x=c.getX(),y=c.getY(),r=c.getR();
00484                      PM.project(c);
00485                      double amin=0,amax=0,astart=0,anull=0;
00486                      double dmax=0.5;
00487                      boolean range=false;
00488                      if (c.hasRange())
00489                      {      range=true;
00490                             double a1=c.getA1();
00491                             double a2=c.getA2();
00492                             double d=a2-a1;
00493                             while (d<0) d+=2*Math.PI;
00494                             while (d>=2*Math.PI) d-=2*Math.PI;
00495                             amin=astart=-d/2;
00496                             amax=d/2;
00497                             anull=(a1+a2)/2;
00498                      }
00499                      else
00500                      {      amin=astart=-Math.PI*0.9999;
00501                             amax=Math.PI*0.9999;
00502                      }
00503                      double a=astart;
00504                      PM.move(x+r*Math.cos(anull+a),y+r*Math.sin(anull+a));
00505                      PM.project(c);
00506                      zc.getConstruction().validate(P,PM);
00507                      zc.resetSum();
00508                      double x1=0,y1=0;
00509                      boolean started=false;
00510                      if (P.valid())
00511                      {      zc.getConstruction().shouldSwitch(true);
00512                             if (P instanceof PointObject)
00513                             {      PointObject p=(PointObject)P;
00514                                    x1=p.getX(); y1=p.getY();
00515                                    V.addElement(new Coordinates(x1,y1));
00516                                    VPM.addElement(new Coordinates(PM.getX(),PM.getY()));
00517                                    started=true;
00518                             }
00519                             else if (P instanceof PrimitiveLineObject)
00520                             {      PrimitiveLineObject L=(PrimitiveLineObject)P;
00521                                    X=L.getX(); Y=L.getY(); DX=L.getDX(); DY=L.getDY();
00522                                    started=true; 
00523                             }
00524                      }
00525                      boolean startedO[]=new boolean[PMax];
00526                      for (int i=0; i<PN; i++) startedO[i]=false;
00527                      long time=System.currentTimeMillis();
00528                      addSecondary(startedO,zc);
00529                      double dmin=0.001;
00530                      if (da<1e-10 || da>zc.dx(1)) da=zc.dx(1)/10;
00531                      double aold=a;
00532                      double x2=0,y2=0;
00533                      while (true)
00534                      {      a=a+da;
00535                             boolean Break=false;
00536                             if ((!started || range) && a>=amax)
00537                             {      a=amax; 
00538                                    Break=true;
00539                             }
00540                             else if ((!started || range) && a<=amin)
00541                             {      a=amin;
00542                                    Break=true;
00543                             }
00544                             else if (started && da>0)
00545                             {      if ((mod(aold-astart)<0 && mod(a-astart)>=0) &&
00546                                           !zc.getConstruction().haveSwitched())
00547                                    {      Break=true;
00548                                           a=astart;
00549                                    }
00550                             }
00551                             aold=a;
00552                             PM.move(x+r*Math.cos(anull+a),y+r*Math.sin(anull+a));
00553                             PM.project(c);
00554                             zc.getConstruction().validate(P,PM);
00555                             if (P.valid())
00556                             {      if (!started)
00557                                    {      zc.getConstruction().shouldSwitch(true);
00558                                           astart=a;
00559                                    }
00560                                    boolean valid=false;
00561                                    if (P instanceof PointObject)
00562                                    {      PointObject p=(PointObject)P;
00563                                           x2=p.getX(); y2=p.getY();
00564                                           valid=true;
00565                                    }
00566                                    else if (P instanceof PrimitiveLineObject)
00567                                    {      PrimitiveLineObject L=(PrimitiveLineObject)P;
00568                                           if (!started)
00569                                           {      X=L.getX(); Y=L.getY(); DX=L.getDX(); DY=L.getDY();
00570                                           }
00571                                           else
00572                                           {      double xx,yy,dx,dy;
00573                                                  xx=L.getX(); yy=L.getY(); dx=L.getDX(); dy=L.getDY();
00574                                                  double det=dx*DY-dy*DX;
00575                                                  if (Math.sqrt(Math.abs(det))>1e-9)
00576                                                  {      double h=(-(X-xx)*DY+DX*(Y-yy))/(-det);
00577                                                         x2=xx+h*dx; y2=yy+h*dy;
00578                                                         valid=true;
00579                                                  }
00580                                                  X=xx; Y=yy; DX=dx; DY=dy;
00581                                           }                                  
00582                                    }
00583                                    double dist=zc.dCenter(x2,y2);
00584                                    boolean different=((int)zc.col(x1)!=(int)zc.col(x2) || 
00585                                           (int)zc.row(y1)!=(int)zc.row(y2));
00586                                    if (valid && different)
00587                                    {      V.addElement(new Coordinates(x2,y2));
00588                                           VPM.addElement(new Coordinates(PM.getX(),PM.getY()));
00589                                    }
00590                                    double dp=Math.abs(x2-x1)+Math.abs(y2-y1);
00591                                    da=updateDA(da,valid,dist,dp,dmin,dmax,zc);
00592                                    x1=x2; y1=y2;
00593                                    started=true;
00594                             }
00595                             else if (started)
00596                             {      V.addElement(new Coordinates(x2,y2));
00597                                    VPM.addElement(new Coordinates(PM.getX(),PM.getY()));
00598                                    da=-da;
00599                             }
00600                             addSecondary(startedO,zc);
00601                             if (Break || System.currentTimeMillis()-time>5000) break;
00602                      }
00603               }
00604               // Running on a line:
00605               else if (O instanceof PrimitiveLineObject)
00606               {      zc.getConstruction().shouldSwitch(false);
00607                      PrimitiveLineObject l=(PrimitiveLineObject)O;
00608                      PM.project(l);
00609                      double lx=l.getX(),ly=l.getY(),ldx=l.getDX(),ldy=l.getDY();
00610                      double amin=0,amax=0,astart=0;
00611                      double dmax=0.5;
00612                      boolean range=false;
00613                      if (l instanceof RayObject)
00614                      {      amin=astart=0;
00615                             amax=Math.PI*0.9999;
00616                             range=true;
00617                      }
00618                      else if (l instanceof SegmentObject)
00619                      {      amin=astart=0; 
00620                             double r=((SegmentObject)l).getLength();
00621                             dmax=r/20;
00622                             amax=Math.atan(r)*2;
00623                             range=true;
00624                      }
00625                      else
00626                      {      amin=astart=-Math.PI*0.99999;
00627                             amax=Math.PI*0.9999;
00628                      }                           
00629                      double a=astart;
00630                      double hd=Math.tan(mod(a)/2);
00631                      PM.move(lx+hd*ldx,ly+hd*ldy);
00632                      PM.project(l);
00633                      zc.getConstruction().validate(P,PM);
00634                      zc.resetSum();
00635                      double x1=0,y1=0;
00636                      boolean started=false;
00637                      if (P.valid())
00638                      {      zc.getConstruction().shouldSwitch(true);
00639                             if (P instanceof PointObject)
00640                             {      PointObject p=(PointObject)P;
00641                                    x1=p.getX(); y1=p.getY();
00642                                    V.addElement(new Coordinates(x1,y1));
00643                                    VPM.addElement(new Coordinates(PM.getX(),PM.getY()));
00644                                    started=true;
00645                             }
00646                             else if (P instanceof PrimitiveLineObject)
00647                             {      PrimitiveLineObject L=(PrimitiveLineObject)P;
00648                                    X=L.getX(); Y=L.getY(); DX=L.getDX(); DY=L.getDY();
00649                                    started=true; 
00650                             }
00651                      }
00652                      boolean startedO[]=new boolean[PMax];
00653                      for (int i=0; i<PN; i++) startedO[i]=false;
00654                      long time=System.currentTimeMillis();
00655                      addSecondary(startedO,zc);
00656                      double dmin=0.001;
00657                      if (da<1e-10 || da>zc.dx(1)) da=zc.dx(1)/10;
00658                      double aold=a;
00659                      double x2=0,y2=0;
00660                      while (true)
00661                      {      a=a+da;
00662                             boolean Break=false;
00663                             if ((!started || range) && a>=amax)
00664                             {      a=amax; 
00665                                    Break=true;
00666                             }
00667                             else if ((!started || range) && a<=amin)
00668                             {      a=amin;
00669                                    Break=true;
00670                             }
00671                             else if (started && da>0)
00672                             {      if ((mod(aold-astart)<0 && mod(a-astart)>=0) &&
00673                                           !zc.getConstruction().haveSwitched())
00674                                    {      Break=true;
00675                                           a=astart;
00676                                    }
00677                             }
00678                             aold=a;
00679                             hd=Math.tan(mod(a)/2);
00680                             PM.move(lx+hd*ldx,ly+hd*ldy);
00681                             PM.project(l);
00682                             zc.getConstruction().validate(P,PM);
00683                             if (P.valid())
00684                             {      if (!started)
00685                                    {      zc.getConstruction().shouldSwitch(true);
00686                                           astart=a;
00687                                    }
00688                                    boolean valid=false;
00689                                    if (P instanceof PointObject)
00690                                    {      PointObject p=(PointObject)P;
00691                                           x2=p.getX(); y2=p.getY();
00692                                           valid=true;
00693                                    }
00694                                    else if (P instanceof PrimitiveLineObject)
00695                                    {      PrimitiveLineObject L=(PrimitiveLineObject)P;
00696                                           if (!started)
00697                                           {      X=L.getX(); Y=L.getY(); DX=L.getDX(); DY=L.getDY();
00698                                           }
00699                                           else
00700                                           {      double xx,yy,dx,dy;
00701                                                  xx=L.getX(); yy=L.getY(); dx=L.getDX(); dy=L.getDY();
00702                                                  double det=dx*DY-dy*DX;
00703                                                  if (Math.sqrt(Math.abs(det))>1e-9)
00704                                                  {      double h=(-(X-xx)*DY+DX*(Y-yy))/(-det);
00705                                                         x2=xx+h*dx; y2=yy+h*dy;
00706                                                         valid=true;
00707                                                  }
00708                                                  X=xx; Y=yy; DX=dx; DY=dy;
00709                                           }                                  
00710                                    }
00711                                    double dist=zc.dCenter(x2,y2);
00712                                    boolean different=((int)zc.col(x1)!=(int)zc.col(x2) || 
00713                                           (int)zc.row(y1)!=(int)zc.row(y2));
00714                                    if (valid && different)
00715                                    {      V.addElement(new Coordinates(x2,y2));
00716                                           VPM.addElement(new Coordinates(PM.getX(),PM.getY()));
00717                                    }
00718                                    double dp=Math.abs(x2-x1)+Math.abs(y2-y1);
00719                                    da=updateDA(da,valid,dist,dp,dmin,dmax,zc);
00720                                    x1=x2; y1=y2;
00721                                    started=true;
00722                             }
00723                             else if (started)
00724                             {      V.addElement(new Coordinates(x2,y2));
00725                                    VPM.addElement(new Coordinates(PM.getX(),PM.getY()));
00726                                    da=-da;
00727                             }
00728                             addSecondary(startedO,zc);
00729                             if (Break || System.currentTimeMillis()-time>5000) break;
00730                      }
00731               }
00732               // Running an expression slider:
00733               else if (O instanceof ExpressionObject)
00734               {      zc.getConstruction().shouldSwitch(false);
00735                      ExpressionObject eo=(ExpressionObject)O;
00736                      if (!eo.isSlider()) return;
00737                      double amin=0,amax=0,astart=0;
00738                      double dmax=0.5;
00739                      boolean range=false;
00740                      amin=astart=0; 
00741                      double r=1;
00742                      dmax=r/20;
00743                      amax=Math.atan(r)*2;
00744                      range=true;
00745                      double a=astart;
00746                      double hd=Math.tan(mod(a)/2);
00747                      eo.setSliderPosition(0);
00748                      zc.getConstruction().validate(P,null);
00749                      zc.resetSum();
00750                      double x1=0,y1=0;
00751                      boolean started=false;
00752                      if (P.valid())
00753                      {      zc.getConstruction().shouldSwitch(true);
00754                             if (P instanceof PointObject)
00755                             {      PointObject p=(PointObject)P;
00756                                    x1=p.getX(); y1=p.getY();
00757                                    V.addElement(new Coordinates(x1,y1));
00758                                    VPM.addElement(new Coordinates(eo.getSliderPosition(),0));
00759                                    started=true;
00760                             }
00761                             else if (P instanceof PrimitiveLineObject)
00762                             {      PrimitiveLineObject L=(PrimitiveLineObject)P;
00763                                    X=L.getX(); Y=L.getY(); DX=L.getDX(); DY=L.getDY();
00764                                    started=true; 
00765                             }
00766                      }
00767                      boolean startedO[]=new boolean[PMax];
00768                      for (int i=0; i<PN; i++) startedO[i]=false;
00769                      long time=System.currentTimeMillis();
00770                      addSecondary(startedO,zc);
00771                      double dmin=0.001;
00772                      if (da<1e-10 || da>zc.dx(1)) da=zc.dx(1)/10;
00773                      double aold=a;
00774                      double x2=0,y2=0;
00775                      while (true)
00776                      {      a=a+da;
00777                             boolean Break=false;
00778                             if ((!started || range) && a>=amax)
00779                             {      a=amax; 
00780                                    Break=true;
00781                             }
00782                             else if ((!started || range) && a<=amin)
00783                             {      a=amin;
00784                                    Break=true;
00785                             }
00786                             else if (started && da>0)
00787                             {      if ((mod(aold-astart)<0 && mod(a-astart)>=0) &&
00788                                           !zc.getConstruction().haveSwitched())
00789                                    {      Break=true;
00790                                           a=astart;
00791                                    }
00792                             }
00793                             aold=a;
00794                             hd=Math.tan(mod(a)/2);
00795                             eo.setSliderPosition(hd);
00796                             zc.getConstruction().validate(P,null);
00797                             if (P.valid())
00798                             {      if (!started)
00799                                    {      zc.getConstruction().shouldSwitch(true);
00800                                           astart=a;
00801                                    }
00802                                    boolean valid=false;
00803                                    if (P instanceof PointObject)
00804                                    {      PointObject p=(PointObject)P;
00805                                           x2=p.getX(); y2=p.getY();
00806                                           valid=true;
00807                                    }
00808                                    else if (P instanceof PrimitiveLineObject)
00809                                    {      PrimitiveLineObject L=(PrimitiveLineObject)P;
00810                                           if (!started)
00811                                           {      X=L.getX(); Y=L.getY(); DX=L.getDX(); DY=L.getDY();
00812                                           }
00813                                           else
00814                                           {      double xx,yy,dx,dy;
00815                                                  xx=L.getX(); yy=L.getY(); dx=L.getDX(); dy=L.getDY();
00816                                                  double det=dx*DY-dy*DX;
00817                                                  if (Math.sqrt(Math.abs(det))>1e-9)
00818                                                  {      double h=(-(X-xx)*DY+DX*(Y-yy))/(-det);
00819                                                         x2=xx+h*dx; y2=yy+h*dy;
00820                                                         valid=true;
00821                                                  }
00822                                                  X=xx; Y=yy; DX=dx; DY=dy;
00823                                           }                                  
00824                                    }
00825                                    double dist=zc.dCenter(x2,y2);
00826                                    boolean different=((int)zc.col(x1)!=(int)zc.col(x2) || 
00827                                           (int)zc.row(y1)!=(int)zc.row(y2));
00828                                    if (valid && different)
00829                                    {      V.addElement(new Coordinates(x2,y2));
00830                                           VPM.addElement(new Coordinates(eo.getSliderPosition(),0));
00831                                    }
00832                                    double dp=Math.abs(x2-x1)+Math.abs(y2-y1);
00833                                    da=updateDA(da,valid,dist,dp,dmin,dmax,zc);
00834                                    x1=x2; y1=y2;
00835                                    started=true;
00836                             }
00837                             else if (started)
00838                             {      V.addElement(new Coordinates(x2,y2));
00839                                    VPM.addElement(new Coordinates(eo.getSliderPosition(),0));
00840                                    da=-da;
00841                             }
00842                             addSecondary(startedO,zc);
00843                             if (Break || System.currentTimeMillis()-time>5000) break;
00844                      }
00845               }
00846        }
00847        
00848        public void addSecondary (boolean startedO[], ZirkelCanvas zc)
00849        {      for (int i=0; i<PN; i++)
00850               {      if (PM!=null) zc.getConstruction().validate(PO[i],PM);
00851                      else zc.getConstruction().validate(PO[i],O);
00852                      if (!PO[i].valid()) continue;
00853                      if (PO[i] instanceof PointObject)
00854                      {      PointObject p=(PointObject)PO[i];
00855                             VO[i].addElement(new Coordinates(p.getX(),p.getY()));
00856                      }
00857                      else if (PO[i] instanceof PrimitiveLineObject)
00858                      {      PrimitiveLineObject L=(PrimitiveLineObject)PO[i];
00859                             if (!startedO[i])
00860                             {      XO[i]=L.getX(); YO[i]=L.getY(); 
00861                                    DXO[i]=L.getDX(); DYO[i]=L.getDY();
00862                                    startedO[i]=true;
00863                             }
00864                             else
00865                             {      double xx,yy,dx,dy;
00866                                    xx=L.getX(); yy=L.getY();
00867                                    dx=L.getDX(); dy=L.getDY();
00868                                    double det=dx*DYO[i]-dy*DXO[i];
00869                                    if (Math.sqrt(Math.abs(det))>1e-9)
00870                                    {      double h=(-(XO[i]-xx)*DYO[i]+
00871                                                  DXO[i]*(YO[i]-yy))/(-det);
00872                                           XO[i]=xx; YO[i]=yy; DXO[i]=dx; DYO[i]=dy;
00873                                           VO[i].addElement(new Coordinates(xx+h*dx,yy+h*dy));                                               
00874                                    }
00875                             }
00876                      }
00877               }
00878        }
00879        
00880        public double StepSize=5;
00881        
00882        public double updateDA (double da, boolean valid, double dist, double dp, 
00883                      double dmin, double dmax,
00884                      ZirkelCanvas zc)
00885        {      if (V.size()>0 && valid)
00886               {      if (dist<1.2)
00887                      {      if (dp>zc.dx(StepSize)) da/=2;
00888                             else if (dp<zc.dx(StepSize/2)) da*=2;
00889                             if (da>0 && da<dmin) da=dmin;
00890                             else if (da<0 && da>-dmin) da=-dmin;
00891                             if (da>dmax) da=dmax;
00892                             else if (da<-dmax) da=-dmax;
00893                      }
00894                      else
00895                      {      if (dp>zc.dx(StepSize*10)) da/=2;
00896                             else if (dp<zc.dx(StepSize*5)) da*=2;
00897                             if (da>0 && da<dmin) da=dmin;
00898                             else if (da<0 && da>-dmin) da=-dmin;
00899                             if (da>dmax) da=dmax;
00900                             else if (da<-dmax) da=-dmax;
00901                      }
00902               }
00903               return da;
00904        }
00905        
00906        public void increaseOmit ()
00907        {      Omit++;
00908        }
00909        
00910        public void decreaseOmit ()
00911        {      if (Omit>1) Omit--;
00912        }
00913        
00914        public void setOmit (int f)
00915        {      Omit=f+1;
00916        }
00917        
00918        public boolean isComplete ()
00919        {      return !(P==null || O==null || 
00920                      (PM==null && !(O instanceof ExpressionObject && ((ExpressionObject)O).isSlider())));
00921        }
00922        
00923        public void keep (ZirkelCanvas zc)
00924        {      if (!isComplete()) return;
00925               TrackObject t=new TrackObject(zc.getConstruction(),
00926                      P,PO,PN,O,PM);
00927               zc.addObject(t);
00928               t.setDefaults();
00929               reset(zc);
00930               t.compute(zc);
00931               zc.validate();
00932        }
00933        
00934        public String getTag () { return "Track"; }
00935        
00936        public boolean construct (XmlTree tree, Construction c)
00937               throws ConstructionException
00938        {      if (!testTree(tree,"Track")) return false;
00939               XmlTag tag=tree.getTag();
00940               if (!tag.hasParam("on") || !tag.hasParam("track"))
00941                      throw new ConstructionException("Track parameters missing!");
00942               else try
00943               {      PointObject pm=null;
00944                      try
00945                      {      pm=(PointObject)c.find(tag.getValue("point"));
00946                      }
00947                      catch (Exception ex) {}
00948                      ConstructionObject o=c.find(tag.getValue("on"));
00949                      if (pm==null && !(o instanceof ExpressionObject)) throw new ConstructionException("");
00950                      ConstructionObject p=c.find(tag.getValue("track"));
00951                      ConstructionObject po[]=new ConstructionObject[PMax];
00952                      int pn=0;
00953                      for (pn=0; pn<PMax; pn++)
00954                      {      if (!tag.hasParam("track"+pn)) break;
00955                             po[pn]=c.find(tag.getValue("track"+pn));
00956                             if (!(po[pn] instanceof PointObject || 
00957                                           po[pn] instanceof PrimitiveLineObject))
00958                                    throw new ConstructionException("Track parameters wrong!");
00959                      }
00960                      if (p==null || o==null)
00961                             throw new ConstructionException("Track parameters wrong!");
00962                      if (!(p instanceof PointObject || p instanceof PrimitiveLineObject))
00963                             throw new ConstructionException("Track parameters wrong!");
00964                      if (!(o instanceof PrimitiveCircleObject || 
00965                                    o instanceof PrimitiveLineObject || o instanceof ExpressionObject))
00966                             throw new ConstructionException("Track parameters wrong!");
00967                      TrackObject tr=new TrackObject(c,p,po,pn,o,pm);
00968                      if (tag.hasParam("filled")) tr.setFilled(true);
00969                      if (tag.hasParam("fixed")) tr.setFixed(true);
00970                      if (tag.hasParam("dmin"))
00971                      {      try
00972                             {      tr.setDMin(new Double(tag.getValue("dmin")).doubleValue());
00973                             }
00974                             catch (Exception e) 
00975                             {      throw new ConstructionException("Track parameters wrong!");
00976                             }
00977                      }
00978                      if (tag.hasTrueParam("discrete")) tr.setDiscrete(true);
00979                      setType(tag,tr);
00980                      setName(tag,tr);
00981                      set(tree,tr);
00982                      c.add(tr);
00983                      setConditionals(tree,c,tr);
00984                      return true;
00985               }
00986               catch (ConstructionException e)
00987               {      // e.printStackTrace();
00988                      throw e;
00989               }
00990               catch (Exception e)
00991               {      // e.printStackTrace();
00992                      throw new ConstructionException("Track Parameters wrong!");
00993               }
00994        }
00995        
00996        public void setType (XmlTag tag, TrackObject p)
00997        {      if (tag.hasParam("shape"))
00998               {      String s=tag.getValue("shape");
00999                      if (s.equals("square")) p.setType(0);
01000                      if (s.equals("diamond")) p.setType(1);
01001                      if (s.equals("circle")) p.setType(2);
01002                      if (s.equals("dot")) p.setType(3);
01003                      if (s.equals("cross")) p.setType(4);
01004                      if (s.equals("dcross")) p.setType(5);
01005               }
01006        }
01007        
01008 }