Back to index

wims  3.65+svn20090927
SegmentObject.java
Go to the documentation of this file.
00001 package rene.zirkel.objects;
00002 
00003 // file: SegmentObject.java
00004 
00005 import java.awt.*;
00006 import java.util.*;
00007 
00008 import rene.util.xml.*;
00009 import rene.zirkel.Zirkel;
00010 import rene.zirkel.ZirkelCanvas;
00011 import rene.zirkel.construction.Construction;
00012 import rene.zirkel.construction.ConstructionException;
00013 import rene.zirkel.construction.Count;
00014 import rene.zirkel.expression.Expression;
00015 import rene.zirkel.expression.InvalidException;
00016 import rene.zirkel.graphics.MyGraphics;
00017 import rene.zirkel.graphics.MyGraphics13;
00018 import rene.dialogs.*;
00019 import rene.gui.*;
00020 
00028 public class SegmentObject extends TwoPointLineObject
00029 {      static Count N=new Count();
00030        protected boolean Fixed=false; // fixed length?
00031        Expression E; // expression to fix the length.
00032        boolean ExpressionFailed; // invalid expression?
00033        boolean Arrow=false; // draw as arrow.
00034        
00035        public SegmentObject (Construction c, PointObject p1, PointObject p2)
00036        {      super(c,p1,p2);
00037               validate();
00038               updateText();
00039               Unit=Global.getParameter("unit.length","");
00040        }
00041        public String getTag () { return "Segment"; }
00042        public int getN () { return N.next(); }
00043        
00044        public void setDefaults ()
00045        {      Arrow=Cn.Vectors;
00046               super.setDefaults();
00047        }
00048        
00049        public void updateText ()
00050        {      if (!Fixed)
00051                      setText(text2(Zirkel.name("text.segment"),P1.getName(),P2.getName()));
00052               else
00053               {      if (E==null) 
00054                             setText(text3(Zirkel.name("text.segment.fixed"),
00055                                    P1.getName(),P2.getName(),""+round(R)));
00056                      else
00057                             setText(text3(Zirkel.name("text.segment.fixed"),
00058                                    P1.getName(),P2.getName(),"\""+E.toString()+"\""));
00059               }
00060        }
00061        
00062        public void validate ()
00063        {      ExpressionFailed=false;
00064               if (!P1.valid() || !P2.valid()) { Valid=false; return; }
00065               else
00066               {      Valid=true;
00067                      X1=P1.getX(); Y1=P1.getY();
00068                      X2=P2.getX(); Y2=P2.getY();
00069                      // compute normalized vector in the direction of the line:
00070                      DX=X2-X1; DY=Y2-Y1; 
00071                      R=Math.sqrt(DX*DX+DY*DY);
00072                      // if fixed, move the moveable endpoint.
00073                      if (Fixed && E!=null)
00074                      {      try
00075                             {      double FixedR=E.getValue();
00076                                    // System.out.println(R+" "+FixedR);
00077                                    if (FixedR<1e-8)
00078                                    {      R=0; ExpressionFailed=true; Valid=false; return;
00079                                    }
00080                                    boolean movefirst=P1.moveableBy(this),
00081                                           movesecond=P2.moveableBy(this);
00082                                    if (P2.getBound()!=null)
00083                                    {      ConstructionObject bound=P2.getBound();
00084                                           if (bound instanceof RayObject)
00085                                           {      if (((RayObject)bound).getP1()==P1) movesecond=true;
00086                                           }
00087                                    }
00088                                    else if (P1.getBound()!=null)
00089                                    {      ConstructionObject bound=P1.getBound();
00090                                           if (bound instanceof RayObject)
00091                                           {      if (((RayObject)bound).getP1()==P2) 
00092                                                  {      movefirst=true; movesecond=false;
00093                                                  }
00094                                           }
00095                                    }
00096                                    if (movesecond)
00097                                    {      if (R<1e-10) P2.move(X1+FixedR,Y1);
00098                                           else P2.move(X1+FixedR*DX/R,Y1+FixedR*DY/R);
00099                                           P1.setUseAlpha(false);
00100                                           // System.out.println("Move "+P2.getName());
00101                                    }
00102                                    else if (movefirst)
00103                                    {      if (R<1e-10) P1.move(X2-FixedR,Y2);
00104                                           else P1.move(X2-FixedR*DX/R,Y2-FixedR*DY/R);
00105                                           P2.setUseAlpha(false);
00106                                           // System.out.println("Move "+P1.getName());
00107                                    }
00108                                    else Fixed=false; // no moveable endpoint!
00109                                    if (Fixed)
00110                                    {      X1=P1.getX(); Y1=P1.getY();
00111                                           X2=P2.getX(); Y2=P2.getY();
00112                                           DX=X2-X1; DY=Y2-Y1; 
00113                                           R=Math.sqrt(DX*DX+DY*DY);
00114                                           P2.movedBy(this);
00115                                           P1.movedBy(this);
00116                                    }
00117                             }
00118                             catch (Exception e)
00119                             {      ExpressionFailed=true; Valid=false; R=0; return;
00120                             }
00121                      }
00122                      // See of the length is too small.
00123                      if (R<1e-10) { R=0; DX=1; DY=0; }
00124                      else { DX/=R; DY/=R; }
00125               }
00126        }
00127 
00128        public void paint (MyGraphics g, ZirkelCanvas zc)
00129        {      if (!Valid || mustHide(zc)) return;
00130               double c1=zc.col(X1),r1=zc.row(Y1),
00131                      c2=zc.col(X2),r2=zc.row(Y2);
00132               if (visible(zc))
00133               {      if (isStrongSelected() && g instanceof MyGraphics13)
00134                      {      ((MyGraphics13)g).drawMarkerLine(c1,r1,c2,r2);
00135                      }
00136                      g.setColor(this);
00137                      g.drawLine(c1,r1,c2,r2,this);
00138                      if (Arrow) // draw as arrow!
00139                      {      double a=Math.PI*0.9;
00140                             double r=zc.dx(zc.scale(
00141                                    Global.getParameter("arrowsize",15))); // 10 pixel on the screen
00142                             g.drawLine(c2,r2,
00143                                    zc.col(X2+(DX*Math.cos(a)+DY*Math.sin(a))*r),
00144                                    zc.row(Y2+(-DX*Math.sin(a)+DY*Math.cos(a))*r),this);
00145                             a=-a;
00146                             g.drawLine(c2,r2,
00147                                    zc.col(X2+(DX*Math.cos(a)+DY*Math.sin(a))*r),
00148                                    zc.row(Y2+(-DX*Math.sin(a)+DY*Math.cos(a))*r),this);                         
00149                      }
00150               }
00151               String s=getDisplayText();
00152               if (!s.equals(""))
00153               {      g.setLabelColor(this);
00154                      setFont(g);
00155                      DisplaysText=true;
00156                      if (KeepClose)
00157                      {      double side=(YcOffset<0)?1:-1;
00158                             drawLabel(g,s,zc,X1+XcOffset*(X2-X1),Y1+XcOffset*(Y2-Y1),
00159                                    side*DX,side*DY,0,0);
00160                      }
00161                      else
00162                             drawLabel(g,s,zc,(X1+X2)/2,(Y1+Y2)/2,
00163                                    DX,DY,XcOffset,YcOffset);
00164               }
00165        }
00166        
00167        public boolean canKeepClose ()
00168        {      return true;
00169        }
00170        
00171        public void setKeepClose (double x, double y)
00172        {      KeepClose=true;
00173               XcOffset=(x-X1)/R*DX+(y-Y1)/R*DY;
00174               YcOffset=(x-X1)/R*DY-(y-Y1)/R*DX;
00175        }
00176 
00177        public String getDisplayValue ()
00178        {      return ""+round(R,ZirkelCanvas.LengthsFactor);
00179        }
00180        
00184        public boolean nearto (int c, int r, ZirkelCanvas zc)
00185        {      if (ExpressionFailed && P1.valid()) return P1.nearto(c,r,zc);
00186               if (ExpressionFailed && P2.valid()) return P2.nearto(c,r,zc);
00187               if (!displays(zc)) return false;
00188               //compute point at c,r
00189               double x=zc.x(c),y=zc.y(r);
00190               // compute distance from line
00191               double d=(x-X1)*DY-(y-Y1)*DX;
00192               // compute offset
00193               double o=(x-X1)*DX+(y-Y1)*DY,o1=(X2-X1)*DX+(Y2-Y1)*DY;
00194               if (o1>0)
00195               {      if (o>o1) d=Math.sqrt((x-X2)*(x-X2)+(y-Y2)*(y-Y2));
00196                      else if (o<0) d=Math.sqrt((x-X1)*(x-X1)+(y-Y1)*(y-Y1));
00197               }
00198               else
00199               {      if (o<o1) d=Math.sqrt((x-X2)*(x-X2)+(y-Y2)*(y-Y2));
00200                      else if (o>0) d=Math.sqrt((x-X1)*(x-X1)+(y-Y1)*(y-Y1));
00201               }
00202               // scale in screen coordinates
00203               Value=Math.abs(zc.col(zc.minX()+d)-zc.col(zc.minX()))*0.9;
00204               return Value<zc.selectionSize();
00205        }
00206        
00210        public boolean onlynearto (int c, int r, ZirkelCanvas zc)
00211        {      return R<zc.dx(3*(int)zc.pointSize());
00212        }
00213 
00214        public void printArgs (XmlWriter xml)
00215        {      xml.printArg("from",P1.getName());
00216               xml.printArg("to",P2.getName());
00217               if (Fixed && E!=null) xml.printArg("fixed",E.toString());
00218               if (Arrow) xml.printArg("arrow","true");
00219               super.printArgs(xml);
00220        }
00221 
00222        public double getLength () { return R; }
00223        public boolean fixed () { return Fixed; }
00224        public void setFixed (boolean flag, String s)
00225               throws ConstructionException
00226        {      if (!flag || s.equals(""))
00227               {      Fixed=false;
00228                      E=null;
00229               }
00230               else
00231               {      E=new Expression(s,getConstruction(),this);
00232                      if (!E.isValid())
00233                             throw new ConstructionException (E.getErrorText());
00234                      Fixed=true;
00235               }
00236               updateText();
00237        }
00238        public void round ()
00239        {      try
00240               {      setFixed(true,getDisplayValue());
00241                      validate();
00242               }
00243               catch (Exception e) {}
00244        }
00245        
00249        public boolean canFix ()
00250        {      return P1.moveableBy(this) || P2.moveableBy(this);
00251        }
00252        
00253        public boolean contains (double x, double y)
00254        {      double a=(x-X1)*DX+(y-Y1)*DY;
00255               if (a<-1e-9 || a>R+1e-9) return false;
00256               return true;
00257        }
00258        
00259        public double project (double x, double y)
00260        {      double h=super.project(x,y);
00261               if (h<0) return 0;
00262               if (h>R) return R;
00263               return h;
00264        }
00265        
00269        public boolean equals (ConstructionObject o)
00270        {      if (!(o instanceof SegmentObject) || !o.valid()) return false;
00271               SegmentObject l=(SegmentObject)o;
00272               return
00273               (      equals(X1,l.X1) && equals(X2,l.X2) &&
00274                      equals(Y1,l.Y1) && equals(Y2,l.Y2)
00275               )
00276               ||
00277               (      equals(X1,l.X2) && equals(Y1,l.Y2) &&
00278                      equals(X2,l.X1) && equals(Y2,l.Y1)
00279               );
00280        }
00281 
00282        public void edit (ZirkelCanvas zc)
00283        {      super.edit(zc);
00284               if (E!=null && !E.isValid())
00285               {      Frame F=zc.getFrame();
00286                      Warning w=new Warning(F,E.getErrorText(),
00287                             Zirkel.name("warning"),true);
00288                      w.center(F);
00289                      w.setVisible(true);
00290               }
00291        }
00292        
00293        public boolean isValidFix ()
00294        {      return E!=null && E.isValid();
00295        }
00296 
00297        public String getStringLength ()
00298        {      if (E!=null) return E.toString();
00299               else return ""+round(R);
00300        }
00301        
00302        public double getValue ()
00303               throws ConstructionException
00304        {      if (!Valid) throw new InvalidException("exception.invalid");
00305               else return R;
00306        }
00307 
00308        public void translate ()
00309        {      super.translate();
00310               try
00311               {      setFixed(Fixed,E.toString());
00312                      E.translate();
00313               }
00314               catch (Exception e) { Fixed=false; }
00315        }
00316        
00317        public Enumeration depending ()
00318        {      if (!Fixed || E==null) return super.depending();
00319               else
00320               {      super.depending();
00321                      Enumeration e=E.getDepList().elements();
00322                      while (e.hasMoreElements())
00323                      {      DL.add((ConstructionObject)e.nextElement());
00324                      }
00325                      return DL.elements();
00326               }
00327        }
00328 
00329        public void setArrow (boolean arrow)
00330        {      Arrow=arrow;
00331        }
00332        public boolean isArrow ()
00333        {      return Arrow;
00334        }
00335 
00336        public void project (PointObject P) 
00337        {      double h=project(P.getX(),P.getY());
00338               P.setXY(getX()+h*getDX(),getY()+h*getDY());
00339               P.setA(h/getLength());
00340        }
00341 
00342        public void project(PointObject P, double alpha)
00343        {      double d=alpha*getLength();
00344               P.setXY(getX()+d*getDX(),getY()+d*getDY());
00345        }
00346 
00347        public boolean moveable () 
00348        {      if (!Fixed && P1.moveable() && P2.moveable()) return true;
00349               return false;
00350        }
00351 
00352 }