1016 lines
37 KiB
Java
1016 lines
37 KiB
Java
/*
|
|
|
|
Copyright 2006 Rene Grothmann, modified by Eric Hakenholz
|
|
|
|
This file is part of C.a.R. software.
|
|
|
|
C.a.R. is a free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, version 3 of the License.
|
|
|
|
C.a.R. is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
package rene.zirkel.objects;
|
|
|
|
// file: Circle3Object.java
|
|
import eric.bar.JPropertiesBar;
|
|
import java.awt.Checkbox;
|
|
import java.awt.Color;
|
|
import java.awt.Frame;
|
|
import java.awt.TextField;
|
|
import java.awt.event.FocusEvent;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.Enumeration;
|
|
import java.util.Vector;
|
|
|
|
import eric.JEricPanel;
|
|
|
|
import rene.dialogs.Warning;
|
|
import rene.gui.Global;
|
|
import rene.gui.IconBar;
|
|
import rene.gui.IconBarListener;
|
|
import rene.gui.MyLabel;
|
|
import rene.gui.TextFieldAction;
|
|
import rene.util.xml.XmlWriter;
|
|
import rene.gui.Global;
|
|
import rene.zirkel.ZirkelCanvas;
|
|
import rene.zirkel.construction.Construction;
|
|
import rene.zirkel.construction.ConstructionException;
|
|
import rene.zirkel.construction.Count;
|
|
import rene.zirkel.expression.Expression;
|
|
import rene.zirkel.expression.ExpressionColor;
|
|
import rene.zirkel.expression.InvalidException;
|
|
import rene.zirkel.graphics.MyGraphics;
|
|
import rene.zirkel.graphics.MainGraphics;
|
|
import rene.zirkel.graphics.PolygonDrawer;
|
|
|
|
public class AngleObject extends ConstructionObject implements InsideObject {
|
|
|
|
protected PointObject P1, P2, P3;
|
|
static Count N=new Count();
|
|
double A, A1, A2, A3D; // Dibs : A3D est l'angle 3D
|
|
double X, Y;
|
|
boolean Fixed;
|
|
Expression E;
|
|
boolean Filled=false;
|
|
final static double LabelScale=0.66;
|
|
public static final int NORMALSIZE=1, SMALL=0, LARGER=2, LARGE=3,
|
|
RECT=4;
|
|
protected int DisplaySize=NORMALSIZE;
|
|
|
|
public AngleObject(final Construction c, final PointObject p1,
|
|
final PointObject p2, final PointObject p3) {
|
|
super(c);
|
|
P1=p1;
|
|
P2=p2;
|
|
P3=p3;
|
|
validate();
|
|
setColor(ColorIndex, SpecialColor);
|
|
updateText();
|
|
Unit=Global.getParameter("unit.angle", "°");
|
|
double xx=P1.getX()+P3.getX()-2*P2.getX();
|
|
double yy=P1.getY()+P3.getY()-2*P2.getY();
|
|
final double ll=Math.max(Math.sqrt(xx*xx+yy*yy),0.000001);
|
|
xx=xx/ll;
|
|
yy=yy/ll;
|
|
XcOffset=xx*25/c.getPixel();
|
|
YcOffset=yy*25/c.getPixel();
|
|
}
|
|
|
|
public AngleObject(final Construction c) {
|
|
super(c);
|
|
}
|
|
|
|
@Override
|
|
public void setDefaults() {
|
|
setShowName(Global.getParameter("options.angle.shownames", false));
|
|
setShowValue(Global.getParameter("options.angle.showvalues", false));
|
|
setColor(Global.getParameter("options.angle.color", 0), Global.getParameter("options.angle.pcolor", (ExpressionColor) null, this));
|
|
setColorType(Global.getParameter("options.angle.colortype", 0));
|
|
setFilled(Global.getParameter("options.angle.filled", false));
|
|
setHidden(Cn.Hidden);
|
|
setObtuse(Global.getParameter("options.angle.obtuse", false));
|
|
setSolid(Global.getParameter("options.angle.solid", false));
|
|
setLarge(Cn.LargeFont);
|
|
setBold(Cn.BoldFont);
|
|
setPartial(Cn.Partial);
|
|
}
|
|
|
|
@Override
|
|
public void setTargetDefaults() {
|
|
setShowName(Global.getParameter("options.angle.shownames", false));
|
|
setShowValue(Global.getParameter("options.angle.showvalues", false));
|
|
setColor(Global.getParameter("options.angle.color", 0), Global.getParameter("options.angle.pcolor", (ExpressionColor) null, this));
|
|
setColorType(Global.getParameter("options.angle.colortype", 0));
|
|
setFilled(Global.getParameter("options.angle.filled", false));
|
|
setObtuse(Global.getParameter("options.angle.obtuse", false));
|
|
setSolid(Global.getParameter("options.angle.solid", false));
|
|
}
|
|
|
|
@Override
|
|
public String getTag() {
|
|
return "Angle";
|
|
}
|
|
|
|
@Override
|
|
public int getN() {
|
|
return N.next();
|
|
}
|
|
|
|
@Override
|
|
public void updateText() {
|
|
if (!Fixed||E==null) {
|
|
setText(text3(Global.name("text.angle"), P1.getName(),
|
|
P2.getName(), P3.getName()));
|
|
} else {
|
|
setText(text4(Global.name("text.angle.fixed"), P1.getName(), P2.getName(), P3.getName(), "\""+E.toString()+"\""));
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public String getDisplayValue() {
|
|
// if (ZirkelCanvas.AnglesFactor<=2) {
|
|
// return ""+(int) (A/Math.PI*180+0.5);
|
|
// } else {
|
|
// return ""+round(A/Math.PI*180, ZirkelCanvas.AnglesFactor);
|
|
// }
|
|
if (P1.is3D()&&P2.is3D()&&P3.is3D()) return Global.getLocaleNumber(A3D/Math.PI*180, "angles");
|
|
else return Global.getLocaleNumber(A/Math.PI*180, "angles");
|
|
}
|
|
|
|
@Override
|
|
public boolean nearto(final int x, final int y, final ZirkelCanvas zc) {
|
|
if (!displays(zc)) {
|
|
return false;
|
|
}
|
|
final double dx=zc.x(x)-X, dy=zc.y(y)-Y;
|
|
final double size=zc.dx(zc.selectionSize());
|
|
final double rd=getDisplaySize(zc), r=Math.sqrt(dx*dx+dy*dy);
|
|
boolean near;
|
|
Value=Math.abs(r-rd);
|
|
if (Filled||DisplaySize==RECT) {
|
|
near=(r<rd+size);
|
|
if (near) {
|
|
Value=0;
|
|
}
|
|
} else {
|
|
near=(Math.abs(r-rd)<size);
|
|
}
|
|
if (!near) {
|
|
return false;
|
|
}
|
|
if (rd<size) {
|
|
return near;
|
|
}
|
|
double a=Math.atan2(dy, dx);
|
|
if (a<0) {
|
|
a+=2*Math.PI;
|
|
}
|
|
final double c=0.05;
|
|
if (a<A1) {
|
|
a+=2*Math.PI;
|
|
}
|
|
return a>A1-c&&a<A1+A+c;
|
|
}
|
|
|
|
@Override
|
|
public void validate() {
|
|
if (P1==null) {
|
|
return;
|
|
}
|
|
if (!P1.valid()||!P2.valid()||!P3.valid()) {
|
|
Valid=false;
|
|
return;
|
|
} else {
|
|
X=P2.getX();
|
|
Y=P2.getY();
|
|
double dx=P1.getX()-X, dy=P1.getY()-Y;
|
|
if (Math.sqrt(dx*dx+dy*dy)<1e-9) {
|
|
Valid=false;
|
|
return;
|
|
}
|
|
A1=Math.atan2(dy, dx);
|
|
if (A1<0) {
|
|
A1+=2*Math.PI;
|
|
}
|
|
dx=P3.getX()-X;
|
|
dy=P3.getY()-Y;
|
|
if (Math.sqrt(dx*dx+dy*dy)<1e-9) {
|
|
Valid=false;
|
|
return;
|
|
}
|
|
A2=Math.atan2(dy, dx);
|
|
if (A2<0) {
|
|
A2+=2*Math.PI;
|
|
}
|
|
A=A2-A1;
|
|
if (A<0) {
|
|
A=A+2*Math.PI;
|
|
}
|
|
if (P1.is3D()&&P2.is3D()&&P3.is3D()) {
|
|
double dx13D=P1.getX3D()-P2.getX3D(), dy13D=P1.getY3D()-P2.getY3D(), dz13D=P1.getZ3D()-P2.getZ3D();
|
|
double dx23D=P3.getX3D()-P2.getX3D(), dy23D=P3.getY3D()-P2.getY3D(), dz23D=P3.getZ3D()-P2.getZ3D();
|
|
double n1=Math.sqrt(dx13D*dx13D+dy13D*dy13D+dz13D*dz13D);
|
|
double n2=Math.sqrt(dx23D*dx23D+dy23D*dy23D+dz23D*dz23D);
|
|
if (n1<1e-9||n2<1e-9) {
|
|
Valid=false;
|
|
return;
|
|
}
|
|
double pscal=dx13D*dx23D+dy13D*dy23D+dz13D*dz23D;
|
|
A3D=Math.acos(pscal/n1/n2);
|
|
}
|
|
Valid=true;
|
|
if (Fixed) {
|
|
double FixedAlpha=0;
|
|
try {
|
|
FixedAlpha=E.getValue()/180*Math.PI;
|
|
} catch (final Exception e) {
|
|
return;
|
|
}
|
|
if (P3.moveableBy(this)) {
|
|
dx=P3.getX()-X;
|
|
dy=P3.getY()-Y;
|
|
double r=Math.sqrt(dx*dx+dy*dy);
|
|
if (r<1e-9) {
|
|
r=1e-9;
|
|
}
|
|
P3.move(X+Math.cos(A1+FixedAlpha)*r, Y+Math.sin(A1+FixedAlpha)*r);
|
|
A2=A1+FixedAlpha;
|
|
} else {
|
|
Fixed=false;
|
|
}
|
|
if (Fixed) {
|
|
A=FixedAlpha;
|
|
P3.movedBy(this);
|
|
P1.movedBy(this);
|
|
}
|
|
} else if (!Obtuse&&A>Math.PI) {
|
|
A1=A2;
|
|
A=2*Math.PI-A;
|
|
A2=A1+A;
|
|
}
|
|
}
|
|
}
|
|
double x[]=new double[4], y[]=new double[4];
|
|
double x3D[]= new double[4], y3D[]= new double[4], z3D[]= new double[4];
|
|
double xx3D, yy3D, zz3D;
|
|
double xx, yy, zz;
|
|
|
|
@Override
|
|
public void paint(final MyGraphics g, final ZirkelCanvas zc) {
|
|
if (zc.is3D()&&P1.is3D()&&P2.is3D()&&P3.is3D()) { // angle 3D
|
|
//final double xx1=P1.getX()-P2.getX();
|
|
//final double yy1=P1.getY()-P2.getY();
|
|
//final double xx2=P3.getX()-P2.getX();
|
|
//final double yy2=P3.getY()-P2.getY();
|
|
double xx3D1=P1.getX3D()-P2.getX3D();
|
|
double yy3D1=P1.getY3D()-P2.getY3D();
|
|
double zz3D1=P1.getZ3D()-P2.getZ3D();
|
|
double d3D1=Math.sqrt(xx3D1*xx3D1+yy3D1*yy3D1+zz3D1*zz3D1);
|
|
double xx3D2=P3.getX3D()-P2.getX3D();
|
|
double yy3D2=P3.getY3D()-P2.getY3D();
|
|
double zz3D2=P3.getZ3D()-P2.getZ3D();
|
|
double d3D2=Math.sqrt(xx3D2*xx3D2+yy3D2*yy3D2+zz3D2*zz3D2);
|
|
xx3D1/=d3D1; // on normalise
|
|
yy3D1/=d3D1;
|
|
zz3D1/=d3D1;
|
|
xx3D2/=d3D2;
|
|
yy3D2/=d3D2;
|
|
zz3D2/=d3D2;
|
|
final double x3DP2=P2.getX3D();
|
|
final double y3DP2=P2.getY3D();
|
|
final double z3DP2=P2.getZ3D();
|
|
final double xO=zc.getConstruction().find("O").getX();
|
|
final double yO=zc.getConstruction().find("O").getY();
|
|
final double deltaxX=zc.getConstruction().find("X").getX()-xO;
|
|
final double deltaxY=zc.getConstruction().find("Y").getX()-xO;
|
|
final double deltaxZ=zc.getConstruction().find("Z").getX()-xO;
|
|
final double deltayX=zc.getConstruction().find("X").getY()-yO;
|
|
final double deltayY=zc.getConstruction().find("Y").getY()-yO;
|
|
final double deltayZ=zc.getConstruction().find("Z").getY()-yO;
|
|
double R3D=getDisplaySize(zc);
|
|
if (!Valid||mustHide(zc)) {
|
|
return;
|
|
}
|
|
final double R=zc.col(getDisplaySize(zc))-zc.col(0);
|
|
final double c1=zc.col(X)-R, r1=zc.row(Y)-R;
|
|
// paint:
|
|
double DA=(A2-A1)/Math.PI*180;
|
|
if (DA<0) {
|
|
DA+=360;
|
|
} else if (DA>=360) {
|
|
DA-=360;
|
|
}
|
|
|
|
if (visible(zc)) {
|
|
if (isStrongSelected()&&g instanceof MainGraphics) {
|
|
((MainGraphics) g).drawMarkerArc(c1+R, r1+R, R, A1/Math.PI*180, DA);
|
|
}
|
|
if (Filled) {
|
|
if (DisplaySize==RECT) { // Dibs : sert à rien ?
|
|
|
|
final double dx1=Math.cos(A1), dy1=Math.sin(A1), dx2=Math.cos(A1+DA/180*Math.PI), dy2=Math.sin(A1+DA/180*Math.PI);
|
|
double dx3=dx1+dx2, dy3=dy1+dy2;
|
|
if (DA>180) {
|
|
dx3=-dx3;
|
|
dy3=-dy3;
|
|
}
|
|
if (Selected||getColorType()!=THIN) {
|
|
g.setColor(this);
|
|
g.drawLine(c1+R+R*dx1, r1+R-R*dy1, c1+R+R*dx3, r1+R-R*dy3);
|
|
g.drawLine(c1+R+R*dx3, r1+R-R*dy3, c1+R+R*dx2, r1+R-R*dy2);
|
|
}
|
|
x[0]=c1+R;
|
|
y[0]=r1+R;
|
|
x[1]=c1+R+R*dx1;
|
|
y[1]=r1+R-R*dy1;
|
|
x[2]=c1+R+R*dx3;
|
|
y[2]=r1+R-R*dy3;
|
|
x[3]=c1+R+R*dx2;
|
|
y[3]=r1+R-R*dy2;
|
|
g.fillPolygon(x, y, 4, false,
|
|
getColorType()!=THICK, this);
|
|
} else { // angle 3D rempli
|
|
if (Math.abs(A3D-Math.PI/2)<0.00002) { // angle 3D droit
|
|
try {
|
|
R3D/=1.4;
|
|
x3D[0]=x3DP2;
|
|
y3D[0]=y3DP2;
|
|
z3D[0]=z3DP2;
|
|
x3D[1]=x3DP2+R3D*xx3D1;
|
|
y3D[1]=y3DP2+R3D*yy3D1;
|
|
z3D[1]=z3DP2+R3D*zz3D1;
|
|
x3D[2]=x3DP2+R3D*(xx3D1+xx3D2);
|
|
y3D[2]=y3DP2+R3D*(yy3D1+yy3D2);
|
|
z3D[2]=z3DP2+R3D*(zz3D1+zz3D2);
|
|
x3D[3]=x3DP2+R3D*xx3D2;
|
|
y3D[3]=y3DP2+R3D*yy3D2;
|
|
z3D[3]=z3DP2+R3D*zz3D2;
|
|
x[0]=xO+x3D[0]*deltaxX+y3D[0]*deltaxY+z3D[0]*deltaxZ;
|
|
y[0]=yO+x3D[0]*deltayX+y3D[0]*deltayY+z3D[0]*deltayZ;
|
|
x[1]=xO+x3D[1]*deltaxX+y3D[1]*deltaxY+z3D[1]*deltaxZ;
|
|
y[1]=yO+x3D[1]*deltayX+y3D[1]*deltayY+z3D[1]*deltayZ;
|
|
x[2]=xO+x3D[2]*deltaxX+y3D[2]*deltaxY+z3D[2]*deltaxZ;
|
|
y[2]=yO+x3D[2]*deltayX+y3D[2]*deltayY+z3D[2]*deltayZ;
|
|
x[3]=xO+x3D[3]*deltaxX+y3D[3]*deltaxY+z3D[3]*deltaxZ;
|
|
y[3]=yO+x3D[3]*deltayX+y3D[3]*deltayY+z3D[3]*deltayZ;
|
|
x[0]=zc.col(x[0]); y[0]=zc.row(y[0]);
|
|
x[1]=zc.col(x[1]); y[1]=zc.row(y[1]);
|
|
x[2]=zc.col(x[2]); y[2]=zc.row(y[2]);
|
|
x[3]=zc.col(x[3]); y[3]=zc.row(y[3]);
|
|
} catch (final Exception e) {
|
|
System.out.println("exception angle");
|
|
}
|
|
g.fillPolygon(x, y, 4, false, getColorType()!=THICK,
|
|
this);
|
|
g.setColor(this);
|
|
g.drawLine(x[1], y[1], x[2], y[2]);
|
|
g.drawLine(x[2], y[2], x[3], y[3]);
|
|
}
|
|
else { // pas droit
|
|
g.setColor(this);
|
|
final PolygonDrawer pd=new PolygonDrawer(true,g, this);
|
|
final double h=zc.dx(zc.getOne());
|
|
double pvectx1=yy3D1*zz3D2-zz3D1*yy3D2; // Objectif : obtenir le "bon vecteur normal" à P2P1
|
|
double pvecty1=zz3D1*xx3D2-xx3D1*zz3D2;
|
|
double pvectz1=xx3D1*yy3D2-yy3D1*xx3D2;
|
|
//final double norme1=Math.sqrt(pvectx1*pvectx1+pvecty1*pvecty1+pvectz1*pvectz1);
|
|
//pvectx1/=norme1; pvecty1/=norme1; pvectz1/=norme1;
|
|
double pvectx2=pvecty1*zz3D1-pvectz1*yy3D1;
|
|
double pvecty2=pvectz1*xx3D1-pvectx1*zz3D1;
|
|
double pvectz2=pvectx1*yy3D1-pvecty1*xx3D1;
|
|
final double norme2=Math.sqrt(pvectx2*pvectx2+pvecty2*pvecty2+pvectz2*pvectz2);
|
|
pvectx2/=norme2; pvecty2/=norme2; pvectz2/=norme2;
|
|
//final double ux=xx3D1/d3D1, uy=yy3D1/d3D1, uz=zz3D1/d3D1;
|
|
double alpha=0;
|
|
boolean valid=false;
|
|
int compteur=0;
|
|
ArrayList<Double> cx= new ArrayList<Double>(), cy=new ArrayList<Double>();
|
|
cx.add(0.0); cy.add(0.0); //juste pour coordonner des indices
|
|
while (alpha<=A3D) {
|
|
try {
|
|
xx3D=x3DP2+R3D*(Math.cos(alpha)*xx3D1+Math.sin(alpha)*pvectx2);
|
|
yy3D=y3DP2+R3D*(Math.cos(alpha)*yy3D1+Math.sin(alpha)*pvecty2);
|
|
zz3D=z3DP2+R3D*(Math.cos(alpha)*zz3D1+Math.sin(alpha)*pvectz2);
|
|
xx=xO+xx3D*deltaxX+yy3D*deltaxY+zz3D*deltaxZ;
|
|
yy=yO+xx3D*deltayX+yy3D*deltayY+zz3D*deltayZ;
|
|
final double c=zc.col(xx), r=zc.row(yy);
|
|
cx.add(c); cy.add(r);
|
|
if (valid) {
|
|
pd.drawTo(c, r);
|
|
compteur++;
|
|
} else {
|
|
|
|
pd.startPolygon(c, r);
|
|
}
|
|
valid=true;
|
|
} catch (final RuntimeException e) {
|
|
System.out.println("runtime exception");
|
|
valid=false;
|
|
}
|
|
alpha+=h;
|
|
}
|
|
pd.finishPolygon();
|
|
final double ccx[]= new double[compteur+2], ccy[]= new double[compteur+2];
|
|
ccx[0]=zc.col(xO+x3DP2*deltaxX+y3DP2*deltaxY+z3DP2*deltaxZ);
|
|
ccy[0]=zc.row(yO+x3DP2*deltayX+y3DP2*deltayY+z3DP2*deltayZ);
|
|
for (int i=1; i<compteur+2; i++) {
|
|
ccx[i]= cx.get(i);ccy[i]= cy.get(i);
|
|
}
|
|
g.fillPolygon(ccx, ccy, compteur+2, false, getColorType()!=THICK,
|
|
this);
|
|
}
|
|
// fin bloc pas droit
|
|
|
|
}
|
|
|
|
} else { // 3D pas rempli
|
|
g.setColor(this);
|
|
if (DisplaySize==RECT) {
|
|
final double dx1=Math.cos(A1), dy1=Math.sin(A1), dx2=Math.cos(A1+DA/180*Math.PI), dy2=Math.sin(A1+DA/180*Math.PI);
|
|
g.drawLine(c1+R+R*dx1, r1+R-R*dy1, c1+R+R*(dx1+dx2), r1+R-R*(dy1+dy2));
|
|
g.drawLine(c1+R+R*(dx1+dx2), r1+R-R*(dy1+dy2), c1+R+R*dx2, r1+R-R*dy2);
|
|
} else {
|
|
if (Math.abs(A3D-Math.PI/2)<0.00002) {
|
|
|
|
try {
|
|
R3D/=1.4;
|
|
x3D[0]=x3DP2;
|
|
y3D[0]=y3DP2;
|
|
z3D[0]=z3DP2;
|
|
x3D[1]=x3DP2+R3D*xx3D1;
|
|
y3D[1]=y3DP2+R3D*yy3D1;
|
|
z3D[1]=z3DP2+R3D*zz3D1;
|
|
x3D[2]=x3DP2+R3D*(xx3D1+xx3D2);
|
|
y3D[2]=y3DP2+R3D*(yy3D1+yy3D2);
|
|
z3D[2]=z3DP2+R3D*(zz3D1+zz3D2);
|
|
x3D[3]=x3DP2+R3D*xx3D2;
|
|
y3D[3]=y3DP2+R3D*yy3D2;
|
|
z3D[3]=z3DP2+R3D*zz3D2;
|
|
x[0]=xO+x3D[0]*deltaxX+y3D[0]*deltaxY+z3D[0]*deltaxZ;
|
|
y[0]=yO+x3D[0]*deltayX+y3D[0]*deltayY+z3D[0]*deltayZ;
|
|
x[1]=xO+x3D[1]*deltaxX+y3D[1]*deltaxY+z3D[1]*deltaxZ;
|
|
y[1]=yO+x3D[1]*deltayX+y3D[1]*deltayY+z3D[1]*deltayZ;
|
|
x[2]=xO+x3D[2]*deltaxX+y3D[2]*deltaxY+z3D[2]*deltaxZ;
|
|
y[2]=yO+x3D[2]*deltayX+y3D[2]*deltayY+z3D[2]*deltayZ;
|
|
x[3]=xO+x3D[3]*deltaxX+y3D[3]*deltaxY+z3D[3]*deltaxZ;
|
|
y[3]=yO+x3D[3]*deltayX+y3D[3]*deltayY+z3D[3]*deltayZ;
|
|
x[0]=zc.col(x[0]); y[0]=zc.row(y[0]);
|
|
x[1]=zc.col(x[1]); y[1]=zc.row(y[1]);
|
|
x[2]=zc.col(x[2]); y[2]=zc.row(y[2]);
|
|
x[3]=zc.col(x[3]); y[3]=zc.row(y[3]);
|
|
} catch (final Exception e) {
|
|
System.out.println("exception angle");
|
|
}
|
|
//g.setColor(this);
|
|
g.drawLine(x[1], y[1], x[2], y[2]);
|
|
g.drawLine(x[2], y[2], x[3], y[3]);
|
|
} else {
|
|
final PolygonDrawer pd=new PolygonDrawer(true,g, this);
|
|
final double h=zc.dx(zc.getOne());
|
|
double pvectx1=yy3D1*zz3D2-zz3D1*yy3D2; // Objectif : obtenir le "bon vecteur normal" à P2P1
|
|
double pvecty1=zz3D1*xx3D2-xx3D1*zz3D2;
|
|
double pvectz1=xx3D1*yy3D2-yy3D1*xx3D2;
|
|
//final double norme1=Math.sqrt(pvectx1*pvectx1+pvecty1*pvecty1+pvectz1*pvectz1);
|
|
//pvectx1/=norme1; pvecty1/=norme1; pvectz1/=norme1;
|
|
double pvectx2=pvecty1*zz3D1-pvectz1*yy3D1;
|
|
double pvecty2=pvectz1*xx3D1-pvectx1*zz3D1;
|
|
double pvectz2=pvectx1*yy3D1-pvecty1*xx3D1;
|
|
final double norme2=Math.sqrt(pvectx2*pvectx2+pvecty2*pvecty2+pvectz2*pvectz2);
|
|
pvectx2/=norme2; pvecty2/=norme2; pvectz2/=norme2;
|
|
//final double ux=xx3D1/d3D1, uy=yy3D1/d3D1, uz=zz3D1/d3D1;
|
|
double alpha=0;
|
|
boolean valid=false;
|
|
while (alpha<=A3D) {
|
|
try {
|
|
xx3D=x3DP2+R3D*(Math.cos(alpha)*xx3D1+Math.sin(alpha)*pvectx2);
|
|
yy3D=y3DP2+R3D*(Math.cos(alpha)*yy3D1+Math.sin(alpha)*pvecty2);
|
|
zz3D=z3DP2+R3D*(Math.cos(alpha)*zz3D1+Math.sin(alpha)*pvectz2);
|
|
xx=xO+xx3D*deltaxX+yy3D*deltaxY+zz3D*deltaxZ;
|
|
yy=yO+xx3D*deltayX+yy3D*deltayY+zz3D*deltayZ;
|
|
final double c=zc.col(xx), r=zc.row(yy);
|
|
if (valid) {
|
|
pd.drawTo(c, r);
|
|
} else {
|
|
|
|
pd.startPolygon(c, r);
|
|
}
|
|
valid=true;
|
|
} catch (final RuntimeException e) {
|
|
System.out.println("runtime exception");
|
|
valid=false;
|
|
}
|
|
alpha+=h;
|
|
}
|
|
pd.finishPolygon();
|
|
//g.setColor(this);
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
final String s=translateToUnicode(getDisplayText());
|
|
if (!s.equals("")) {
|
|
g.setLabelColor(this);
|
|
setFont(g);
|
|
DisplaysText=true;
|
|
final double dx=Math.cos(A1+A/2), dy=Math.sin(A1+A/2);
|
|
// if (s.equals("90"+getUnit()) || Name.startsWith("."))
|
|
// {
|
|
//
|
|
// if (KeepClose)
|
|
// { double d=Math.sqrt(XcOffset*XcOffset+YcOffset*YcOffset);
|
|
// TX1=zc.col(X+d*dx)-3;
|
|
// TY1=zc.row(Y+d*dy)-3;
|
|
// TX2=TX1+9;
|
|
// TY2=TY1+9;
|
|
// g.drawRect(zc.col(X+d*dx)-1,
|
|
// zc.row(Y+d*dy)-1,3,3);
|
|
// }
|
|
// else
|
|
// { TX1=zc.col(X+zc.dx(R*LabelScale)*dx+XcOffset)-3;
|
|
// TY1=zc.row(Y+zc.dy(R*LabelScale)*dy+YcOffset)-3;
|
|
// TX2=TX1+9;
|
|
// TY2=TY1+9;
|
|
// g.drawRect(zc.col(X+zc.dx(R*LabelScale)*dx+XcOffset)-1,
|
|
// zc.row(Y+zc.dy(R*LabelScale)*dy+YcOffset)-1,3,3);
|
|
// }
|
|
// }
|
|
// else
|
|
// {
|
|
|
|
if (KeepClose) {
|
|
final double d=Math.sqrt(XcOffset*XcOffset+YcOffset*YcOffset);
|
|
drawCenteredLabel(g, s, zc, X+d*dx, Y+d*dy, 0, 0);
|
|
} else {
|
|
drawCenteredLabel(g, s, zc, X+zc.dx(R*LabelScale)*dx, Y+zc.dy(R*LabelScale)*dy, XcOffset, YcOffset);
|
|
}
|
|
// }
|
|
}
|
|
}
|
|
else { // angle 2D
|
|
|
|
if (!Valid||mustHide(zc)) {
|
|
return;
|
|
}
|
|
final double R=zc.col(getDisplaySize(zc))-zc.col(0);
|
|
final double c1=zc.col(X)-R, r1=zc.row(Y)-R;
|
|
// paint:
|
|
double DA=(A2-A1)/Math.PI*180;
|
|
if (DA<0) {
|
|
DA+=360;
|
|
} else if (DA>=360) {
|
|
DA-=360;
|
|
}
|
|
|
|
if (visible(zc)) {
|
|
if (isStrongSelected()&&g instanceof MainGraphics) {
|
|
((MainGraphics) g).drawMarkerArc(c1+R, r1+R, R, A1/Math.PI*180, DA);
|
|
}
|
|
if (Filled) {
|
|
if (DisplaySize==RECT) {
|
|
|
|
final double dx1=Math.cos(A1), dy1=Math.sin(A1), dx2=Math.cos(A1+DA/180*Math.PI), dy2=Math.sin(A1+DA/180*Math.PI);
|
|
double dx3=dx1+dx2, dy3=dy1+dy2;
|
|
if (DA>180) {
|
|
dx3=-dx3;
|
|
dy3=-dy3;
|
|
}
|
|
if (Selected||getColorType()!=THIN) {
|
|
g.setColor(this);
|
|
g.drawLine(c1+R+R*dx1, r1+R-R*dy1, c1+R+R*dx3, r1+R-R*dy3);
|
|
g.drawLine(c1+R+R*dx3, r1+R-R*dy3, c1+R+R*dx2, r1+R-R*dy2);
|
|
}
|
|
x[0]=c1+R;
|
|
y[0]=r1+R;
|
|
x[1]=c1+R+R*dx1;
|
|
y[1]=r1+R-R*dy1;
|
|
x[2]=c1+R+R*dx3;
|
|
y[2]=r1+R-R*dy3;
|
|
x[3]=c1+R+R*dx2;
|
|
y[3]=r1+R-R*dy2;
|
|
g.fillPolygon(x, y, 4, false,
|
|
getColorType()!=THICK, this);
|
|
} else {
|
|
if (Math.abs(DA-90)<0.0000001) {
|
|
|
|
final double dx1=Math.cos(A1), dy1=Math.sin(A1), dx2=Math.cos(A1+DA/180*Math.PI), dy2=Math.sin(A1+DA/180*Math.PI);
|
|
final double dx3=dx1+dx2, dy3=dy1+dy2;
|
|
x[0]=c1;
|
|
y[0]=r1;
|
|
x[0]=c1+R;
|
|
y[0]=r1+R;
|
|
x[1]=c1+R+R*dx1;
|
|
y[1]=r1+R-R*dy1;
|
|
x[2]=c1+R+R*dx3;
|
|
y[2]=r1+R-R*dy3;
|
|
x[3]=c1+R+R*dx2;
|
|
y[3]=r1+R-R*dy2;
|
|
g.fillPolygon(x, y, 4, false, getColorType()!=THICK,
|
|
this);
|
|
g.setColor(this);
|
|
g.drawLine(x[1], y[1], x[2], y[2]);
|
|
g.drawLine(x[2], y[2], x[3], y[3]);
|
|
} else {
|
|
g.fillArc(c1, r1, 2*R, 2*R, A1/Math.PI*180, DA,
|
|
Selected||getColorType()!=THIN,
|
|
getColorType()!=THICK, true, this);
|
|
}
|
|
}
|
|
} else {
|
|
g.setColor(this);
|
|
if (DisplaySize==RECT) {
|
|
final double dx1=Math.cos(A1), dy1=Math.sin(A1), dx2=Math.cos(A1+DA/180*Math.PI), dy2=Math.sin(A1+DA/180*Math.PI);
|
|
g.drawLine(c1+R+R*dx1, r1+R-R*dy1, c1+R+R*(dx1+dx2), r1+R-R*(dy1+dy2));
|
|
g.drawLine(c1+R+R*(dx1+dx2), r1+R-R*(dy1+dy2), c1+R+R*dx2, r1+R-R*dy2);
|
|
} else {
|
|
if (Math.abs(DA-90)<0.0000001) {
|
|
|
|
final double dx1=Math.cos(A1), dy1=Math.sin(A1), dx2=Math.cos(A1+DA/180*Math.PI), dy2=Math.sin(A1+DA/180*Math.PI);
|
|
final double dx3=dx1+dx2, dy3=dy1+dy2;
|
|
x[1]=c1+R+R*dx1;
|
|
y[1]=r1+R-R*dy1;
|
|
x[2]=c1+R+R*dx3;
|
|
y[2]=r1+R-R*dy3;
|
|
x[3]=c1+R+R*dx2;
|
|
y[3]=r1+R-R*dy2;
|
|
g.setColor(this);
|
|
g.drawLine(x[1], y[1], x[2], y[2]);
|
|
g.drawLine(x[2], y[2], x[3], y[3]);
|
|
} else {
|
|
g.drawCircleArc(c1+R, r1+R, R, A1/Math.PI*180,
|
|
DA, this);
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
final String s=translateToUnicode(getDisplayText());
|
|
if (!s.equals("")) {
|
|
g.setLabelColor(this);
|
|
setFont(g);
|
|
DisplaysText=true;
|
|
final double dx=Math.cos(A1+A/2), dy=Math.sin(A1+A/2);
|
|
// if (s.equals("90"+getUnit()) || Name.startsWith("."))
|
|
// {
|
|
//
|
|
// if (KeepClose)
|
|
// { double d=Math.sqrt(XcOffset*XcOffset+YcOffset*YcOffset);
|
|
// TX1=zc.col(X+d*dx)-3;
|
|
// TY1=zc.row(Y+d*dy)-3;
|
|
// TX2=TX1+9;
|
|
// TY2=TY1+9;
|
|
// g.drawRect(zc.col(X+d*dx)-1,
|
|
// zc.row(Y+d*dy)-1,3,3);
|
|
// }
|
|
// else
|
|
// { TX1=zc.col(X+zc.dx(R*LabelScale)*dx+XcOffset)-3;
|
|
// TY1=zc.row(Y+zc.dy(R*LabelScale)*dy+YcOffset)-3;
|
|
// TX2=TX1+9;
|
|
// TY2=TY1+9;
|
|
// g.drawRect(zc.col(X+zc.dx(R*LabelScale)*dx+XcOffset)-1,
|
|
// zc.row(Y+zc.dy(R*LabelScale)*dy+YcOffset)-1,3,3);
|
|
// }
|
|
// }
|
|
// else
|
|
// {
|
|
|
|
if (KeepClose) {
|
|
final double d=Math.sqrt(XcOffset*XcOffset+YcOffset*YcOffset);
|
|
drawCenteredLabel(g, s, zc, X+d*dx, Y+d*dy, 0, 0);
|
|
} else {
|
|
drawCenteredLabel(g, s, zc, X+zc.dx(R*LabelScale)*dx, Y+zc.dy(R*LabelScale)*dy, XcOffset, YcOffset);
|
|
}
|
|
// }
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean canKeepClose() {
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public void setKeepClose(final double x, final double y) {
|
|
KeepClose=true;
|
|
XcOffset=x-X;
|
|
YcOffset=y-Y;
|
|
}
|
|
|
|
double getDisplaySize(final ZirkelCanvas zc) {
|
|
double R=zc.dx(12*zc.pointSize());
|
|
if (DisplaySize==SMALL||DisplaySize==RECT) {
|
|
R/=2;
|
|
} else if (DisplaySize==LARGER) {
|
|
R*=2;
|
|
} else if (DisplaySize==LARGE) {
|
|
final double dx=P1.getX()-X, dy=P1.getY()-Y;
|
|
R=Math.sqrt(dx*dx+dy*dy);
|
|
}
|
|
return R;
|
|
}
|
|
|
|
public double getLength() {
|
|
return A;
|
|
}
|
|
|
|
@Override
|
|
public boolean fixed() {
|
|
return Fixed;
|
|
}
|
|
|
|
@Override
|
|
public void setFixed(final boolean flag) {
|
|
Fixed=flag;
|
|
updateText();
|
|
}
|
|
|
|
@Override
|
|
public void setFixed(final String s) {
|
|
Fixed=true;
|
|
E=new Expression(s, getConstruction(), this);
|
|
updateText();
|
|
}
|
|
|
|
@Override
|
|
public boolean canFix() {
|
|
return P3.moveableBy(this);
|
|
}
|
|
|
|
@Override
|
|
public void printArgs(final XmlWriter xml) {
|
|
if (P1!=null) {
|
|
xml.printArg("first", P1.getName());
|
|
xml.printArg("root", P2.getName());
|
|
xml.printArg("second", P3.getName());
|
|
}
|
|
if (DisplaySize==SMALL) {
|
|
xml.printArg("display", "small");
|
|
}
|
|
if (DisplaySize==NORMALSIZE) {
|
|
xml.printArg("display", "normalsize");
|
|
}
|
|
if (DisplaySize==LARGE) {
|
|
xml.printArg("display", "large");
|
|
}
|
|
if (DisplaySize==LARGER) {
|
|
xml.printArg("display", "larger");
|
|
}
|
|
if (DisplaySize==RECT) {
|
|
xml.printArg("display", "rectangle");
|
|
}
|
|
if (Filled) {
|
|
xml.printArg("filled", "true");
|
|
}
|
|
if (Fixed&&E!=null) {
|
|
xml.printArg("fixed", E.toString());
|
|
}
|
|
if (!Obtuse) {
|
|
xml.printArg("acute", "true");
|
|
}
|
|
super.printArgs(xml);
|
|
}
|
|
|
|
|
|
@Override
|
|
public void setDisplaySize(final int i) {
|
|
DisplaySize=i;
|
|
}
|
|
|
|
@Override
|
|
public int getDisplaySize() {
|
|
return DisplaySize;
|
|
}
|
|
|
|
@Override
|
|
public Enumeration depending() {
|
|
super.depending();
|
|
if (P1==null) {
|
|
return DL.elements();
|
|
}
|
|
if (!Fixed) {
|
|
return depset(P1, P2, P3);
|
|
} else {
|
|
depset(P1, P2, P3);
|
|
final Enumeration e=E.getDepList().elements();
|
|
while (e.hasMoreElements()) {
|
|
DL.add((ConstructionObject) e.nextElement());
|
|
}
|
|
return DL.elements();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean equals(final ConstructionObject o) {
|
|
if (!(o instanceof AngleObject)||!o.valid()) {
|
|
return false;
|
|
}
|
|
final AngleObject l=(AngleObject) o;
|
|
return equals(X, l.X)&&equals(Y, l.Y)&&equals(A1, l.A1)&&equals(A2, l.A2);
|
|
}
|
|
public static char Translation[]={'a', '\u03B1', 'A', '\u0391', 'b',
|
|
'\u03B2', 'B', '\u0392', 'c', '\u03B3', 'C', '\u0393', 'd',
|
|
'\u03B4', 'D', '\u0394', 'e', '\u03B5', 'E', '\u0395', 'f',
|
|
'\u03D5', 'F', '\u03A6', 'g', '\u03B3', 'G', '\u0393', 'h',
|
|
'\u03B7', 'H', '\u0397', 'i', '\u03B9', 'I', '\u0399', 'k',
|
|
'\u03BA', 'K', '\u039A', 'l', '\u03BB', 'L', '\u039B', 'm',
|
|
'\u03BC', 'M', '\u039C', 'n', '\u03BD', 'N', '\u039D', 'o',
|
|
'\u03BF', 'O', '\u03A9', 'p', '\u03C0', 'P', '\u03A0', 'q',
|
|
'\u03C7', 'Q', '\u03A7', 'r', '\u03C1', 'R', '\u03A1', 's',
|
|
'\u03C3', 'S', '\u03A3', 't', '\u03C4', 'T', '\u03A4', 'u',
|
|
'\u03C5', 'U', '\u03A5', 'v', '\u03C8', 'V', '\u03A8', 'w',
|
|
'\u03C9', 'W', '\u03A9', 'x', '\u03BE', 'X', '\u039E', 'y',
|
|
'\u03C7', 'Y', '\u03A7', 'z', '\u03B6', 'Z', '\u0396',};
|
|
|
|
public static String translateToUnicode(final String s) {
|
|
if (s.startsWith("$")) {
|
|
return s;
|
|
}
|
|
if (s.indexOf('\\')<0) {
|
|
return s;
|
|
}
|
|
final StringBuffer b=new StringBuffer();
|
|
for (int i=0; i<s.length(); i++) {
|
|
char c=s.charAt(i);
|
|
if (c!='\\') {
|
|
b.append(c);
|
|
} else {
|
|
i++;
|
|
if (i<s.length()) {
|
|
c=s.charAt(i);
|
|
if (c=='0') {
|
|
int n=0;
|
|
i++;
|
|
while (i<s.length()) {
|
|
final char ch=s.charAt(i);
|
|
if (ch>='0'&&ch<='9') {
|
|
n=n*16+(int) (ch-'0');
|
|
} else if (ch>='A'&&ch<='F') {
|
|
n=n*16+(int) (ch-'A'+10);
|
|
} else {
|
|
break;
|
|
}
|
|
i++;
|
|
}
|
|
if (n>0) {
|
|
c=(char) n;
|
|
b.append(c);
|
|
}
|
|
i--;
|
|
continue;
|
|
}
|
|
int j=0;
|
|
for (j=0; j<Translation.length; j+=2) {
|
|
if (Translation[j]==c) {
|
|
b.append(Translation[j+1]);
|
|
break;
|
|
}
|
|
}
|
|
if (j>=Translation.length) {
|
|
b.append(c);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return b.toString();
|
|
}
|
|
|
|
@Override
|
|
public void translate() {
|
|
P1=(PointObject) P1.getTranslation();
|
|
P2=(PointObject) P2.getTranslation();
|
|
P3=(PointObject) P3.getTranslation();
|
|
if (Fixed) {
|
|
try {
|
|
setFixed(E.toString());
|
|
E.translate();
|
|
} catch (final Exception e) {
|
|
Fixed=false;
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public String getE() {
|
|
if (Fixed&&E!=null) {
|
|
return E.toString();
|
|
} else {
|
|
if (P1.is3D()&&P2.is3D()&&P3.is3D()) return ""+round(A3D/Math.PI*180);
|
|
else return ""+round(A/Math.PI*180);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public double getValue() throws ConstructionException {
|
|
if (!Valid) {
|
|
throw new InvalidException("exception.invalid");
|
|
} else {
|
|
if (P1.is3D()&&P2.is3D()&&P3.is3D()) return A3D/Math.PI*180;
|
|
else return A/Math.PI*180;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void setFilled(final boolean flag) {
|
|
Filled=flag;
|
|
}
|
|
|
|
@Override
|
|
public boolean isFilled() {
|
|
return Filled;
|
|
}
|
|
|
|
@Override
|
|
public boolean maybeTransparent() {
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public boolean isFilledForSelect() {
|
|
return false;
|
|
}
|
|
|
|
public double containsInside(final PointObject P) {
|
|
final double dx=P.getX()-X, dy=P.getY()-Y;
|
|
double a=Math.atan2(dy, dx);
|
|
if (a<0) {
|
|
a+=2*Math.PI;
|
|
}
|
|
if (a<A1) {
|
|
a+=2*Math.PI;
|
|
}
|
|
final double c=1e-5;
|
|
if (a>A1&&a<A1+A) {
|
|
return 1;
|
|
} else if (a>A1-c&&a<A1+A+c) {
|
|
return 0.5;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
public boolean keepInside(final PointObject P) {
|
|
if (containsInside(P)>0) {
|
|
return true;
|
|
}
|
|
final double x=P.getX(), y=P.getY();
|
|
final double x1=P2.getX(), y1=P2.getY();
|
|
double xmin=x1, ymin=y1, dmin=1e20;
|
|
double x2=P1.getX(), y2=P1.getY();
|
|
double dx=x2-x1, dy=y2-y1;
|
|
double r=dx*dx+dy*dy;
|
|
double h=dx*(x-x1)/r+dy*(y-y1)/r;
|
|
if (h<0) {
|
|
h=0;
|
|
}
|
|
double xh=x1+h*dx, yh=y1+h*dy;
|
|
double dist=Math.sqrt((x-xh)*(x-xh)+(y-yh)*(y-yh));
|
|
if (dist<dmin) {
|
|
dmin=dist;
|
|
xmin=xh;
|
|
ymin=yh;
|
|
}
|
|
x2=P3.getX();
|
|
y2=P3.getY();
|
|
dx=x2-x1;
|
|
dy=y2-y1;
|
|
r=dx*dx+dy*dy;
|
|
h=dx*(x-x1)/r+dy*(y-y1)/r;
|
|
if (h<0) {
|
|
h=0;
|
|
}
|
|
xh=x1+h*dx;
|
|
yh=y1+h*dy;
|
|
dist=Math.sqrt((x-xh)*(x-xh)+(y-yh)*(y-yh));
|
|
if (dist<dmin) {
|
|
dmin=dist;
|
|
xmin=xh;
|
|
ymin=yh;
|
|
}
|
|
P.move(xmin, ymin);
|
|
return false;
|
|
}
|
|
|
|
public PointObject getP1() {
|
|
return P1;
|
|
}
|
|
|
|
public PointObject getP2() {
|
|
return P2;
|
|
}
|
|
|
|
public PointObject getP3() {
|
|
return P3;
|
|
}
|
|
}
|
|
|
|
|