Back to index

wims  3.65+svn20090927
RayObject.java
Go to the documentation of this file.
00001 package rene.zirkel.objects;
00002 
00003 // file: SegmentObject.java
00004 
00005 import rene.util.xml.XmlWriter;
00006 import rene.zirkel.Zirkel;
00007 import rene.zirkel.ZirkelCanvas;
00008 import rene.zirkel.construction.Construction;
00009 import rene.zirkel.construction.Count;
00010 import rene.zirkel.graphics.MyGraphics;
00011 import rene.zirkel.graphics.MyGraphics13;
00012 import rene.zirkel.structures.Coordinates;
00013 
00014 public class RayObject extends TwoPointLineObject
00015 {      static Count N=new Count();
00016        public RayObject (Construction c, PointObject p1, PointObject p2)
00017        {      super(c,p1,p2);
00018               validate();
00019               updateText();
00020        }
00021        public String getTag () { return "Ray"; }
00022        public int getN () { return N.next(); }
00023        
00024        public void updateText ()
00025        {      setText(text2(Zirkel.name("text.ray"),P1.getName(),P2.getName()));
00026        }
00027        public void validate ()
00028        {      if (!P1.valid() || !P2.valid()) { Valid=false; return; }
00029               else
00030               {      Valid=true;
00031                      X1=P1.getX(); Y1=P1.getY();
00032                      X2=P2.getX(); Y2=P2.getY();
00033                      // compute normalized vector in the direction of the line:
00034                      DX=X2-X1; DY=Y2-Y1; 
00035                      R=Math.sqrt(DX*DX+DY*DY);
00036                      if (R<1e-10) { Valid=false; return; }
00037                      DX/=R; DY/=R;
00038               }
00039        }
00040        
00041        public void paint (MyGraphics g, ZirkelCanvas zc)
00042        {      if (!Valid || mustHide(zc)) return;
00043               //compute middle of the screen:
00044               double xm=(zc.minX()+zc.maxX())/2,ym=(zc.minY()+zc.maxY())/2;
00045               // compute distance from middle to line:
00046               double d=(xm-X1)*DY-(ym-Y1)*DX;
00047               // compute point with minimal distance
00048               double x=xm-d*DY,y=ym+d*DX;
00049               // compute size of the screen
00050               double a=Math.max(zc.maxX()-zc.minX(),zc.maxY()-zc.minY());
00051               if (Math.abs(d)>a) return;
00052               // compute distance from closest point to source
00053               double b=(x-X1)*DX+(y-Y1)*DY;
00054               // compute the two visible endpoints
00055               k1=b-a; k2=b+a; k12valid=true;
00056               if (k1<0) k1=0;
00057               if (k1>=k2) return;
00058               if (Partial && !zc.showHidden() && Dep!=null)
00059               {      double dd=(zc.maxX()-zc.minX())/20;
00060                      double dmin=-dd,dmax=R+dd;
00061                      for (int i=0; i<NDep; i++)
00062                      {      if (!Dep[i].valid() || Dep[i].mustHide(zc)) continue;
00063                             double s=project(Dep[i].getX(),Dep[i].getY());
00064                             if (s-dd<dmin) dmin=s-dd;
00065                             else if (s+dd>dmax) dmax=s+dd;
00066                      }
00067                      if (k1<dmin) k1=dmin;
00068                      if (k2>dmax) k2=dmax;
00069               }
00070               double c1=zc.col(X1+k1*DX),c2=zc.col(X1+k2*DX),
00071                      r1=zc.row(Y1+k1*DY),r2=zc.row(Y1+k2*DY);
00072               // paint:
00073               if (isStrongSelected() && g instanceof MyGraphics13)
00074               {      ((MyGraphics13)g).drawMarkerLine(c1,r1,c2,r2);
00075               }
00076               g.setColor(this);
00077               if (visible(zc)) g.drawLine(c1,r1,c2,r2,this);
00078               String s=getDisplayText();
00079               if (!s.equals(""))
00080               {      g.setLabelColor(this);
00081                      DisplaysText=true;
00082                      double c=-b+a/5;
00083                      if (c<-a/5) c=-a/5;
00084                      else if (c>a/5) c=a/5;
00085                      if (c<-b+a/10) c=-b+a/10;
00086                      if (KeepClose)
00087                      {      double side=(YcOffset<0)?1:-1;
00088                             drawLabel(g,s,zc,X1+XcOffset*(X2-X1),Y1+XcOffset*(Y2-Y1),
00089                                    side*DX,side*DY,0,0);
00090                      }
00091                      else
00092                             drawLabel(g,s,zc,x+c*DX,y+c*DY,DX,DY,XcOffset,YcOffset);
00093               }             
00094        }
00095        
00096        public boolean canKeepClose ()
00097        {      return true;
00098        }
00099        
00100        public void setKeepClose (double x, double y)
00101        {      KeepClose=true;
00102               XcOffset=(x-X1)/R*DX+(y-Y1)/R*DY;
00103               YcOffset=(x-X1)/R*DY-(y-Y1)/R*DX;
00104        }
00105 
00106        public String getDisplayValue ()
00107        {      return ""+round(R,ZirkelCanvas.LengthsFactor);
00108        }
00109 
00110        public boolean nearto (int c, int r, ZirkelCanvas zc)
00111        {      if (!displays(zc)) return false;
00112               //compute point at c,r
00113               double x=zc.x(c),y=zc.y(r);
00114               // compute distance from line
00115               double d=(x-X1)*DY-(y-Y1)*DX;
00116               // compute offset
00117               double o=(x-X1)*DX+(y-Y1)*DY,o1=(X2-X1)*DX+(Y2-Y1)*DY;
00118               if (o1>0)
00119               {      if (o<0) d=Math.sqrt((x-X1)*(x-X1)+(y-Y1)*(y-Y1));
00120               }
00121               else
00122               {      if (o>0) d=Math.sqrt((x-X1)*(x-X1)+(y-Y1)*(y-Y1));
00123               }
00124               // test, if on visible part
00125               double s=project(x,y);
00126               if (s<k1 || s>k2) return false;
00127               // scale in screen coordinates
00128               Value=Math.abs(zc.col(zc.minX()+d)-zc.col(zc.minX()));
00129               return Value<zc.selectionSize()*2;
00130        }
00131 
00132        public void printArgs (XmlWriter xml)
00133        {      xml.printArg("from",P1.getName());
00134               xml.printArg("to",P2.getName());
00135               super.printArgs(xml);
00136        }
00137 
00138        public boolean contains (double x, double y)
00139        {      double a=(x-X1)*DX+(y-Y1)*DY;
00140               if (a<1e-9) return false;
00141               return true;
00142        }
00143        public double project (double x, double y)
00144        {      double h=super.project(x,y);
00145               if (h<0) return 0;
00146               return h;
00147        }
00148 
00149        public boolean equals (ConstructionObject o)
00150        {      if (!(o instanceof RayObject) || !o.valid()) return false;
00151               RayObject l=(RayObject)o;
00152               return equals(X1,l.X1) && equals(Y1,l.Y1) &&
00153                      equals(DX,l.DX) && equals(DY,l.DY);
00154        }
00155 
00156        public static Coordinates intersect 
00157               (PrimitiveLineObject l1, PrimitiveLineObject l2)
00158        // compute the intersection coordinates of two lines
00159        {      double det=-l1.DX*l2.DY+l1.DY*l2.DX;
00160               if (Math.abs(det)<1e-10) return null;
00161               double a=(-(l2.X1-l1.X1)*l2.DY+(l2.Y1-l1.Y1)*l2.DX)/det;
00162               return new Coordinates(l1.X1+a*l1.DX,l1.Y1+a*l1.DY);
00163        }
00164 
00165        public static Coordinates intersect
00166               (PrimitiveLineObject l, PrimitiveCircleObject c)
00167        // compute the intersection coordinates of a line with a circle
00168        {      double x=c.getX(),y=c.getY(),r=c.getR();
00169               double d=(x-l.X1)*l.DY-(y-l.Y1)*l.DX;
00170               if (Math.abs(d)>r+1e-10) return null;
00171               x-=d*l.DY; y+=d*l.DX;
00172               double h=r*r-d*d;
00173               if (h>0) h=Math.sqrt(h);
00174               else h=0;
00175               return new Coordinates(x+h*l.DX,y+h*l.DY,x-h*l.DX,y-h*l.DY);
00176        }
00177 
00178 }