Back to index

wims  3.65+svn20090927
AngleObject.java
Go to the documentation of this file.
00001 package rene.zirkel.objects;
00002 
00003 // file: Circle3Object.java
00004 
00005 import java.awt.*;
00006 import java.awt.event.*;
00007 import java.util.*;
00008 
00009 import rene.gui.*;
00010 import rene.dialogs.*;
00011 import rene.util.xml.*;
00012 import rene.zirkel.*;
00013 import rene.zirkel.construction.*;
00014 import rene.zirkel.dialogs.*;
00015 import rene.zirkel.expression.*;
00016 import rene.zirkel.graphics.*;
00017 
00018 class AngleEditDialog extends ObjectEditDialog
00019        implements IconBarListener
00020 {      TextField Length;
00021        Checkbox Fixed;
00022        IconBar SizeIB;
00023        
00024        public AngleEditDialog (Frame f, AngleObject o)
00025        {      super(f,Zirkel.name("edit.angle.title"),o,"angle");
00026        }
00027        
00028        public void addFirst (Panel P)
00029        {      AngleObject o=(AngleObject)O;
00030               Length=new TextFieldAction(this,"Length",o.getE(),30);
00031               P.add(new MyLabel(Zirkel.name("edit.angle.length")));
00032               P.add(Length);
00033               if (o.canFix())
00034               {      Fixed=new Checkbox("");     
00035                      Fixed.setState(o.fixed());
00036               }
00037               else Length.setEditable(false);
00038               if (Fixed!=null)
00039               {      P.add(new MyLabel(Zirkel.name("edit.fixed"))); P.add(Fixed);
00040               }
00041        }
00042        public void doAction (String o)
00043        {      if (o.equals("Length") && Fixed!=null)
00044               {      Fixed.setState(true);
00045                      super.doAction("OK");
00046               }
00047               else super.doAction(o);
00048        }
00049        public void addSecond (Panel P)
00050        {      AngleObject p=(AngleObject)O;
00051        
00052               SizeIB=new IconBar(F);
00053               SizeIB.addToggleGroupLeft("angle",5);
00054               SizeIB.toggle("angle",p.getDisplaySize());
00055               SizeIB.addSeparatorLeft();
00056               SizeIB.addOnOffLeft("filled");
00057               SizeIB.setState("filled",p.isFilled());
00058               SizeIB.addOnOffLeft("obtuse");
00059               SizeIB.setState("obtuse",p.getObtuse());
00060               P.add(new MyLabel("")); P.add(SizeIB);
00061               SizeIB.setIconBarListener(this);
00062        }
00063        public void iconPressed (String o)
00064        {      if (o.equals("filled"))
00065               {      if (SizeIB.getState("filled"))
00066                      {      IB.setState("isback",true);
00067                             ThicknessIB.setEnabled("solid",true);
00068                      }
00069                      else
00070                      {      IB.setState("isback",false);
00071                             ThicknessIB.setState("solid",false);
00072                             ThicknessIB.setEnabled("solid",false);
00073                      }
00074               }
00075               super.iconPressed(o);
00076        }
00077        public void setAction ()
00078        {      AngleObject o=(AngleObject)O;
00079               if (Fixed!=null && Fixed.getState()==true)
00080               {      o.setFixed(Length.getText());
00081               }
00082               if (Fixed!=null && Fixed.getState()==false)
00083                      o.setFixed(false);
00084               o.setDisplaySize(SizeIB.getToggleState("angle"));
00085               o.setFilled(SizeIB.getState("filled"));
00086               o.setObtuse(SizeIB.getState("obtuse"));
00087               Global.setParameter("unit.angle",Unit.getText());
00088        }
00089        public void focusGained (FocusEvent e)
00090        {      if (Fixed!=null && Fixed.getState()) Length.requestFocus();
00091               else super.focusGained(e);
00092        }
00093 }
00094 
00095 public class AngleObject extends ConstructionObject
00096        implements InsideObject
00097 {      protected PointObject P1,P2,P3;
00098        static Count N=new Count();
00099        double A,A1,A2;
00100        double X,Y;
00101        boolean Fixed;
00102        Expression E;
00103        boolean Filled=false;
00104        final static double LabelScale=0.66;
00105        
00106        public static final int NORMALSIZE=1,SMALL=0,LARGER=2,LARGE=3,RECT=4;
00107        protected int DisplaySize=NORMALSIZE;
00108        
00109        public AngleObject (Construction c,
00110               PointObject p1, PointObject p2, PointObject p3)
00111        {      super(c);
00112               P1=p1; P2=p2; P3=p3;
00113               validate();
00114               setColor(ColorIndex);
00115               updateText();
00116               Unit=Global.getParameter("unit.angle","");
00117        }
00118        
00119        public AngleObject (Construction c)
00120               {      super(c);
00121               }
00122               
00123        public String getTag () { return "Angle"; }
00124        public int getN () { return N.next(); }
00125        
00126        public void updateText ()
00127        {      if (!Fixed || E==null)
00128                      setText(text3(Zirkel.name("text.angle"),
00129                             P1.getName(),P2.getName(),P3.getName()));
00130               else
00131                      setText(text4(Zirkel.name("text.angle.fixed"),
00132                                    P1.getName(),P2.getName(),P3.getName(),"\""+E.toString()+"\""));
00133        }
00134        
00135        public String getDisplayValue ()
00136        {      if (ZirkelCanvas.AnglesFactor<=2) return ""+(int)(A/Math.PI*180+0.5);
00137               else return ""+round(A/Math.PI*180,ZirkelCanvas.AnglesFactor);
00138        }
00139        
00140        public boolean nearto (int x, int y, ZirkelCanvas zc)
00141        {      if (!displays(zc)) return false;
00142               double dx=zc.x(x)-X,dy=zc.y(y)-Y;
00143               double size=zc.dx((int)zc.selectionSize());
00144               double rd=getDisplaySize(zc),r=Math.sqrt(dx*dx+dy*dy);
00145               boolean near;
00146               Value=Math.abs(r-rd);
00147               if (Filled || DisplaySize==RECT)
00148               {      near=(r<rd+size);
00149                      if (near) Value=0;
00150               }
00151               else near=(Math.abs(r-rd)<size);
00152               if (!near) return false;
00153               if (rd<size) return near;
00154               double a=Math.atan2(dy,dx);
00155               if (a<0) a+=2*Math.PI;
00156               double c=0.05;
00157               if (a<A1) a+=2*Math.PI;
00158               return a>A1-c && a<A1+A+c;
00159        }
00160        
00161        public void validate ()
00162        {      if (P1==null) return;
00163               if (!P1.valid() || !P2.valid() || !P3.valid()) { Valid=false; return; }
00164               else
00165               {      X=P2.getX(); Y=P2.getY();
00166                      double dx=P1.getX()-X,dy=P1.getY()-Y;
00167                      if (Math.sqrt(dx*dx+dy*dy)<1e-9)
00168                      {      Valid=false; return;
00169                      }
00170                      A1=Math.atan2(dy,dx);
00171                      if (A1<0) A1+=2*Math.PI;
00172                      dx=P3.getX()-X; dy=P3.getY()-Y;
00173                      if (Math.sqrt(dx*dx+dy*dy)<1e-9)
00174                      {      Valid=false; return;
00175                      }
00176                      A2=Math.atan2(dy,dx);
00177                      if (A2<0) A2+=2*Math.PI;
00178                      A=A2-A1;
00179                      if (A<0) A=A+2*Math.PI;
00180                      Valid=true;
00181                      if (Fixed)
00182                      {      double FixedAlpha=0;
00183                             try
00184                             {      FixedAlpha=E.getValue()/180*Math.PI;
00185                             }
00186                             catch (Exception e)
00187                             {      return;
00188                             }
00189                             if (P3.moveableBy(this))
00190                             {      dx=P3.getX()-X; dy=P3.getY()-Y;
00191                                    double r=Math.sqrt(dx*dx+dy*dy);
00192                                    if (r<1e-9) r=1e-9;
00193                                    P3.move(X+Math.cos(A1+FixedAlpha)*r,
00194                                           Y+Math.sin(A1+FixedAlpha)*r);
00195                                    A2=A1+FixedAlpha;
00196                             }
00197                             else Fixed=false;
00198                             if (Fixed)
00199                             {      A=FixedAlpha;
00200                                    P3.movedBy(this);
00201                                    P1.movedBy(this);
00202                             }
00203                      }
00204                      else if (!Obtuse && A>Math.PI)
00205                      {      A1=A2;
00206                             A=2*Math.PI-A;
00207                             A2=A1+A;
00208                      }
00209               }
00210        }
00211 
00212        double x[]=new double[4],y[]=new double[4];
00213        
00214        public void paint (MyGraphics g, ZirkelCanvas zc)
00215        {      if (!Valid  || mustHide(zc)) return;
00216               double R=zc.col(getDisplaySize(zc))-zc.col(0);
00217               double c1=zc.col(X)-R,r1=zc.row(Y)-R;
00218               // paint:
00219               double DA=(A2-A1)/Math.PI*180;
00220               if (DA<0) DA+=360;
00221               else if (DA>=360) DA-=360;
00222               if (visible(zc))
00223               {      if (isStrongSelected() && g instanceof MyGraphics13)
00224                      {      ((MyGraphics13)g).drawMarkerArc(c1+R,r1+R,R,A1/Math.PI*180,DA);
00225                      }
00226                      if (Filled)
00227                      {      if (DisplaySize==RECT)
00228                             {      double dx1=Math.cos(A1),dy1=Math.sin(A1),
00229                                    dx2=Math.cos(A1+DA/180*Math.PI),dy2=Math.sin(A1+DA/180*Math.PI);
00230                                    double dx3=dx1+dx2,dy3=dy1+dy2;
00231                                    if (DA>180)
00232                                    {      dx3=-dx3; dy3=-dy3;
00233                                    }
00234                                    if (Selected||getColorType()!=THIN)
00235                                    {      g.setColor(this);
00236                                           g.drawLine(c1+R+R*dx1,r1+R-R*dy1,c1+R+R*dx3,r1+R-R*dy3);
00237                                           g.drawLine(c1+R+R*dx3,r1+R-R*dy3,c1+R+R*dx2,r1+R-R*dy2);
00238                                    }
00239                                    x[0]=c1+R; y[0]=r1+R;
00240                                    x[1]=c1+R+R*dx1; y[1]=r1+R-R*dy1;
00241                                    x[2]=c1+R+R*dx3; y[2]=r1+R-R*dy3;
00242                                    x[3]=c1+R+R*dx2; y[3]=r1+R-R*dy2;
00243                                    g.fillPolygon(x,y,4,false,getColorType()!=THICK,this);
00244                             }
00245                             else 
00246                                    g.fillArc(c1,r1,2*R,2*R,A1/Math.PI*180,DA,
00247                                                  Selected||getColorType()!=THIN,getColorType()!=THICK,true,this);
00248                      }
00249                      else
00250                      {      g.setColor(this);
00251                             if (DisplaySize==RECT)
00252                             {      double dx1=Math.cos(A1),dy1=Math.sin(A1),
00253                                           dx2=Math.cos(A1+DA/180*Math.PI),dy2=Math.sin(A1+DA/180*Math.PI);
00254                                    g.drawLine(c1+R+R*dx1,r1+R-R*dy1,c1+R+R*(dx1+dx2),r1+R-R*(dy1+dy2));
00255                                    g.drawLine(c1+R+R*(dx1+dx2),r1+R-R*(dy1+dy2),c1+R+R*dx2,r1+R-R*dy2);
00256                             }
00257                             else 
00258                                    g.drawCircleArc(c1+R,r1+R,R,A1/Math.PI*180,DA,this);
00259                      }
00260               }
00261               String s=translateToUnicode(getDisplayText());
00262               if (!s.equals(""))
00263               {      g.setLabelColor(this);
00264                      setFont(g);
00265                      DisplaysText=true;
00266                      double dx=Math.cos(A1+A/2),dy=Math.sin(A1+A/2);
00267                      if (s.equals("90"+getUnit()) || Name.startsWith("."))
00268                      {      if (KeepClose)
00269                             {      double d=Math.sqrt(XcOffset*XcOffset+YcOffset*YcOffset);
00270                                    TX1=zc.col(X+d*dx)-3; 
00271                                    TY1=zc.row(Y+d*dy)-3;
00272                                    TX2=TX1+9;
00273                                    TY2=TY1+9;
00274                                    g.drawRect(zc.col(X+d*dx)-1,
00275                                           zc.row(Y+d*dy)-1,3,3);
00276                             }
00277                             else
00278                             {      TX1=zc.col(X+zc.dx(R*LabelScale)*dx+XcOffset)-3; 
00279                                    TY1=zc.row(Y+zc.dy(R*LabelScale)*dy+YcOffset)-3;
00280                                    TX2=TX1+9;
00281                                    TY2=TY1+9;
00282                                    g.drawRect(zc.col(X+zc.dx(R*LabelScale)*dx+XcOffset)-1,
00283                                           zc.row(Y+zc.dy(R*LabelScale)*dy+YcOffset)-1,3,3);
00284                             }
00285                      }
00286                      else
00287                      {      if (KeepClose)
00288                             {      double d=Math.sqrt(XcOffset*XcOffset+YcOffset*YcOffset);
00289                                    drawCenteredLabel(g,s,zc,
00290                                           X+d*dx,Y+d*dy,0,0);
00291                             }
00292                             else
00293                                    drawCenteredLabel(g,s,zc,
00294                                           X+zc.dx(R*LabelScale)*dx,Y+zc.dy(R*LabelScale)*dy,
00295                                           XcOffset,YcOffset);
00296                      }
00297               }
00298        }
00299 
00300        public boolean canKeepClose ()
00301        {      return true;
00302        }
00303        
00304        public void setKeepClose (double x, double y)
00305        {      KeepClose=true;
00306               XcOffset=x-X;
00307               YcOffset=y-Y;
00308        }
00309 
00310        double getDisplaySize (ZirkelCanvas zc)
00311        {      double R=zc.dx((int)(12*zc.pointSize()));
00312               if (DisplaySize==SMALL || DisplaySize==RECT) R/=2;
00313               else if (DisplaySize==LARGER) R*=2;
00314               else if (DisplaySize==LARGE)
00315               {      double dx=P1.getX()-X,dy=P1.getY()-Y;
00316                      R=Math.sqrt(dx*dx+dy*dy);
00317               }
00318               return R;
00319        }
00320 
00321        public double getLength () { return A; }
00322        public boolean fixed () { return Fixed; }
00323        public void setFixed (boolean flag)
00324        {      Fixed=flag;
00325               updateText();
00326        }
00327        public void setFixed (String s)
00328        {      Fixed=true;
00329               E=new Expression(s,getConstruction(),this);
00330               updateText();
00331        }
00332 
00333        public boolean canFix ()
00334        {      return P3.moveableBy(this);
00335        }
00336 
00337        public void printArgs (XmlWriter xml)
00338        {      if (P1!=null)
00339               {      xml.printArg("first",P1.getName());
00340                      xml.printArg("root",P2.getName());
00341                      xml.printArg("second",P3.getName());
00342               }
00343               if (DisplaySize==SMALL) xml.printArg("display","small");
00344               if (DisplaySize==LARGE) xml.printArg("display","large");
00345               if (DisplaySize==LARGER) xml.printArg("display","larger");
00346               if (DisplaySize==RECT) xml.printArg("display","rectangle");
00347               if (Filled) xml.printArg("filled","true");
00348               if (Fixed && E!=null) xml.printArg("fixed",E.toString());
00349               if (!Obtuse) xml.printArg("acute","true");
00350               super.printArgs(xml);
00351        }      
00352 
00353        public void edit (ZirkelCanvas zc)
00354        {      ObjectEditDialog d=new AngleEditDialog(zc.getFrame(),this);
00355               d.setVisible(true);
00356               zc.repaint();
00357               if ((E!=null && !E.isValid()))
00358               {      Frame F=zc.getFrame();
00359                      Warning w=new Warning(F,E.getErrorText(),
00360                             Zirkel.name("warning"),true);
00361                      w.center(F);
00362                      w.setVisible(true);
00363               }
00364               if (d.wantsMore())
00365               {      new EditConditionals(zc.getFrame(),this);
00366                      validate();
00367               }
00368        }
00369 
00370        public void setDisplaySize (int i) { DisplaySize=i; }
00371        public int getDisplaySize () { return DisplaySize; }
00372 
00373        public Enumeration depending ()
00374        {      super.depending();
00375               if (P1==null) return DL.elements();
00376               if (!Fixed) return depset(P1,P2,P3);
00377               else
00378               {      depset(P1,P2,P3);
00379                      Enumeration e=E.getDepList().elements();
00380                      while (e.hasMoreElements())
00381                      {      DL.add((ConstructionObject)e.nextElement());
00382                      }
00383                      return DL.elements();
00384               }
00385        }
00386 
00387        public boolean equals (ConstructionObject o)
00388        {      if (!(o instanceof AngleObject) || !o.valid()) return false;
00389               AngleObject l=(AngleObject)o;
00390               return equals(X,l.X) && equals(Y,l.Y) &&
00391                      equals(A1,l.A1) && equals(A2,l.A2);
00392        }
00393 
00394        public static char Translation[]=
00395        {      'a','\u03B1','A','\u0391',
00396               'b','\u03B2','B','\u0392',
00397               'c','\u03B3','C','\u0393',
00398               'd','\u03B4','D','\u0394',
00399               'e','\u03B5','E','\u0395',
00400               'f','\u03D5','F','\u03A6',
00401               'g','\u03B3','G','\u0393',
00402               'h','\u03B7','H','\u0397',
00403               'i','\u03B9','I','\u0399',
00404               'k','\u03BA','K','\u039A',
00405               'l','\u03BB','L','\u039B',
00406               'm','\u03BC','M','\u039C',
00407               'n','\u03BD','N','\u039D',
00408               'o','\u03BF','O','\u03A9',
00409               'p','\u03C0','P','\u03A0',
00410               'q','\u03C7','Q','\u03A7',
00411               'r','\u03C1','R','\u03A1',
00412               's','\u03C3','S','\u03A3',
00413               't','\u03C4','T','\u03A4',
00414               'u','\u03C5','U','\u03A5',
00415               'v','\u03C8','V','\u03A8',
00416               'w','\u03C9','W','\u03A9',
00417               'x','\u03BE','X','\u039E',
00418               'y','\u03C7','Y','\u03A7',
00419               'z','\u03B6','Z','\u0396',         
00420        };
00421 
00422        public static String translateToUnicode (String s)
00423        {      if (s.startsWith("$")) return s;
00424               if (s.indexOf('\\')<0) return s;
00425               StringBuffer b=new StringBuffer();
00426               for (int i=0; i<s.length(); i++)
00427               {      char c=s.charAt(i);
00428                      if (c!='\\') b.append(c);
00429                      else
00430                      {      i++;
00431                             if (i<s.length())
00432                             {      c=s.charAt(i);
00433                                    if (c=='0')
00434                                    {      int n=0;
00435                                           i++;
00436                                           while (i<s.length())
00437                                           {      char ch=s.charAt(i);
00438                                                  if (ch>='0' && ch<='9')
00439                                                  {      n=n*16+(int)(ch-'0');
00440                                                  }
00441                                                  else if (ch>='A' && ch<='F')
00442                                                  {      n=n*16+(int)(ch-'A'+10);
00443                                                  }
00444                                                  else break;
00445                                                  i++;
00446                                           }
00447                                           if (n>0)
00448                                           {      c=(char)n;
00449                                                  b.append(c);
00450                                           }
00451                                           i--; continue;
00452                                    }
00453                                    int j=0;
00454                                    for (j=0; j<Translation.length; j+=2)
00455                                    {      if (Translation[j]==c)
00456                                           {      b.append(Translation[j+1]);
00457                                                  break;
00458                                           }      
00459                                    }
00460                                    if (j>=Translation.length) b.append(c);
00461                             }
00462                      }
00463               }
00464               return b.toString();
00465        }
00466 
00467        public void translate ()
00468        {      P1=(PointObject)P1.getTranslation();
00469               P2=(PointObject)P2.getTranslation();
00470               P3=(PointObject)P3.getTranslation();
00471               if (Fixed)
00472               {      try
00473                      {      setFixed(E.toString());
00474                             E.translate();
00475                      }
00476                      catch (Exception e) { Fixed=false; }
00477               }
00478        }
00479 
00480        public String getE ()
00481        {      if (Fixed && E!=null) return E.toString();
00482               else return ""+round(A/Math.PI*180);
00483        }
00484        
00485        public double getValue ()
00486               throws ConstructionException
00487        {      if (!Valid) throw new InvalidException("exception.invalid");
00488               else return A/Math.PI*180;
00489        }
00490 
00491        public void setFilled (boolean flag)
00492        {      Filled=flag;
00493        }
00494        public boolean isFilled ()
00495        {      return Filled;
00496        }
00497 
00498        public boolean maybeTransparent ()
00499        {      return true;
00500        }      
00501 
00502        public boolean isFilledForSelect ()
00503        {      return false;
00504        }
00505 
00506        public double containsInside (PointObject P) 
00507        {      double dx=P.getX()-X,dy=P.getY()-Y;
00508               double a=Math.atan2(dy,dx);
00509               if (a<0) a+=2*Math.PI;
00510               if (a<A1) a+=2*Math.PI;
00511               double c=1e-5;
00512               if (a>A1 && a<A1+A) return 1;
00513               else if (a>A1-c && a<A1+A+c) return 0.5;
00514               return 0;
00515        }
00516 
00517        public boolean keepInside(PointObject P) 
00518        {      if (containsInside(P)>0) return true;
00519               double x=P.getX(),y=P.getY();
00520               double x1=P2.getX(),y1=P2.getY();
00521               double xmin=x1,ymin=y1,dmin=1e20;
00522               double x2=P1.getX(),y2=P1.getY();
00523               double dx=x2-x1,dy=y2-y1;
00524               double r=dx*dx+dy*dy;
00525               double h=dx*(x-x1)/r+dy*(y-y1)/r;
00526               if (h<0) h=0;
00527               double xh=x1+h*dx,yh=y1+h*dy;
00528               double dist=Math.sqrt((x-xh)*(x-xh)+(y-yh)*(y-yh));
00529               if (dist<dmin)
00530               {      dmin=dist;
00531                      xmin=xh; ymin=yh;
00532               }
00533               x2=P3.getX(); y2=P3.getY();
00534               dx=x2-x1; dy=y2-y1;
00535               r=dx*dx+dy*dy;
00536               h=dx*(x-x1)/r+dy*(y-y1)/r;
00537               if (h<0) h=0;
00538               xh=x1+h*dx; yh=y1+h*dy;
00539               dist=Math.sqrt((x-xh)*(x-xh)+(y-yh)*(y-yh));
00540               if (dist<dmin)
00541               {      dmin=dist;
00542                      xmin=xh; ymin=yh;
00543               }
00544               P.move(xmin,ymin);
00545               return false;
00546        }      
00547 }