Back to index

wims  3.65+svn20090927
PrimitiveCircleObject.java
Go to the documentation of this file.
00001 package rene.zirkel.objects;
00002 
00003 // file: PrimitiveCircleObject.java
00004 
00005 import java.util.Enumeration;
00006 
00007 import rene.gui.Global;
00008 import rene.util.xml.XmlWriter;
00009 import rene.zirkel.*;
00010 import rene.zirkel.construction.*;
00011 import rene.zirkel.dialogs.CircleEditDialog;
00012 import rene.zirkel.dialogs.EditConditionals;
00013 import rene.zirkel.dialogs.ObjectEditDialog;
00014 import rene.zirkel.graphics.*;
00015 import rene.zirkel.structures.Coordinates;
00016 import rene.zirkel.expression.*;
00017 
00018 public class PrimitiveCircleObject extends ConstructionObject
00019        implements PointonObject, InsideObject
00020 {      protected double X,Y,R;
00021        static Count N=new Count();
00022        boolean Partial=false;
00023        PointObject Dep[]; // array for points, depending on the circle for partial display
00024        int NDep; // number of points in Dep
00025        PointObject M; // The midpoint
00026        boolean Filled=false;
00027        Expression Start=null,End=null; // drawing range
00028        double A1,A2,A;
00029        boolean Arc=true;
00030 
00031        public PrimitiveCircleObject (Construction c, PointObject p)
00032        {      super(c);
00033               setColor(ColorIndex);
00034               M=p;
00035               Unit=Global.getParameter("unit.length","");
00036        }
00037 
00038        public String getTag () { return "Circle"; }
00039        public int getN () { return N.next(); }
00040        
00041        public void paint (MyGraphics g, ZirkelCanvas zc)
00042        {      if (!Valid  || mustHide(zc)) return;
00043               double c1=zc.col(X-R),c2=zc.col(X+R),
00044                      r1=zc.row(Y+R),r2=zc.row(Y-R),
00045                      r=(r2-r1)/2;
00046               double ssa=1/Math.sqrt(2),ssb=-ssa;
00047               // paint:
00048               if (!zc.showHidden() && Dep!=null && NDep>0 && Partial && 
00049                             !hasRange()) // partial display
00050               {      for (int i=0; i<NDep; i++)
00051                      {      if (!Dep[i].valid() || Dep[i].mustHide(zc)) continue;
00052                             double A=Math.atan2(Dep[i].getY()-Y,Dep[i].getX()-X);
00053                             if (A<0) A+=2*Math.PI;
00054                             double a=A/Math.PI*180;
00055                             if (visible(zc))
00056                             {      if (isStrongSelected() && g instanceof MyGraphics13)
00057                                    {      ((MyGraphics13)g).drawMarkerArc((c1+c2)/2.0,(r1+r2)/2.0,r,a-10,20);
00058                                    }
00059                                    g.setColor(this);
00060                                    g.drawCircleArc(c1+r,r1+r,r,a-10,20,this);
00061                             }
00062                             if (i==0)
00063                             {      String s=getDisplayText();
00064                                    if (!s.equals(""))
00065                                    {      g.setLabelColor(this);
00066                                           DisplaysText=true;
00067                                           double sx=Math.cos(A-0.1);
00068                                           double sy=Math.sin(A-0.1);
00069                                           drawLabel(g,s,zc,X+sx*R,Y+sy*R,sy,-sx,XcOffset,YcOffset);
00070                                    }
00071                             }
00072                      }
00073               }
00074               else
00075               {      if (hasRange()) // arc display
00076                      {      computeA1A2();
00077                             if (visible(zc))
00078                             {      if (isStrongSelected() && g instanceof MyGraphics13)
00079                                    {      ((MyGraphics13)g).drawMarkerArc((c1+c2)/2.0,(r1+r2)/2.0,
00080                                                  r,A1/Math.PI*180,A/Math.PI*180);
00081                                    }
00082                                    g.setColor(this);
00083                                    if (Filled)
00084                                    {      g.fillArc(c1,r1,c2-c1,r2-r1,
00085                                                  A1/Math.PI*180,A/Math.PI*180,
00086                                                  Selected||(getColorType()!=THIN),
00087                                                  getColorType()!=THICK,Arc,this);
00088                                    }
00089                                    else if (visible(zc)) 
00090                                           g.drawCircleArc(c1+r,r1+r,r,
00091                                                  A1/Math.PI*180,A/Math.PI*180,this);
00092                             }
00093                             ssa=Math.cos(A1+A/2);
00094                             ssb=Math.sin(A1+A/2);
00095                      }
00096                      else if (Filled)
00097                      {      if (visible(zc))
00098                             {      if (isStrongSelected() && g instanceof MyGraphics13)
00099                                    {      ((MyGraphics13)g).drawMarkerArc((c1+c2)/2.0,(r1+r2)/2.0,r,0,360);
00100                                    }
00101                                    g.setColor(this);
00102                                    g.fillOval(c1,r1,c2-c1,r2-r1,
00103                                           Indicated||Selected||(getColorType()==NORMAL),getColorType()!=THICK,
00104                                                  this);
00105                             }
00106                      }
00107                      else // full unfilled display
00108                      {      if (visible(zc)) 
00109                             {      if (isStrongSelected() && g instanceof MyGraphics13)
00110                                    {      ((MyGraphics13)g).drawMarkerArc((c1+c2)/2.0,(r1+r2)/2.0,r,0,360);
00111                                    }
00112                                    g.setColor(this);
00113                                    g.drawCircle(c1+r,r1+r,r,this);
00114                             }
00115                      }
00116                      String s=getDisplayText();
00117                      if (!s.equals(""))
00118                      {      g.setLabelColor(this);
00119                             DisplaysText=true;
00120                             drawLabel(g,s,zc,X+ssa*R,Y+ssb*R,-ssa,ssb,XcOffset,YcOffset);
00121                      }             
00122               }
00123        }
00124        
00125        public String getDisplayValue ()
00126        {      return ""+round(R,ZirkelCanvas.LengthsFactor);
00127        }
00128        
00129        public String getEquation ()
00130        {      return "(x"+helpDisplayNumber(false,-X)+")^2+"
00131               +"(y"+helpDisplayNumber(false,-Y)+")^2="
00132               +helpDisplayNumber(true,R*R);
00133        }
00134 
00135        public boolean nearto (int c, int r, ZirkelCanvas zc)
00136        {      return nearto(c,r,false,zc);
00137        }
00138        
00139        public boolean nearto (int c, int r, boolean ignorefill, ZirkelCanvas zc)
00140        {      if (!displays(zc)) return false;
00141               double x=zc.x(c)-X,y=zc.y(r)-Y;
00142               if (!ignorefill && Filled)
00143               {      double d=Math.sqrt(x*x+y*y);
00144                      if (d<R) Value=0;
00145                      return d<R;
00146               }
00147               else if (hasRange())
00148               {      computeA1A2();
00149                      double a=Math.atan2(y,x);
00150                      if (a<0) a+=2*Math.PI;
00151                      a-=A1;
00152                      if (a<0) a+=2*Math.PI;
00153                      double d=Math.abs(Math.sqrt(x*x+y*y)-R);
00154                      if (a<=A+0.01)
00155                             Value=Math.abs(zc.col(zc.minX()+d)-zc.col(zc.minX()));
00156                      return Value<zc.selectionSize() && a<=A+0.01;
00157               }
00158               // partial display:
00159               else if (!zc.showHidden() && NDep>0 && Partial)
00160               {      double d=Math.abs(Math.sqrt(x*x+y*y)-R);
00161                      Value=Math.abs(zc.col(zc.minX()+d)-zc.col(zc.minX()));
00162                      if (Math.abs(zc.col(zc.minX()+d)-zc.col(zc.minX()))>=
00163                             zc.selectionSize()) return false;
00164                      d=Math.PI/18;
00165                      double a=Math.atan2(y,x);
00166                      if (a<0) a+=2*Math.PI;
00167                      for (int i=0; i<NDep; i++)
00168                      {      if (!Dep[i].valid() || Dep[i].mustHide(zc)) continue;
00169                             double A=Math.atan2(Dep[i].getY()-Y,Dep[i].getX()-X);
00170                             if (A<0) A+=2*Math.PI;
00171                             double h=a-A;
00172                             if (h>2*Math.PI) h-=2*Math.PI;
00173                             if (h<-2*Math.PI) h+=2*Math.PI;
00174                             if (Math.abs(h)<d) return true;
00175                      }
00176                      return false;
00177               }
00178               else   
00179               {      double d=Math.abs(Math.sqrt(x*x+y*y)-R);
00180                      Value=Math.abs(zc.col(zc.minX()+d)-zc.col(zc.minX()));
00181                      return Math.abs(zc.col(zc.minX()+d)-zc.col(zc.minX()))<
00182                             zc.selectionSize();
00183               }
00184        }
00185        
00186        public boolean onlynearto (int c, int r, ZirkelCanvas zc)
00187        {      if (R<zc.dx(3*(int)zc.pointSize())) return true;
00188               if (hasRange())
00189               {      double A1=Math.atan2(getStart().getY()-Y,getStart().getX()-X);
00190                      if (A1<0) A1+=2*Math.PI;
00191                      double A2=Math.atan2(getEnd().getY()-Y,getEnd().getX()-X);
00192                      if (A2<0) A2+=2*Math.PI;
00193                      double A=A2-A1;
00194                      if (A>=2*Math.PI) A-=2*Math.PI;
00195                      if (A<0) A+=2*Math.PI;
00196                      if (!Obtuse && A>Math.PI)
00197                      {      A1=A2;
00198                             A=2*Math.PI-A;
00199                             A2=A1+A;
00200                      }
00201                      if (A*R<zc.dx(6*(int)zc.pointSize())) return true;
00202               }
00203               return false;
00204        }
00205 
00206        public double getX () { return X; }
00207        public double getY () { return Y; }
00208        public double getR () { return R; }
00209 
00210        public static Coordinates intersect (PrimitiveCircleObject c1, 
00211               PrimitiveCircleObject c2)
00212        {      double dx=c2.X-c1.X,dy=c2.Y-c1.Y,r=Math.sqrt(dx*dx+dy*dy);
00213               if (r>c1.R+c2.R+1e-10) return null;
00214               if (r<=1e-10) return new Coordinates(c1.X,c1.Y,c1.X,c1.Y);
00215               double l=(r*r+c1.R*c1.R-c2.R*c2.R)/(2*r);
00216               dx/=r; dy/=r;
00217               double x=c1.X+l*dx,y=c1.Y+l*dy,h=c1.R*c1.R-l*l;
00218               if (h<-1e-10) return null;
00219               if (h<0) h=0;
00220               else h=Math.sqrt(h);
00221               return new Coordinates(x+h*dy,y-h*dx,x-h*dy,y+h*dx);
00222        }
00223 
00224        public void edit (ZirkelCanvas zc)
00225        {      ObjectEditDialog d=new CircleEditDialog(zc.getFrame(),this,zc);
00226               d.setVisible(true);
00227               zc.getConstruction().updateCircleDep(); 
00228               zc.validate(); zc.repaint();
00229               if (d.wantsMore())
00230               {      new EditConditionals(zc.getFrame(),this);
00231                      validate();
00232               }
00233        }
00234 
00235        public boolean equals (ConstructionObject o)
00236        {      if (!(o instanceof PrimitiveCircleObject) || !o.valid())
00237                      return false;
00238               PrimitiveCircleObject l=(PrimitiveCircleObject)o;
00239               return equals(X,l.X) && equals(Y,l.Y) && equals(R,l.R);
00240        }
00241 
00242        public void setPartial (boolean flag)
00243        {      if (flag==Partial) return;
00244               Partial=flag;
00245               if (flag) // depending objects no longer needed
00246               {      Dep=new PointObject[16];
00247                      NDep=0;
00248               }
00249               else Dep=null;
00250        }
00251        
00257        public void addDep (PointObject p)
00258        {      if (!Partial || hasRange() || 
00259                      Dep==null || NDep>=Dep.length) return;
00260               Dep[NDep++]=p;
00261        } 
00262        
00263        public void clearCircleDep ()
00264        {      NDep=0;
00265        }
00266        
00267        public boolean isPartial ()
00268        {      return Partial;
00269        }
00270        
00271        public void printArgs (XmlWriter xml)
00272        {      xml.printArg("midpoint",M.getName());
00273               if (Partial) xml.printArg("partial","true");
00274               if (Filled) xml.printArg("filled","true");
00275               if (getStart()!=null) xml.printArg("start",getStart().getName());
00276               if (getEnd()!=null) xml.printArg("end",getEnd().getName());
00277               if (!Obtuse) xml.printArg("acute","true");
00278               if (!Arc) xml.printArg("chord","true");
00279               super.printArgs(xml);
00280        }
00281        
00285        public ConstructionObject copy ()
00286        {      PrimitiveCircleObject o=
00287                      (PrimitiveCircleObject)super.copy();
00288               if (o.Partial)
00289               {      o.Dep=new PointObject[16];
00290                      o.NDep=0;
00291               }
00292               else o.Dep=null;
00293               return o;
00294        }
00295 
00296        public void setDefaults ()
00297        {      super.setDefaults();
00298               setPartial(Cn.Partial);
00299        }
00300 
00306        public Enumeration depending ()
00307        {      super.depending();
00308               DL.add(M);
00309               return DL.elements();
00310        }
00311 
00315        public Enumeration secondaryParams ()
00316        {      DL.reset();
00317               return depset(M);
00318        }
00319 
00320        public void toggleHidden ()
00321        {      if (Hidden)
00322               {      Hidden=false;
00323               }
00324               else
00325               {      if (Partial)
00326                      {      setPartial(false);
00327                             Hidden=true;
00328                      }
00329                      else setPartial(true);
00330               }
00331        }
00332 
00333        public PointObject getP1 ()
00334        {      return M;
00335        }
00336        
00337        public void setFilled (boolean flag)
00338        {      Filled=flag;
00339        }
00340        public boolean isFilled ()
00341        {      return Filled;
00342        }
00343        public boolean isFilledForSelect ()
00344        {      return Filled;
00345        }
00346 
00347        public void translate ()
00348        {      M=(PointObject)M.getTranslation();
00349               if (hasRange())
00350               {      setRange(getStart().getName(),getEnd().getName());
00351                      Start.translate();
00352                      End.translate();
00353               }
00354        }      
00355 
00356        public boolean setRange (String s1, String s2)
00357        {      try
00358               {      Start=new Expression("@\""+s1+"\"",Cn,this);
00359                      End=new Expression("@\""+s2+"\"",Cn,this);
00360                      return hasRange();
00361               }
00362               catch (Exception e) { Start=End=null; }
00363               return false;
00364        }
00365 
00366        public PointObject getStart ()
00367        {      return getPointObject(Start);
00368        }
00369        public PointObject getEnd ()
00370        {      return getPointObject(End);
00371        }
00372        
00373        public String getStartString ()
00374        {      String s="";
00375               if (Start!=null) s=Start.toString();
00376               if (s.startsWith("@")) s=s.substring(1);
00377               return s;
00378        }
00379        public String getEndString ()
00380        {      String s="";
00381               if (End!=null) s=End.toString();
00382               if (s.startsWith("@")) s=s.substring(1);
00383               return s;
00384        }
00385        
00386        public double getA1 () { return A1; }
00387        public double getA2 () { return A2; }
00388        
00389        public boolean hasRange ()
00390        {      return getStart()!=null && getEnd()!=null;
00391        }
00392        
00393        public void clearRange ()
00394        {      Start=End=null;
00395        }
00396        
00397        public boolean maybeTransparent ()
00398        {      return true;
00399        }
00400        
00401        public boolean locallyLike (ConstructionObject o)
00402        {      if (!(o instanceof PrimitiveCircleObject)) return false;
00403               return (equals(X,((PrimitiveCircleObject)o).X) &&
00404                      equals(Y,((PrimitiveCircleObject)o).Y) &&
00405                      equals(R,((PrimitiveCircleObject)o).R));
00406        }
00407 
00408        public boolean getArc ()
00409        {      return Arc;
00410        }
00411        public void setArc (boolean flag)
00412        {      Arc=flag;
00413        }
00414 
00415        public void computeA1A2 ()
00416        {      A1=Math.atan2(getStart().getY()-Y,getStart().getX()-X);
00417               if (A1<0) A1+=2*Math.PI;
00418               A2=Math.atan2(getEnd().getY()-Y,getEnd().getX()-X);
00419               if (A2<0) A2+=2*Math.PI;
00420               if (A2<A1) A2+=2*Math.PI;
00421               A=A2-A1;
00422               if (!Obtuse && A>Math.PI+1e-10)
00423               {      A1=A2;
00424                      if (A1>=2*Math.PI) A1-=2*Math.PI;
00425                      A=2*Math.PI-A;
00426                      A2=A1+A;
00427               }
00428               if (Partial)
00429               {      A1-=10/180.0*Math.PI; A+=20/180.0*Math.PI;
00430               }
00431        }
00432 
00437        public boolean contains (double x, double y)
00438        {      if (!hasRange()) return true;
00439               computeA1A2();
00440               double a=Math.atan2(y-Y,x-X);
00441               if (a<0) a+=2*Math.PI;
00442               double d=a-A1;
00443               if (d<0) d+=2*Math.PI;
00444               return d<A+0.0001;
00445        }
00446 
00447        public void project (PointObject P) 
00448        {      double dx=P.getX()-getX(),dy=P.getY()-getY();
00449               double r=Math.sqrt(dx*dx+dy*dy);
00450               double X=0,Y=0;
00451               if (r<1e-10)
00452               {      X=getX()+getR(); Y=getY(); 
00453               }
00454               else
00455               {      X=getX()+dx/r*getR(); Y=getY()+dy/r*getR();
00456               }
00457               double Alpha=Math.atan2(P.getY()-getY(),P.getX()-getX());
00458               if (hasRange() && getStart()!=P && getEnd()!=P)
00459               {      if (Alpha<0) Alpha+=2*Math.PI;
00460                      computeA1A2();
00461                      double a1=getA1(),a2=getA2();
00462                      if (Alpha<a1) Alpha+=2*Math.PI;
00463                      if (Alpha>a2)
00464                      {      if (2*Math.PI-(Alpha-a1) < Alpha-a2) Alpha=a1;
00465                             else Alpha=a2;
00466                      }
00467                      X=getX()+getR()*Math.cos(Alpha);
00468                      Y=getY()+getR()*Math.sin(Alpha);   
00469               }
00470               P.setXY(X,Y);
00471               P.setA(Alpha);
00472        }
00473        
00474        public void project (PointObject P, double alpha) 
00475        {      double dx=P.getX()-getX(),dy=P.getY()-getY();
00476               double r=Math.sqrt(dx*dx+dy*dy);
00477               double X=0,Y=0;
00478               if (r<1e-10)
00479               {      X=getX()+getR(); Y=getY(); 
00480               }
00481               else
00482               {      X=getX()+dx/r*getR(); Y=getY()+dy/r*getR();
00483               }
00484               if (hasRange() && getStart()!=P && getEnd()!=P)
00485               {      double Alpha=P.getAlpha();
00486                      if (Alpha<0) Alpha+=2*Math.PI;
00487                      if (Alpha>=2*Math.PI) Alpha-=2*Math.PI;
00488                      computeA1A2();
00489                      double a1=getA1(),a2=getA2();
00490                      if (Alpha<a1) Alpha+=2*Math.PI;
00491                      if (Alpha>a2)
00492                      {      if (2*Math.PI-(Alpha-a1) < Alpha-a2) Alpha=a1;
00493                             else Alpha=a2;
00494                      }
00495                      P.setA(Alpha);
00496                      X=getX()+getR()*Math.cos(Alpha);
00497                      Y=getY()+getR()*Math.sin(Alpha);
00498               }
00499               else
00500               {      X=getX()+getR()*Math.cos(alpha);
00501                      Y=getY()+getR()*Math.sin(alpha);
00502               }
00503               P.setXY(X,Y);
00504        }
00505 
00506        public double containsInside (PointObject P) 
00507        {      double dx=P.getX()-X,dy=P.getY()-Y;
00508               double r=Math.sqrt(dx*dx+dy*dy);
00509               if (r<R*(1-1e-10)) return 1;
00510               if (r<R*(1+1e-10)) return 0.5;
00511               return 0;
00512        }
00513 
00514        public boolean keepInside(PointObject P) 
00515        {      double dx=P.getX()-X,dy=P.getY()-Y;
00516               double r=Math.sqrt(dx*dx+dy*dy);
00517               double f=1;
00518               if (Filled && ColorType==THIN) f=0.9999;
00519               if (r<R*f || R<1e-10) return true;
00520               P.setXY(X+dx/r*(R*f),Y+dy/r*(R*f));
00521               return false;
00522        }
00523 
00524        public boolean canInteresectWith(ConstructionObject o) 
00525        {
00526               return true;
00527        }
00528 
00529 }