Make first real commit: copy of CaRMetal 4.2.8

This commit is contained in:
Glen Whitney 2018-09-04 22:51:42 -04:00
parent 002acfc88e
commit c312811084
1120 changed files with 226843 additions and 1 deletions

File diff suppressed because it is too large Load diff

BIN
rene/zirkel/objects/.DS_Store vendored Normal file

Binary file not shown.

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,785 @@
/*
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: LineObject.java
import java.awt.Rectangle;
import java.util.Enumeration;
import java.util.Vector;
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.ExpressionColor;
import rene.zirkel.expression.InvalidException;
import rene.zirkel.graphics.MyGraphics;
import rene.zirkel.graphics.MainGraphics;
public class AreaObject extends ConstructionObject implements InsideObject,
PointonObject, MoveableObject {
static Count N=new Count();
double xpoints[]=new double[3], ypoints[]=new double[3];
double R, X, Y, A;
public Vector V;
boolean Filled=true;
private PointObject preview=null;
public AreaObject(final Construction c, final Vector v) {
super(c);
V=v;
validate();
updateText();
Global.getParameter("unit.area", "");
}
@Override
public void setDefaults() {
setShowName(Global.getParameter("options.area.shownames", false));
setShowValue(Global.getParameter("options.area.showvalues", false));
setColor(Global.getParameter("options.area.color", 0), Global.getParameter("options.area.pcolor", (ExpressionColor) null, this));
setColorType(Global.getParameter("options.area.colortype", 0));
setFilled(Global.getParameter("options.area.filled", true));
setSolid(Global.getParameter("options.area.solid", false));
setHidden(Cn.Hidden);
setObtuse(Cn.Obtuse);
// setSolid(Cn.Solid);
setLarge(Cn.LargeFont);
setBold(Cn.BoldFont);
setPartial(Cn.Partial);
}
@Override
public void setTargetDefaults() {
setShowName(Global.getParameter("options.area.shownames", false));
setShowValue(Global.getParameter("options.area.showvalues", false));
setColor(Global.getParameter("options.area.color", 0), Global.getParameter("options.area.pcolor", (ExpressionColor) null, this));
setColorType(Global.getParameter("options.area.colortype", 0));
setFilled(Global.getParameter("options.area.filled", true));
setSolid(Global.getParameter("options.area.solid", false));
}
public void setPreviewPoint(PointObject p){
preview=p;
}
public void clearPreviewPoint(){
preview=null;
}
@Override
public String getTag() {
return "Polygon";
}
@Override
public void updateText() {
String Text=Global.name("text.area");
final Enumeration en=V.elements();
boolean first=true;
while (en.hasMoreElements()) {
final PointObject p=(PointObject) en.nextElement();
if (!first) {
Text=Text+", ";
} else {
Text=Text+" ";
}
first=false;
Text=Text+p.getName();
}
setText(Text);
}
@Override
public void validate() {
final Enumeration e=V.elements();
while (e.hasMoreElements()) {
if (!((ConstructionObject) e.nextElement()).valid()) {
Valid=false;
return;
}
}
int realsize=(preview==null)?V.size():V.size()+1;
if (realsize<2) {
Valid=false;
return;
}
final Enumeration en=V.elements();
double x=0, y=0;
while (en.hasMoreElements()) {
final PointObject p=(PointObject) en.nextElement();
x+=p.getX();
y+=p.getY();
}
X=x/V.size();
Y=y/V.size();
A=area();
Valid=true;
}
@Override
public void paint(final MyGraphics g, final ZirkelCanvas zc) {
if (!Valid||mustHide(zc)) {
return;
}
final int n=(preview==null)?V.size():V.size()+1;
if (xpoints.length!=n) {
xpoints=new double[n];
ypoints=new double[n];
}
if (visible(zc)) {
final Enumeration e=V.elements();
int i=0;
while (e.hasMoreElements()) {
final PointObject p=(PointObject) e.nextElement();
xpoints[i]=zc.col(p.getX());
ypoints[i]=zc.row(p.getY());
if (i>0) {
if (isStrongSelected()&&g instanceof MainGraphics) {
((MainGraphics) g).drawMarkerLine(xpoints[i-1],
ypoints[i-1], xpoints[i], ypoints[i]);
}
}
i++;
}
if (preview!=null){
xpoints[i]=zc.col(preview.getX());
ypoints[i]=zc.row(preview.getY());
i++;
}
if (i>1) {
if (isStrongSelected()&&g instanceof MainGraphics) {
((MainGraphics) g).drawMarkerLine(xpoints[i-1],
ypoints[i-1], xpoints[0], ypoints[0]);
}
}
g.fillPolygon(xpoints, ypoints, n, this);
}
final String s=getDisplayText();
if (!s.equals("")) {
// if (getColorIndex() == 0 && getColorType() == THICK) {
// g.setColor(Color.gray.brighter());
// } else {
// g.setColor(Color.black);
// }
DisplaysText=true;
TX1=zc.col(X+XcOffset);
TY1=zc.row(Y+YcOffset);
setFont(g);
drawLabel(g, s);
}
}
@Override
public String getDisplayValue() {
// return ""+round(Math.abs(A), ZirkelCanvas.LengthsFactor);
return Global.getLocaleNumber(Math.abs(A), "lengths");
}
@Override
public void printArgs(final XmlWriter xml) {
if (!Filled) {
xml.printArg("filled", "false");
}
final Enumeration e=V.elements();
int n=1;
while (e.hasMoreElements()) {
final ConstructionObject o=(ConstructionObject) e.nextElement();
xml.printArg("point"+n, o.getName());
n++;
}
super.printArgs(xml);
}
@Override
public Enumeration depending() {
super.depending();
final Enumeration e=V.elements();
while (e.hasMoreElements()) {
final ConstructionObject o=(ConstructionObject) e.nextElement();
DL.add(o);
}
return DL.elements();
}
@Override
public void translate() {
final Enumeration e=V.elements();
final Vector w=new Vector();
while (e.hasMoreElements()) {
final ConstructionObject o=(ConstructionObject) e.nextElement();
w.addElement(o.getTranslation());
}
V=w;
}
@Override
public boolean isInRect(Rectangle r, ZirkelCanvas zc) {
final Enumeration e=V.elements();
while (e.hasMoreElements()) {
final PointObject p=(PointObject) e.nextElement();
if (!r.contains(zc.col(p.getX()), zc.row(p.getY()))) {
return false;
}
}
return true;
}
@Override
public boolean nearto(final int c, final int r, final ZirkelCanvas zc) {
if (!displays(zc)) {
return false;
}
return contains(zc.x(c), zc.y(r));
}
@Override
public boolean nearto(final int c, final int r, final boolean ignorefill,
final ZirkelCanvas zc) {
if (!displays(zc)) {
return false;
}
if (contains(zc.x(c), zc.y(r), zc.dx(zc.selectionSize()))) {
if (ignorefill) {
return OnBoundary;
} else {
return true;
}
}
return false;
}
boolean OnBoundary;
public boolean contains(final double x, final double y, final double eps) {
if (!Valid) {
return false;
}
OnBoundary=false;
final PointObject First=(PointObject) V.elementAt(0);
PointObject P=First;
if (Math.max(Math.abs(P.getX()-x), Math.abs(P.getY()-y))<eps) {
OnBoundary=true;
return true;
}
final Enumeration e=V.elements();
double a=Math.atan2(P.getX()-x, P.getY()-y);
double sum=0;
PointObject Q;
while (e.hasMoreElements()) {
Q=(PointObject) e.nextElement();
if (Math.max(Math.abs(Q.getX()-x), Math.abs(Q.getY()-y))<eps) {
OnBoundary=true;
return true;
}
final double b=Math.atan2(Q.getX()-x, Q.getY()-y);
double d=b-a;
if (d>Math.PI) {
d=d-2*Math.PI;
} else if (d<-Math.PI) {
d=d+2*Math.PI;
}
if (Math.abs(Math.abs(d)-Math.PI)<0.1) {
OnBoundary=true;
return true;
}
a=b;
P=Q;
sum+=d;
}
Q=First;
final double b=Math.atan2(Q.getX()-x, Q.getY()-y);
double d=b-a;
if (d>Math.PI) {
d=d-2*Math.PI;
} else if (d<-Math.PI) {
d=d+2*Math.PI;
}
if (Math.abs(Math.abs(d)-Math.PI)<0.1) {
OnBoundary=true;
return true;
}
sum+=d;
return Math.abs(sum)>=Math.PI/2;
}
public boolean contains(final double x, final double y) {
return contains(x, y, 1e-4);
}
// This one is better than "contains" method :
public boolean contains2(final double x, final double y) {
if (!Valid) {
return false;
}
final int npoints=V.size();
if (npoints<=2) {
return false;
}
int hits=0;
final PointObject last=(PointObject) V.get(npoints-1);
double lastx=last.getX();
double lasty=last.getY();
double curx, cury;
final Enumeration e=V.elements();
for (int i=0; i<npoints; lastx=curx, lasty=cury, i++) {
final PointObject p=(PointObject) e.nextElement();
curx=p.getX();
cury=p.getY();
if (cury==lasty) {
continue;
}
double leftx;
if (curx<lastx) {
if (x>=lastx) {
continue;
}
leftx=curx;
} else {
if (x>=curx) {
continue;
}
leftx=lastx;
}
double test1, test2;
if (cury<lasty) {
if (y<cury||y>=lasty) {
continue;
}
if (x<leftx) {
hits++;
continue;
}
test1=x-curx;
test2=y-cury;
} else {
if (y<lasty||y>=cury) {
continue;
}
if (x<leftx) {
hits++;
continue;
}
test1=x-lastx;
test2=y-lasty;
}
if (test1<(test2/(lasty-cury)*(lastx-curx))) {
hits++;
}
}
return ((hits&1)!=0);
}
public double area() {
if (!Valid) {
return -1;
}
final PointObject First=(PointObject) V.elementAt(0);
PointObject P=First;
final Enumeration e=V.elements();
double sum=0;
PointObject Q;
while (e.hasMoreElements()) {
Q=(PointObject) e.nextElement();
sum+=(Q.getX()-X)*(P.getY()-Y)-(Q.getY()-Y)*(P.getX()-X);
P=Q;
}
Q=First;
sum+=(Q.getX()-X)*(P.getY()-Y)-(Q.getY()-Y)*(P.getX()-X);
return sum/2;
}
@Override
public boolean equals(final ConstructionObject o) {
if (!(o instanceof AreaObject)||!o.valid()) {
return false;
}
final AreaObject a=(AreaObject) o;
final int n=V.size(), m=a.V.size();
final PointObject p[]=new PointObject[n];
V.copyInto(p);
final PointObject pa[]=new PointObject[m];
a.V.copyInto(pa);
double x0=0, y0=0;
for (int i=0; i<m; i++) {
boolean r=true;
int j=0, kj=0;
while (true) {
int k=i+kj;
if (k>=m) {
k-=m;
}
if (!p[j].equals(pa[k])) {
if (j==0||!between(x0, y0, p[j].getX(), p[j].getY(), pa[k].getX(), pa[k].getY())) {
r=false;
break;
}
} else {
x0=p[j].getX();
y0=p[j].getY();
j++;
}
kj++;
if (j>=n||kj>=m) {
break;
}
}
if (r&&kj>=m) {
return true;
}
}
for (int i=0; i<m; i++) {
boolean r=true;
int j=0, kj=0;
while (true) {
int k=i+kj;
if (k>=m) {
k-=m;
}
if (!p[n-j-1].equals(pa[k])) {
if (j==0||!between(x0, y0, p[n-j-1].getX(), p[n-j-1].getY(), pa[k].getX(), pa[k].getY())) {
r=false;
break;
}
} else {
x0=p[n-j-1].getX();
y0=p[n-j-1].getY();
j++;
}
kj++;
if (j>=n||kj>=m) {
break;
}
}
if (r&&kj>=m) {
return true;
}
}
return false;
}
public boolean between(final double x0, final double y0, final double x1,
final double y1, final double x, final double y) {
double lambda;
if (Math.abs(x1-x0)>Math.abs(y1-y0)) {
lambda=(x-x0)/(x1-x0);
} else {
lambda=(y-y0)/(y1-y0);
}
return Math.abs(x0+lambda*(x1-x0)-x)<1e-10&&Math.abs(y0+lambda*(y1-y0)-y)<1e-10;
}
@Override
public double getValue() throws ConstructionException {
if (!Valid) {
throw new InvalidException("exception.invalid");
} else {
return A;
}
}
@Override
public boolean maybeTransparent() {
return true;
}
@Override
public void setFilled(final boolean flag) {
Filled=flag;
}
@Override
public boolean isFilled() {
return Filled;
}
@Override
public boolean onlynearto(final int x, final int y, final ZirkelCanvas zc) {
return false;
}
public void keepBaricentricCoords(final PointObject P) {
if ((P.BarycentricCoordsInitialzed)&&(V.size()>2)) {
final PointObject AA=(PointObject) V.get(0);
final PointObject BB=(PointObject) V.get(1);
final PointObject CC=(PointObject) V.get(2);
final double xa=AA.getX(), ya=AA.getY();
final double xb=BB.getX(), yb=BB.getY();
final double xc=CC.getX(), yc=CC.getY();
final double xm=xa+P.Gx*(xb-xa)+P.Gy*(xc-xa);
final double ym=ya+P.Gx*(yb-ya)+P.Gy*(yc-ya);
P.move(xm, ym);
} else {
P.computeBarycentricCoords();
}
}
@Override
public int getDistance(final PointObject P) {
final double x=P.getX(), y=P.getY();
final Enumeration e=V.elements();
PointObject p=(PointObject) e.nextElement();
double x1=p.getX(), y1=p.getY();
final double xstart=x1, ystart=y1;
int count=0;
double xmin=x1, ymin=y1, dmin=1e20;
while (e.hasMoreElements()) {
p=(PointObject) e.nextElement();
final double x2=p.getX(), y2=p.getY();
final double dx=x2-x1, dy=y2-y1;
final double r=dx*dx+dy*dy;
if (r>1e-5) {
double h=dx*(x-x1)/r+dy*(y-y1)/r;
if (h>1) {
h=1;
} else if (h<0) {
h=0;
}
final double xh=x1+h*dx, yh=y1+h*dy;
final double dist=Math.sqrt((x-xh)*(x-xh)+(y-yh)*(y-yh));
if (dist<dmin) {
dmin=dist;
xmin=xh;
ymin=yh;
}
}
count++;
x1=x2;
y1=y2;
}
final double x2=xstart, y2=ystart;
final double dx=x2-x1, dy=y2-y1;
final double r=dx*dx+dy*dy;
if (r>1e-5) {
double h=dx*(x-x1)/r+dy*(y-y1)/r;
if (h>1) {
h=1;
} else if (h<0) {
h=0;
}
final double xh=x1+h*dx, yh=y1+h*dy;
final double dist=Math.sqrt((x-xh)*(x-xh)+(y-yh)*(y-yh));
if (dist<dmin) {
dmin=dist;
xmin=xh;
ymin=yh;
}
}
final double dd=Math.sqrt((P.getX()-xmin)*(P.getX()-xmin)+(P.getY()-ymin)*(P.getY()-ymin));
return (int) Math.round(dd*Cn.getPixel());
}
public void project(final PointObject P) {
final double x=P.getX(), y=P.getY();
final Enumeration e=V.elements();
PointObject p=(PointObject) e.nextElement();
double x1=p.getX(), y1=p.getY();
final double xstart=x1, ystart=y1;
int count=0;
double xmin=x1, ymin=y1, dmin=1e20, hmin=0;
while (e.hasMoreElements()) {
p=(PointObject) e.nextElement();
final double x2=p.getX(), y2=p.getY();
final double dx=x2-x1, dy=y2-y1;
final double r=dx*dx+dy*dy;
if (r>1e-5) {
double h=dx*(x-x1)/r+dy*(y-y1)/r;
if (h>1) {
h=1;
} else if (h<0) {
h=0;
}
final double xh=x1+h*dx, yh=y1+h*dy;
final double dist=Math.sqrt((x-xh)*(x-xh)+(y-yh)*(y-yh));
if (dist<dmin) {
dmin=dist;
xmin=xh;
ymin=yh;
hmin=count+h;
}
}
count++;
x1=x2;
y1=y2;
}
final double x2=xstart, y2=ystart;
final double dx=x2-x1, dy=y2-y1;
final double r=dx*dx+dy*dy;
if (r>1e-5) {
double h=dx*(x-x1)/r+dy*(y-y1)/r;
if (h>1) {
h=1;
} else if (h<0) {
h=0;
}
final double xh=x1+h*dx, yh=y1+h*dy;
final double dist=Math.sqrt((x-xh)*(x-xh)+(y-yh)*(y-yh));
if (dist<dmin) {
dmin=dist;
xmin=xh;
ymin=yh;
hmin=count+h;
}
}
P.move(xmin, ymin);
P.setA(hmin);
}
public void project(final PointObject P, final double alpha) {
final int i=(int) Math.floor(alpha);
final double h=alpha-i;
if (i<0||i>=V.size()) {
project(P);
return;
}
final PointObject P1=(PointObject) V.elementAt(i);
PointObject P2;
if (i==V.size()-1) {
P2=(PointObject) V.elementAt(0);
} else {
P2=(PointObject) V.elementAt(i+1);
}
P.setXY(P1.getX()+h*(P2.getX()-P1.getX()), P1.getY()+h*(P2.getY()-P1.getY()));
}
public double containsInside(final PointObject P) {
final boolean inside=contains2(P.getX(), P.getY());
if (inside&&OnBoundary) {
return 0.5;
} else if (inside) {
return 1;
}
return 0;
}
public boolean keepInside(final PointObject P) {
keepBaricentricCoords(P);
if (contains2(P.getX(), P.getY())) {
return true;
}
project(P);
return false;
}
public void dragTo(final double x, final double y) {
final Enumeration e=V.elements();
int i=0;
while (e.hasMoreElements()) {
final PointObject p=(PointObject) e.nextElement();
p.move(xd[i]+(x-x1), yd[i]+(y-y1));
i++;
}
}
@Override
public void move(final double x, final double y) {
}
public boolean moveable() {
if (V==null) {
return false;
}
final Enumeration e=V.elements();
while (e.hasMoreElements()) {
if (!((PointObject) e.nextElement()).moveable()) {
return false;
}
}
return true;
}
double xd[], yd[], x1, y1;
public void startDrag(final double x, final double y) {
if (xd==null||xd.length!=V.size()) {
xd=new double[V.size()];
yd=new double[V.size()];
}
final Enumeration e=V.elements();
int i=0;
while (e.hasMoreElements()) {
final PointObject p=(PointObject) e.nextElement();
xd[i]=p.getX();
yd[i]=p.getY();
i++;
}
x1=x;
y1=y;
}
public double getOldX() {
return 0;
}
public double getOldY() {
return 0;
}
@Override
public void snap(final ZirkelCanvas zc) {
if (moveable()) {
final Enumeration e=V.elements();
while (e.hasMoreElements()) {
final PointObject p=(PointObject) e.nextElement();
p.snap(zc);
}
}
}
public boolean canInteresectWith(final ConstructionObject o) {
if (o instanceof PointonObject) {
final ConstructionObject line=(ConstructionObject) o;
final Enumeration e=V.elements();
{
final PointObject P=(PointObject) e.nextElement();
if (line.contains(P)) {
return false;
}
}
}
return true;
}
public void repulse(final PointObject P) {
project(P);
}
}

View file

@ -0,0 +1,118 @@
/*
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: LineCircleIntersectionObject.java
import rene.util.xml.XmlWriter;
import rene.zirkel.construction.Construction;
public class AxisFunctionIntersectionObject extends IntersectionObject {
public AxisFunctionIntersectionObject(final Construction c,
final AxisObject P1, final FunctionObject P2, final boolean first) {
super(c, P1, P2);
First = first;
validate();
}
// public void updateCircleDep ()
// { ((QuadricObject)P2).addDep(this);
// ((PrimitiveLineObject)P1).addDep(this);
// }
// public void validate ()
// { boolean oldvalid=Valid;
// if (!P1.valid() || !P2.valid()) Valid=false;
// else Valid=true;
// if (!Valid) return;
//
// Coordinates c=AxisObject.intersect(
// (PrimitiveLineObject)P1,(FunctionObject)P2);
//
// if (c==null)
// { if (oldvalid && getConstruction().shouldSwitch())
// { doSwitch();
// if (!getConstruction().noteSwitch()) Switched=false;
// }
// else if (oldvalid && Alternate && Away==null &&
// getConstruction().canAlternate())
// { First=!First;
// }
// Valid=false; return;
// }
// double X1,Y1;
// if (getAway()!=null)
// { double x=getAway().getX(),y=getAway().getY();
// double r=(x-c.X)*(x-c.X)+(y-c.Y)*(y-c.Y);
// double r1=(x-c.X1)*(x-c.X1)+(y-c.Y1)*(y-c.Y1);
// boolean flag=(r>r1);
// if (!StayAway) flag=!flag;
// if (flag)
// {
// setXY(c.X,c.Y);
// X1=c.X1; Y1=c.Y1;
// }
// else
// {
// setXY(c.X1,c.Y1);
// X1=c.X; Y1=c.Y;
// }
// }
// else
// { if (First) { setXY(c.X,c.Y); X1=c.X1; Y1=c.Y1; }
// else { setXY(c.X1,c.Y1); X1=c.X; Y1=c.Y; }
// }
// if (Restricted)
// {
//
// if (!((PrimitiveLineObject)P1).contains(X,Y)) {
// if (!((PrimitiveLineObject)P1).contains(X1,Y1)){
// Valid=false;
// }else{
// setXY(X1,Y1);
// }
//
// }
//
//
// }
// }
@Override
public void printArgs(final XmlWriter xml) {
super.printArgs(xml);
if (First)
xml.printArg("which", "first");
else
xml.printArg("which", "second");
}
@Override
public boolean isSwitchable() {
return true;
}
@Override
public boolean canAlternate() {
return true;
}
}

View file

@ -0,0 +1,183 @@
/*
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: SegmentObject.java
import java.util.Enumeration;
import rene.util.xml.XmlWriter;
import rene.zirkel.ZirkelCanvas;
import rene.zirkel.construction.Construction;
import rene.zirkel.graphics.MyGraphics;
public class AxisObject extends PrimitiveLineObject {
public AxisObject(final Construction c, final boolean xaxis) {
super(c, (xaxis) ? "xAxis" : "yAxis");
X1 = 0;
Y1 = 0;
if (xaxis) {
DX = 1;
DY = 0;
} else {
DX = 0;
DY = 1;
}
updateText();
}
@Override
public void setName() {
// if (DX==1) {
// Name="xaxis"+getN();
// } else {
// Name="yaxis"+getN();
// }
//
}
@Override
public boolean nearto(final int c, final int r, final ZirkelCanvas zc) {
if (!displays(zc)) {
return false;
}
if (!zc.getAxis_show()) {
return false;
}
// compute point at c,r
final double x = zc.x(c), y = zc.y(r);
// compute distance from x,y
final double d = (x - X1) * DY - (y - Y1) * DX;
// scale in screen coordinates
Value = Math.abs(zc.col(zc.minX() + d) - zc.col(zc.minX()));
return Value < zc.selectionSize() * 2;
}
// public static Coordinates intersect(PrimitiveLineObject l, FunctionObject
// q) {
//
//
//
// return new Coordinates(0, 0);
// }
// public String getTag() {
// return "Axis";
// }
@Override
public void printArgs(final XmlWriter xml) {
if (DX == 1) {
xml.printArg("xaxis", "true");
} else {
xml.printArg("yaxis", "true");
}
}
@Override
public Enumeration depending() {
DL.reset();
return DL.elements();
}
public double getLength() {
return 0;
}
@Override
public void translate() {
P1 = (PointObject) P1.getTranslation();
}
@Override
public boolean contains(final PointObject p) {
return false;
}
@Override
public void paint(final MyGraphics g, final ZirkelCanvas zc) {
if (!Valid || mustHide(zc)) {
return;
}
// if (isStrongSelected()&&g instanceof MyGraphics13) {
// ((MyGraphics13)
// g).drawMarkerLine(zc.col(-5),zc.row(1),zc.col(5),zc.row(1));
// }
if (zc.getAxis_show()) {
if (indicated()) {
g.setColor(this);
if (DX == 1) {
g.drawLine(0, zc.row(0), zc.IW, zc.row(0), this);
} else {
g.drawLine(zc.col(0), 0, zc.col(0), zc.IH, this);
}
}
}
}
@Override
public void updateText() {
if (DX == 1) {
setText("X axis");
} else {
setText("Y axis");
}
}
public void dragTo(final double x, final double y) {
}
@Override
public void move(final double x, final double y) {
}
public boolean moveable() {
return false;
}
double x1, y1, x2, y2, x3, y3;
public void startDrag(final double x, final double y) {
}
@Override
public void snap(final ZirkelCanvas zc) {
}
public double getOldX() {
return 0;
}
public double getOldY() {
return 0;
}
}

View file

@ -0,0 +1,104 @@
/*
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 java.util.Enumeration;
import rene.util.xml.XmlWriter;
import rene.gui.Global;
import rene.zirkel.construction.Construction;
import rene.zirkel.construction.ConstructionException;
import rene.zirkel.expression.InvalidException;
public class Circle3Object extends PrimitiveCircleObject {
protected PointObject P1, P2;
public Circle3Object(final Construction c, final PointObject p1,
final PointObject p2, final PointObject p3) {
super(c, p3);
P1 = p1;
P2 = p2;
validate();
updateText();
}
@Override
public String getTag() {
return "Circle3";
}
@Override
public void updateText() {
setText(text3(Global.name("text.circle3"), M.getName(), P1.getName(),
P2.getName()));
}
@Override
public void validate() {
super.validate();
if (!M.valid() || !P1.valid() || !P2.valid()) {
Valid = false;
return;
} else {
Valid = true;
X = M.getX();
Y = M.getY();
// compute normalized vector in the direction of the line:
final double DX = P2.getX() - P1.getX(), DY = P2.getY() - P1.getY();
R = Math.sqrt(DX * DX + DY * DY);
if (R < 0) {
R = 0;
}
}
}
@Override
public void printArgs(final XmlWriter xml) {
xml.printArg("from", P1.getName());
xml.printArg("to", P2.getName());
super.printArgs(xml);
}
@Override
public double getValue() throws ConstructionException {
if (!Valid)
throw new InvalidException("exception.invalid");
else
return R;
}
@Override
public Enumeration depending() {
super.depending();
return depset(P1, P2);
}
@Override
public void translate() {
P1 = (PointObject) P1.getTranslation();
P2 = (PointObject) P2.getTranslation();
super.translate();
}
}

View file

@ -0,0 +1,202 @@
/*
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: CircleIntersectionObject.java
import rene.util.xml.XmlWriter;
import rene.zirkel.construction.Construction;
import rene.zirkel.structures.Coordinates;
public class CircleIntersectionObject extends IntersectionObject {
public CircleIntersectionObject(final Construction c,
final PrimitiveCircleObject P1, final PrimitiveCircleObject P2,
final boolean first) {
super(c, P1, P2);
First=first;
validate();
}
@Override
public void updateCircleDep() {
((PrimitiveCircleObject) P1).addDep(this);
((PrimitiveCircleObject) P2).addDep(this);
}
@Override
public void validate() {
// System.out.println(getName()+":"+First);
final boolean oldvalid=Valid;
if (!P1.valid()||!P2.valid()) {
Valid=false;
} else {
Valid=true;
}
if (!Valid) {
return;
}
final Coordinates c=PrimitiveCircleObject.intersect(
(PrimitiveCircleObject) P1, (PrimitiveCircleObject) P2);
if (c==null) {
if (oldvalid&&getConstruction().shouldSwitch()) {
doSwitch();
if (!getConstruction().noteSwitch()) {
Switched=false;
}
} else if (oldvalid&&Alternate&&Away==null
&&getConstruction().canAlternate()) {
First=!First;
}
Valid=false;
return;
}
// Gestion des intersections droite/cercle (droite au sens large) en mode DP :
if (((P1.isDPLineOrSegmentObject())&&(P2.isDPCircleObject()))
||(((P2.isDPLineOrSegmentObject())&&(P1.isDPCircleObject())))) {
// arc doit être la droite ou le segment hyperbolique :
PrimitiveCircleObject arc=(PrimitiveCircleObject) ((P1.isDPLineOrSegmentObject())?P1:P2);
// Calcul de la coord z du produit vectoriel OStart ^ OEnd :
Double prod1=(arc.getStart().getX()-arc.getX())*(arc.getEnd().getY()-arc.getY())
-(arc.getStart().getY()-arc.getY())*(arc.getEnd().getX()-arc.getX());
// Calcul de la coord z du produit vectoriel OI ^ OJ (I et J sont les deux pts
// d'intersection calculés) :
Double prod2=(c.X-arc.getX())*(c.Y1-arc.getY())-(c.Y-arc.getY())*(c.X1-arc.getX());
if (prod1*prod2>0) {
if (First) {
setXY(c.X, c.Y);
} else {
setXY(c.X1, c.Y1);
}
} else {
if (First) {
setXY(c.X1, c.Y1);
} else {
setXY(c.X, c.Y);
}
}
if (Restricted) {
if (!(((PrimitiveCircleObject) P1).getStart()==this||((PrimitiveCircleObject) P1).getEnd()==this)
&&!((PrimitiveCircleObject) P1).contains(X, Y)) {
Valid=false;
}
if (!(((PrimitiveCircleObject) P2).getStart()==this||((PrimitiveCircleObject) P2).getEnd()==this)
&&!((PrimitiveCircleObject) P2).contains(X, Y)) {
Valid=false;
}
}
return;
}
// Gestion des intersections droite/droite (droite au sens large) en mode DP :
else if((P1.isDPLineOrSegmentObject())&&(P2.isDPLineOrSegmentObject())) {
PrimitiveCircleObject Hz=Cn.getHZ();
if ((Hz!=P1)&&(Hz!=P2)) {
final double r=(c.X)*(c.X)+(c.Y)*(c.Y);
final double r1=(c.X1)*(c.X1)+(c.Y1)*(c.Y1);
final double R=Hz.getR()*Hz.getR();
if ((r>R)||(r1>R)) {
if (r<R) {
setXY(c.X, c.Y);
} else {
setXY(c.X1, c.Y1);
}
if (Restricted) {
if (!(((PrimitiveCircleObject) P1).getStart()==this||((PrimitiveCircleObject) P1).getEnd()==this)
&&!((PrimitiveCircleObject) P1).contains(X, Y)) {
Valid=false;
}
if (!(((PrimitiveCircleObject) P2).getStart()==this||((PrimitiveCircleObject) P2).getEnd()==this)
&&!((PrimitiveCircleObject) P2).contains(X, Y)) {
Valid=false;
}
}
return;
}
}
}
final PointObject oa=getAway();
if (oa!=null) {
final double x=oa.getX(), y=oa.getY();
final double r=(x-c.X)*(x-c.X)+(y-c.Y)*(y-c.Y);
final double r1=(x-c.X1)*(x-c.X1)+(y-c.Y1)*(y-c.Y1);
boolean flag=(r>r1);
if (!StayAway) {
flag=!flag;
}
if (flag) {
setXY(c.X, c.Y);
} else {
setXY(c.X1, c.Y1);
}
} else {
if (First) {
setXY(c.X, c.Y);
} else {
setXY(c.X1, c.Y1);
}
}
if (Restricted) {
if (!(((PrimitiveCircleObject) P1).getStart()==this||((PrimitiveCircleObject) P1).getEnd()==this)
&&!((PrimitiveCircleObject) P1).contains(X, Y)) {
Valid=false;
}
if (!(((PrimitiveCircleObject) P2).getStart()==this||((PrimitiveCircleObject) P2).getEnd()==this)
&&!((PrimitiveCircleObject) P2).contains(X, Y)) {
Valid=false;
}
}
}
@Override
public void printArgs(final XmlWriter xml) {
super.printArgs(xml);
if (First) {
xml.printArg("which", "first");
} else {
xml.printArg("which", "second");
}
}
@Override
public boolean isSwitchable() {
return true;
}
@Override
public boolean canAlternate() {
return true;
}
}

View file

@ -0,0 +1,272 @@
/*
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: CircleObject.java
import java.awt.Frame;
import java.util.Enumeration;
import rene.dialogs.Warning;
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.expression.Expression;
import rene.zirkel.expression.InvalidException;
public class CircleObject extends PrimitiveCircleObject implements
MoveableObject {
protected PointObject P2;
boolean Fixed = false;
Expression E;
boolean ExpressionFailed;
boolean Ellipse = false;
public CircleObject(final Construction c, final PointObject p1,
final PointObject p2) {
super(c, p1);
P2 = p2;
validate();
updateText();
}
@Override
public String getTag() {
return "Circle";
}
@Override
public void updateText() {
if (Fixed) {
if (E == null) {
setText(text3(Global.name("text.circle.fixed"), M.getName(), P2
.getName(), "" + round(R)));
} else {
setText(text3(Global.name("text.circle.fixed"), M.getName(), P2
.getName(), "\"" + E.toString() + "\""));
}
} else {
setText(text2(Global.name("text.circle"), M.getName(), P2.getName()));
}
}
@Override
public void validate() {
super.validate();
ExpressionFailed = false;
if (!M.valid() || !P2.valid()) {
Valid = false;
return;
} else {
Valid = true;
X = M.getX();
Y = M.getY();
final double X2 = P2.getX(), Y2 = P2.getY();
// compute normalized vector in the direction of the line:
final double DX = X2 - X, DY = Y2 - Y;
R = Math.sqrt(DX * DX + DY * DY);
if (Fixed) {
if (!P2.moveableBy(this)) {
Fixed = false;
} else {
try {
double FixR = E.getValue();
if (FixR < 0) {
FixR = 0;
}
if (R < 1e-10) {
P2.move(X + FixR, Y);
} else {
P2.move(X + DX * FixR / R, Y + DY * FixR / R);
}
R = FixR;
P2.movedBy(this);
} catch (final Exception e) {
R = 0;
P2.move(X, Y);
ExpressionFailed = true;
Valid = false;
}
}
}
}
}
@Override
public void printArgs(final XmlWriter xml) {
xml.printArg("through", P2.getName());
if (Fixed && E != null) {
xml.printArg("fixed", E.toString());
}
super.printArgs(xml);
}
@Override
public boolean canFix() {
return /* M.moveableBy(this) || */P2.moveableBy(this);
}
@Override
public boolean fixed() {
return Fixed;
}
@Override
public void setFixed(final boolean flag, final String s)
throws ConstructionException {
if (!flag || s.equals("")) {
Fixed = false;
E = null;
} else {
E = new Expression(s, getConstruction(), this);
if (!E.isValid()) {
throw new ConstructionException(E.getErrorText());
}
Fixed = true;
}
updateText();
}
@Override
public boolean nearto(final int c, final int r, final ZirkelCanvas zc) {
if (ExpressionFailed && M.valid()) {
return M.nearto(c, r, zc);
}
return super.nearto(c, r, zc);
}
public boolean isValidFix() {
return E != null && E.isValid();
}
@Override
public void updateCircleDep() {
addDep(P2);
}
@Override
public void translate() {
super.translate();
P2 = (PointObject) P2.getTranslation();
try {
setFixed(Fixed, E.toString());
E.translate();
} catch (final Exception e) {
Fixed = false;
}
}
@Override
public String getStringLength() {
if (E != null) {
return E.toString();
} else {
return "" + roundDisplay(R);
}
}
@Override
public double getValue() throws ConstructionException {
if (!Valid) {
throw new InvalidException("exception.invalid");
} else {
return R;
}
}
@Override
public Enumeration depending() {
super.depending();
if (!Fixed || E == null) {
return depset(P2);
} else {
depset(P2);
final Enumeration e = E.getDepList().elements();
while (e.hasMoreElements()) {
DL.add((ConstructionObject) e.nextElement());
}
return DL.elements();
}
}
public void setP1P2(final PointObject p1, final PointObject p2) {
M = p1;
P2 = p2;
}
public PointObject getP2() {
return P2;
}
@Override
public boolean contains(final PointObject p) {
return p == P2;
}
public void dragTo(final double x, final double y) {
M.move(x1 + (x - x3), y1 + (y - y3));
P2.move(x2 + (x - x3), y2 + (y - y3));
}
@Override
public void move(final double x, final double y) {
}
public boolean moveable() {
if (!Fixed && M.moveable() && P2.moveable()) {
return true;
}
return false;
}
double x1, y1, x2, y2, x3, y3;
public void startDrag(final double x, final double y) {
x1 = M.getX();
y1 = M.getY();
x2 = P2.getX();
y2 = P2.getY();
x3 = x;
y3 = y;
}
public double getOldX() {
return 0;
}
public double getOldY() {
return 0;
}
@Override
public void snap(final ZirkelCanvas zc) {
if (moveable()) {
M.snap(zc);
P2.snap(zc);
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,31 @@
/*
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;
public interface DriverObject {
public void clearChanges();
public boolean somethingChanged();
public boolean isDriverObject();
}

View file

@ -0,0 +1,464 @@
/*
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;
import eric.bar.JPropertiesBar;
import java.util.Enumeration;
import java.util.Vector;
import rene.gui.Global;
import rene.util.xml.XmlWriter;
import rene.zirkel.ZirkelCanvas;
import rene.zirkel.construction.Construction;
import rene.zirkel.construction.ConstructionException;
import rene.zirkel.expression.Expression;
import rene.zirkel.expression.InvalidException;
import rene.zirkel.graphics.MyGraphics;
import rene.zirkel.structures.Coordinates;
/**
*
* @author erichake
*/
public class EquationXYObject extends ConstructionObject implements
PointonObject {
Vector V=new Vector();
// Number of horizontal divisions for the full zero search algorithm :
int Dhor=100;
// canvas left,top,width,height :
double Wl=0, Wt=0, Ww=0, Wh=0;
Construction C;
Expression EY=null;
double X[]={0, 0};
String Var[]={"x", "y"};
public EquationXYObject(final Construction c, final String eq) {
super(c);
EY=new Expression(eq, c, this, Var);
updateText();
C=c;
}
public EquationXYObject(final Construction c, final String eq, final int d) {
this(c, eq);
Dhor=d;
}
public int getDhor() {
return Dhor;
}
public void setDhor(final int newDHor) {
Dhor=newDHor;
compute();
updateText();
}
@Override
public void setDefaults() {
setShowName(Global.getParameter("options.locus.shownames", false));
setShowValue(Global.getParameter("options.locus.showvalues", false));
setColor(Global.getParameter("options.locus.color", 0));
setColorType(Global.getParameter("options.locus.colortype", 0));
setFilled(Global.getParameter("options.locus.filled", false));
setHidden(Cn.Hidden);
setObtuse(Cn.Obtuse);
setSolid(Cn.Solid);
setLarge(Cn.LargeFont);
setBold(Cn.BoldFont);
}
@Override
public void setTargetDefaults() {
setShowName(Global.getParameter("options.locus.shownames", false));
setShowValue(Global.getParameter("options.locus.showvalues", false));
setColor(Global.getParameter("options.locus.color", 0));
setColorType(Global.getParameter("options.locus.colortype", 0));
setFilled(Global.getParameter("options.locus.filled", false));
}
public void setEquation(final String eq, final ZirkelCanvas zc) {
EY=new Expression(eq, C, this, Var);
compute();
updateText();
}
public double getValue(final String var) throws ConstructionException {
if (!Valid) {
throw new InvalidException("exception.invalid");
}
return (var.equals("x"))?X[0]:X[1];
}
public double evaluateF(final double x, final double y)
throws ConstructionException {
X[0]=x;
X[1]=y;
try {
return EY.getValue();
} catch (final Exception e) {
throw new ConstructionException("");
}
}
public void compute() {
Wl=C.getX()-C.getW();
Wt=C.getY()-C.getH()/2;
Ww=2*C.getW();
Wh=C.getH();
searchZerosSegments();
}
public void searchZerosSegments() {
V.clear();
final double dx=Ww/Dhor;
final double dy=dx*Math.sqrt(3)/2;
final int xn=Dhor+2;
final int yn=(int) (Wh/dy)+1;
final double[] x=new double[xn+1];
final double[] y=new double[yn+1];
final double[][] z=new double[xn+1][yn+1];
for (int i=0; i<=xn; i++) {
x[i]=Wl-dx+i*dx;
}
for (int j=0; j<=yn; j++) {
y[j]=Wt+j*dy;
}
for (int i=0; i<=xn; i++) {
for (int j=0; j<=yn; j++) {
xv[0]=x[i];
xv[1]=y[j];
if (j%2==0) {
xv[0]+=dx/2;
}
try {
z[i][j]=evaluateF(xv[0], xv[1]);
} catch (final Exception e) {
z[i][j]=0;
}
}
}
for (int i=0; i<=xn-1; i++) {
for (int j=0; j<=yn-1; j++) {
if (j%2==0) {
searchOneZerosSegment(V, x[i]+dx/2, y[j], z[i][j],
x[i], y[j+1], z[i][j+1], x[i+1], y[j+1],
z[i+1][j+1]);
searchOneZerosSegment(V, x[i]+dx/2, y[j], z[i][j],
x[i+1]+dx/2, y[j], z[i+1][j], x[i+1],
y[j+1], z[i+1][j+1]);
} else {
searchOneZerosSegment(V, x[i], y[j], z[i][j], x[i+1],
y[j], z[i+1][j], x[i]+dx/2, y[j+1],
z[i][j+1]);
searchOneZerosSegment(V, x[i+1], y[j], z[i+1][j],
x[i+1]-dx/2, y[j+1], z[i][j+1], x[i+1]+dx/2, y[j+1], z[i+1][j+1]);
}
}
}
}
public void searchOneZerosSegment(final Vector v, final double x1,
final double y1, final double z1, final double x2, final double y2,
final double z2, final double x3, final double y3, final double z3) {
if (z1*z2<0) {
double l1=z2/(z2-z1);
l1=fix(x1, y1, z1, x2, y2, z2, l1);
final double m1=1-l1;
if (z1*z3<0) {
double l2=z3/(z3-z1);
l2=fix(x1, y1, z1, x3, y3, z3, l2);
final double m2=1-l2;
v.add(new Coordinates(l1*x1+m1*x2, l1*y1+m1*y2, l2*x1+m2*x3, l2*y1+m2*y3));
} else {
double l2=z3/(z3-z2);
l2=fix(x2, y2, z2, x3, y3, z3, l2);
final double m2=1-l2;
v.add(new Coordinates(l1*x1+m1*x2, l1*y1+m1*y2, l2*x2+m2*x3, l2*y2+m2*y3));
}
} else if (z1*z3<0) {
double l1=z3/(z3-z1);
l1=fix(x1, y1, z1, x3, y3, z3, l1);
final double m1=1-l1;
double l2=z3/(z3-z2);
l2=fix(x2, y2, z2, x3, y3, z3, l2);
final double m2=1-l2;
v.add(new Coordinates(l1*x1+m1*x3, l1*y1+m1*y3, l2*x2+m2*x3, l2*y2+m2*y3));
}
}
double xv[]=new double[2];
public double fix(final double x1, final double y1, final double z1,
final double x2, final double y2, final double z2, double l1) {
try {
final double z=evaluateF(x1*l1+x2*(1-l1), y1*l1+y2*(1-l1));
if (Math.abs(z)>(Math.abs(z1)+Math.abs(z2))*1e-5) {
final double mu=1-l1, mu2=mu*mu, mu3=mu2*mu, mu4=mu3*mu;
final double h=Math.sqrt(mu4*z2*z2+((-2*mu4+4*mu3-2*mu2)*z1-2*mu2*z)*z2+(mu4-4*mu3+6*mu2-4*mu+1)*z1*z1+(-2*mu2+4*mu-2)*z*z1+z*z);
final double h1=(mu2*z2-mu2*z1+z1-z+h)/(2*(mu*z2-mu*z1+z1-z));
final double h2=(mu2*z2-mu2*z1+z1-z-h)/(2*(mu*z2-mu*z1+z1-z));
if (h1>=0&&h1<=1) {
l1=1-h1;
} else if (h2>=0&&h2<=1) {
l1=1-h2;
}
}
} catch (final Exception e) {
}
return l1;
}
@Override
public void paint(final MyGraphics g, final ZirkelCanvas zc) {
if (!Valid||mustHide(zc)) {
return;
}
Coordinates c1;
g.setColor(this);
final Enumeration e=V.elements();
while (e.hasMoreElements()) {
c1=(Coordinates) e.nextElement();
g.drawLine(zc.col(c1.X), zc.row(c1.Y), zc.col(c1.X1),
zc.row(c1.Y1), this);
}
}
@Override
public boolean nearto(final int cc, final int rr, final ZirkelCanvas zc) {
final Enumeration e=V.elements();
Coordinates c1;
while (e.hasMoreElements()) {
c1=(Coordinates) e.nextElement();
if (((Math.abs(zc.col(c1.X)-cc)+Math.abs(zc.row(c1.Y)-rr))<5)||((Math.abs(zc.col(c1.X1)-cc)+Math.abs(zc.row(c1.Y1)-rr))<5)) {
return true;
}
}
return false;
}
public int getDistance(final PointObject P) {
xx=P.getX();
yy=P.getY();
Coordinates c;
double dd, dm=0, xm1=0, ym1=0, zm1=0, xm2=0, ym2=0, zm2=0;
// search the closer segment [M1M2] :
final Enumeration e=V.elements();
if (e.hasMoreElements()) {
c=(Coordinates) e.nextElement();
xm1=c.X;
ym1=c.Y;
xm2=c.X1;
ym2=c.Y1;
dm=Math.sqrt((c.X-xx)*(c.X-xx)+(c.Y-yy)*(c.Y-yy))+Math.sqrt((c.X1-xx)*(c.X1-xx)+(c.Y1-yy)*(c.Y1-yy))-Math.sqrt((c.X-c.X1)*(c.X-c.X1)+(c.Y-c.Y1)*(c.Y-c.Y1));
} else {
return Integer.MAX_VALUE;
}
while (e.hasMoreElements()) {
c=(Coordinates) e.nextElement();
dd=Math.sqrt((c.X-xx)*(c.X-xx)+(c.Y-yy)*(c.Y-yy))+Math.sqrt((c.X1-xx)*(c.X1-xx)+(c.Y1-yy)*(c.Y1-yy))-Math.sqrt((c.X-c.X1)*(c.X-c.X1)+(c.Y-c.Y1)*(c.Y-c.Y1));
if (dd<dm) {
xm1=c.X;
ym1=c.Y;
xm2=c.X1;
ym2=c.Y1;
dm=dd;
}
}
// coords du vecteur unitaire directeur de (M1M2) :
double lg=Math.sqrt((xm2-xm1)*(xm2-xm1)+(ym2-ym1)*(ym2-ym1));
double dx=(xm2-xm1)/lg;
double dy=(ym2-ym1)/lg;
// coords du point H projeté ortho de P sur (M1M2) :
final double h=(xx-xm1)*dx+(yy-ym1)*dy;
final double xh=xm1+h*dx;
final double yh=ym1+h*dy;
// coords du vecteur unitaire directeur de (HP) :
lg=Math.sqrt((xx-xh)*(xx-xh)+(yy-yh)*(yy-yh));
dx=(xx-xh)/lg;
dy=(yy-yh)/lg;
// ten pixel length :
final double d10=10/C.getPixel();
// Try to have a very accurate precision :
try {
xm1=xh+d10*dx;
ym1=yh+d10*dy;
zm1=evaluateF(xm1, ym1);
xm2=xh-d10*dx;
ym2=yh-d10*dy;
zm2=evaluateF(xm2, ym2);
if (zm1*zm2<0) {
findRootBetween(xm1, ym1, zm1, xm2, ym2, zm2);
dd=Math.sqrt((P.getX()-xx)*(P.getX()-xx)+(P.getY()-yy)*(P.getY()-yy));
return (int) Math.round(dd*Cn.getPixel());
}
} catch (final Exception ex) {
}
// If nothing found, then sorry... :
return Integer.MAX_VALUE;
}
public void project(final PointObject P) {
xx=P.getX();
yy=P.getY();
Coordinates c;
double dd, dm=0, xm1=0, ym1=0, zm1=0, xm2=0, ym2=0, zm2=0;
// search the closer segment [M1M2] :
final Enumeration e=V.elements();
if (e.hasMoreElements()) {
c=(Coordinates) e.nextElement();
xm1=c.X;
ym1=c.Y;
xm2=c.X1;
ym2=c.Y1;
dm=Math.sqrt((c.X-xx)*(c.X-xx)+(c.Y-yy)*(c.Y-yy))+Math.sqrt((c.X1-xx)*(c.X1-xx)+(c.Y1-yy)*(c.Y1-yy))-Math.sqrt((c.X-c.X1)*(c.X-c.X1)+(c.Y-c.Y1)*(c.Y-c.Y1));
} else {
return;
}
while (e.hasMoreElements()) {
c=(Coordinates) e.nextElement();
dd=Math.sqrt((c.X-xx)*(c.X-xx)+(c.Y-yy)*(c.Y-yy))+Math.sqrt((c.X1-xx)*(c.X1-xx)+(c.Y1-yy)*(c.Y1-yy))-Math.sqrt((c.X-c.X1)*(c.X-c.X1)+(c.Y-c.Y1)*(c.Y-c.Y1));
if (dd<dm) {
xm1=c.X;
ym1=c.Y;
xm2=c.X1;
ym2=c.Y1;
dm=dd;
}
}
// coords du vecteur unitaire directeur de (M1M2) :
double lg=Math.sqrt((xm2-xm1)*(xm2-xm1)+(ym2-ym1)*(ym2-ym1));
double dx=(xm2-xm1)/lg;
double dy=(ym2-ym1)/lg;
// coords du point H projeté ortho de P sur (M1M2) :
final double h=(xx-xm1)*dx+(yy-ym1)*dy;
final double xh=xm1+h*dx;
final double yh=ym1+h*dy;
// coords du vecteur unitaire directeur de (HP) :
lg=Math.sqrt((xx-xh)*(xx-xh)+(yy-yh)*(yy-yh));
dx=(xx-xh)/lg;
dy=(yy-yh)/lg;
// ten pixel length :
final double d10=10/C.getPixel();
// Try to have a very accurate precision :
try {
xm1=xh+d10*dx;
ym1=yh+d10*dy;
zm1=evaluateF(xm1, ym1);
xm2=xh-d10*dx;
ym2=yh-d10*dy;
zm2=evaluateF(xm2, ym2);
if (zm1*zm2<0) {
findRootBetween(xm1, ym1, zm1, xm2, ym2, zm2);
P.move(xx, yy);
return;
}
} catch (final Exception ex) {
}
// If nothing found, then project on the segment (low precision) :
P.move(xh, yh);
}
double xx, yy, zz;
public void findRootBetween(final double x1, final double y1,
final double z1, final double x2, final double y2, final double z2) {
try {
xx=(x1+x2)/2;
yy=(y1+y2)/2;
zz=evaluateF(xx, yy);
if (Math.abs(zz)<1e-10) {
return;
}
if (zz*z1<0) {
findRootBetween(x1, y1, z1, xx, yy, zz);
} else {
findRootBetween(xx, yy, zz, x2, y2, z2);
}
} catch (final Exception e) {
}
}
public void project(final PointObject P, final double alpha) {
project(P);
}
public boolean canInteresectWith(final ConstructionObject o) {
return false;
}
@Override
public String getEY() {
if (EY!=null) {
return EY.toString();
} else {
return "0";
}
}
@Override
public String getDisplayValue() {
return EY.toString();
}
@Override
public String getTag() {
return "EqXY";
}
@Override
public void printArgs(final XmlWriter xml) {
xml.printArg("f", EY.toString());
xml.printArg("Dhor", String.valueOf(Dhor));
super.printArgs(xml);
}
@Override
public void updateText() {
setText(getDisplayValue()+"=0");
}
public void repulse(final PointObject P) {
project(P);
}
}

View file

@ -0,0 +1,28 @@
/*
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;
import rene.zirkel.construction.ConstructionException;
public interface Evaluator {
public double evaluateF(double x) throws ConstructionException;
}

View file

@ -0,0 +1,747 @@
/*
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: PointObject.java
import eric.JZirkelCanvas;
import java.awt.Color;
import java.awt.FontMetrics;
import java.util.Enumeration;
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;
public class ExpressionObject extends ConstructionObject implements
MoveableObject, SimulationObject, DriverObject {
protected double X, Y;
private static Count N=new Count();
public Expression E;
protected Expression EX, EY;
protected boolean Fixed;
String Prompt=Global.name("expression.value");
protected double CurrentValue=0;
protected boolean CurrentValueValid=true;
protected boolean Slider=false;
protected Expression SMin, SMax;
private String LASTE="";
private boolean isOwned=false; // tell if this expression belongs to a control
public ExpressionObject(final Construction c, final double x, final double y) {
super(c);
X=x;
Y=y;
setColor(ColorIndex, SpecialColor);
updateText();
setFixed("0");
}
@Override
public void setDefaults() {
setShowName(Global.getParameter("options.text.shownames", false));
setShowValue(true);
// setShowValue(Global.getParameter("options.text.showvalues",false));
setColor(Global.getParameter("options.text.color", 0), Global.getParameter("options.text.pcolor", (ExpressionColor) null, this));
setColorType(Global.getParameter("options.text.colortype", 0));
setHidden(Cn.Hidden);
setObtuse(Cn.Obtuse);
setSolid(Cn.Solid);
setLarge(Cn.LargeFont);
setBold(Cn.BoldFont);
setPartial(Cn.Partial);
setPrompt(this.getName()); // Dibs
}
@Override
public void setTargetDefaults() {
setShowName(Global.getParameter("options.text.shownames", false));
setShowValue(Global.getParameter("options.text.showvalues", false));
setColor(Global.getParameter("options.text.color", 0), Global.getParameter("options.text.pcolor", (ExpressionColor) null, this));
setColorType(Global.getParameter("options.text.colortype", 0));
}
@Override
public String getTag() {
return "Expression";
}
@Override
public int getN() {
return N.next();
}
@Override
public void updateText() {
if (E!=null) {
setText(text3(Global.name("text.expression"), E.toString(), ""
+roundDisplay(X), ""+roundDisplay(Y)));
} else {
setText(text3(Global.name("text.expression"), "", ""
+roundDisplay(X), ""+roundDisplay(Y)));
}
}
public double C, R, W, H; // for the expression position
public double SC, SR, SW, SH; // for the slider position in screen coord.
public double SX, SY, SD; // for the slider scale in x,y-coordinates
/**
* Paint the expression. Use value, name (i.e. tag), or slider. Remember
* slider position for nearto and drags.
*/
@Override
public void paint(final MyGraphics g, final ZirkelCanvas zc) {
DisplaysText=false;
if (!Valid||mustHide(zc)) {
return;
}
C=zc.col(X);
R=zc.row(Y);
setFont(g);
final FontMetrics fm=g.getFontMetrics();
if (isStrongSelected()&&g instanceof MyGraphics) {
((MainGraphics) g).drawMarkerRect(C-5, R-5, 10, 10);
}
g.setColor(this);
String s="";
if (showName()) // shows the tag with or without = ...
{
s=Prompt;
if (showValue()) // =, if value shows and % is not surpressed
{
if (s.endsWith("_")&&s.length()>1) {
s=s.substring(0, s.length()-1);
} else {
if (!s.equals("")) {
s=s+" = ";
}
}
} else {
s=Prompt;
}
}
if (showValue()) // show the value
{
try {
E.getValue();
double x=round(CurrentValue);
if (Slider) {
x=round(CurrentValue, 100);
}
if (Math.abs(x-Math.round(x))<1e-10) {
s=s+Global.getLocaleNumber((int) x, "edit");
// s = s + (int) x;
} else {
s=s+Global.getLocaleNumber(x, "edit");
// s = s + x;
}
} catch (final Exception e) {
s=s+"???";
}
}
s=s+Unit; // add optional unit
s=AngleObject.translateToUnicode(s); // translate \a etc.
// s=s.replace(".",",");
if (s.equals("")) // nothing to show
{
if (!Slider) {
s="-";
}
}
W=fm.stringWidth(s);
if (!s.equals("")) {
setFont(g);
R-=fm.getAscent();
H=g.drawStringExtended(s, C, R);
//W=((MyGraphics13) g).getW();//pb export eps et svg, il faut un double
}
if (Slider) // we draw an additional slider
{
final int coffset=(int) (4*zc.pointSize());
R+=H;
g.drawLine(C, R+coffset/2, C+10*coffset, R+coffset/2);
final double d=getSliderPosition();
final int size=coffset/4;
final double rslider=C+d*10*coffset;
final double cw=2*size+2;
if (getColorType()==THICK) {
g.fillOval(rslider-size-1, R+coffset/2-size-1, cw,
cw, true, false, this);
} else {
g.fillOval(rslider-size-1, R+coffset/2-size-1, cw,
cw, new Color(250, 250, 250));
g.setColor(this);
g.drawOval(rslider-size-1, R+coffset/2-size-1, cw,
cw);
}
// remember position
SC=rslider-size;
SR=R+coffset/2-size;
SW=SH=2*size;
SX=zc.x((int) C);
SY=zc.y((int) R+coffset/2-size);
SD=zc.x((int) C+10*coffset)-SX;
R-=H;
}
}
/**
* Compute the relative position, the slider must be on according to
* CurrentValue
*
* @return 0 <= position <= 1
*/
public double getSliderPosition() {
try {
final double min=SMin.getValue();
final double max=SMax.getValue();
double x=CurrentValue;
if (min>=max) {
Valid=false;
return 0;
}
if (x<min) {
x=min;
}
if (x>max) {
x=max;
}
return (x-min)/(max-min);
} catch (final Exception e) {
Valid=false;
return 0;
}
}
/**
* Set the expression according to the relative value the slider is on. 0 <=
* d <= 1.
*
* @param d
*/
public void setSliderPosition(final double d) {
try {
final double min=SMin.getValue();
final double max=SMax.getValue();
if (min>=max) {
Valid=false;
return;
}
double value=min+d*(max-min);
if (value<min) {
value=min;
}
if (value>max) {
value=max;
}
E.setValue(value); // kills expression and makes it a constant
} catch (final Exception e) {
Valid=false;
}
}
@Override
public boolean nearto(final int x, final int y, final ZirkelCanvas zc) {
DragSlider=false;
if (Valid&&!displays(zc)) {
return false;
}
if (C<=x&&x<=C+W&&R<=y&&y<=R+H) {
return true;
}
if (SC<=x&&SR<=y&&SC+SW>=x&&SR+SH>=y) {
DragSlider=true;
return true;
}
return false;
}
@Override
public double getX() {
return X;
}
@Override
public double getY() {
return Y;
}
public Expression getExp() {
return E;
}
@Override
public void move(final double x, final double y) {
X=x;
Y=y;
}
@Override
public void snap(final ZirkelCanvas zc) {
final double d=zc.getGridSize()/2;
X=Math.round(X/d)*d;
Y=Math.round(Y/d)*d;
}
@Override
public void round() {
move(round(X, ZirkelCanvas.LengthsFactor), round(Y,
ZirkelCanvas.LengthsFactor));
}
@Override
public void printArgs(final XmlWriter xml) {
if (Fixed&&EX!=null&&EX.isValid()) {
xml.printArg("x", EX.toString());
} else {
xml.printArg("x", ""+X);
}
if (Fixed&&EY!=null&&EY.isValid()) {
xml.printArg("y", EY.toString());
} else {
xml.printArg("y", ""+Y);
}
if (E!=null) {
xml.printArg("value", E.toString());
} else {
xml.printArg("value", "");
}
xml.printArg("prompt", Prompt);
if (Fixed) {
xml.printArg("fixed", "true");
}
if (Slider) {
xml.printArg("slider", "true");
xml.printArg("min", SMin.toString());
xml.printArg("max", SMax.toString());
}
}
@Override
public boolean equals(final ConstructionObject o) {
return false;
}
@Override
public void setExpression(final String expr, final Construction c)
throws ConstructionException {
E=new Expression(expr, c, this);
updateText();
}
@Override
public void setFixed(final String expr) {
E=new Expression(expr, getConstruction(), this);
updateText();
}
@Override
public String getExpression() {
if (E!=null) {
return E.toString();
} else {
return "";
}
}
// public Enumeration depending() {
// DL.reset();
// if (E != null) {
// Enumeration e = E.getDepList().elements();
// while (e.hasMoreElements()) {
// DL.add((ConstructionObject) e.nextElement());
// }
// }
// if (Fixed) {
// Enumeration e;
// if (EX != null) {
// e = EX.getDepList().elements();
// while (e.hasMoreElements()) {
// DL.add((ConstructionObject) e.nextElement());
// }
// }
// if (EY != null) {
// e = EY.getDepList().elements();
// while (e.hasMoreElements()) {
// DL.add((ConstructionObject) e.nextElement());
// }
// }
// }
// return DL.elements();
// }
@Override
public Enumeration depending() {
DL.reset();
addDepending(E);
addDepending(SMin);
addDepending(SMax);
if (Fixed) {
addDepending(EX);
addDepending(EY);
}
return DL.elements();
}
public void addDepending(final Expression EE) {
if (EE!=null) {
final Enumeration e=EE.getDepList().elements();
while (e.hasMoreElements()) {
DL.add((ConstructionObject) e.nextElement());
}
}
}
@Override
public double getValue() throws ConstructionException {
if (!CurrentValueValid) {
throw new InvalidException("");
}
return CurrentValue;
}
@Override
public String getPrompt() {
return Prompt;
}
@Override
public void setPrompt(final String prompt) {
Prompt=prompt;
}
@Override
public void translate() {
if (Slider) {
SMin.translate();
SMax.translate();
} else {
E.translate();
}
if (Fixed) {
try {
setFixed(EX.toString(), EY.toString());
EX.translate();
EY.translate();
} catch (final Exception e) {
}
}
updateText();
}
@Override
public void validate() {
double oldV;
try {
oldV=CurrentValue;
CurrentValue=E.getValue();
CurrentValueValid=true;
if (oldV!=CurrentValue) {
}
} catch (final Exception e) {
CurrentValueValid=false;
}
Valid=true;
if (Fixed&&EX!=null&&EX.isValid()) {
try {
X=EX.getValue();
} catch (final Exception e) {
Valid=false;
return;
}
}
if (Fixed&&EY!=null&&EY.isValid()) {
try {
Y=EY.getValue();
} catch (final Exception e) {
Valid=false;
return;
}
}
}
@Override
public void setFixed(final boolean flag) {
Fixed=flag;
if (!Fixed) {
EX=EY=null;
}
updateText();
}
@Override
public void setFixed(final String x, final String y) {
Fixed=true;
EX=new Expression(x, getConstruction(), this);
EY=new Expression(y, getConstruction(), this);
updateText();
}
@Override
public ConstructionObject copy(final double x, final double y) {
try {
final ExpressionObject o=(ExpressionObject) clone();
setTranslation(o);
if (Slider) {
o.setSlider(SMin.toString(), SMax.toString());
} else {
o.setExpression(E.toString(), getConstruction());
}
o.translateConditionals();
o.translate();
o.setName();
o.updateText();
o.setBreak(false);
// o.setTarget(false);
return o;
} catch (final Exception e) {
return null;
}
}
public boolean moveable() {
if (Slider) {
return true;
}
return EX==null&&EY==null;
}
public void reset() {
if (E!=null) {
E.reset();
}
}
@Override
public boolean fixed() {
return Fixed;
}
@Override
public String getEX() {
if (EX!=null) {
return EX.toString();
} else {
return ""+round(X);
}
}
@Override
public String getEY() {
if (EY!=null) {
return EY.toString();
} else {
return ""+round(Y);
}
}
public void setCurrentValue(final double x) {
CurrentValue=x;
CurrentValueValid=true;
}
// For the simulate function:
private double OldE;
/**
* Set the simulation value, remember the old value.
*/
public void setSimulationValue(final double x) {
OldE=CurrentValue;
CurrentValue=x;
}
/**
* Reset the old value.
*/
public void resetSimulationValue() {
CurrentValue=OldE;
}
/**
* Set the slider to min, max und step values.
*
* @param smin
* @param smax
* @param sstep
*/
@Override
public void setSlider(final String smin, final String smax) {
Slider=true;
SMin=new Expression(smin, getConstruction(), this);
SMax=new Expression(smax, getConstruction(), this);
}
/**
* Set or clear the slider.
*
* @param flag
*/
@Override
public void setSlider(final boolean flag) {
Slider=flag;
}
double oldx, oldy, startx, starty;
boolean DragSlider;
public void startDrag(final double x, final double y) {
oldx=X;
oldy=Y;
startx=x;
starty=y;
}
public void dragTo(final double x, final double y) {
if (DragSlider) {
setSliderPosition((x-SX)/SD);
} else {
move(oldx+(x-startx), oldy+(y-starty));
}
}
public double getOldX() {
return oldx;
}
public double getOldY() {
return oldy;
}
@Override
public boolean isSlider() {
return Slider;
}
public double getMinValue() {
try {
double d=SMin.getValue();
return d;
} catch (Exception ex) {
return -5;
}
}
public double getMaxValue() {
try {
double d=SMax.getValue();
return d;
} catch (Exception ex) {
return -5;
}
}
@Override
public String getMin() {
if (Slider) {
return SMin.toString();
} else {
return ("-5");
}
}
@Override
public String getMax() {
if (Slider) {
return SMax.toString();
} else {
return ("5");
}
}
@Override
public String getDisplayValue() {
String s="";
try {
E.getValue();
double x=round(CurrentValue);
if (Slider) {
x=round(CurrentValue, 100);
}
if (Math.abs(x-Math.round(x))<1e-10) {
s=s+(int) x;
} else {
s=s+x;
}
} catch (final Exception e) {
s=s+"???";
}
s=s+Unit; // add optional unit
return s;
}
@Override
public String getEquation() {
if (E==null) {
return "???";
} else {
return E.toString();
}
}
@Override
public boolean isDriverObject() {
return true;
}
public boolean somethingChanged() {
return (!getEquation().equals(LASTE));
}
public void clearChanges() {
LASTE=getEquation();
}
@Override
public boolean isOwnedByControl() {
return isOwned;
}
@Override
public void setOwnedByControl(boolean b) {
isOwned=b;
}
}

View file

@ -0,0 +1,764 @@
/*
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;
import eric.bar.JPropertiesBar;
import java.awt.Button;
import java.awt.Checkbox;
import java.awt.Color;
import java.awt.Frame;
import java.awt.TextField;
import java.awt.event.FocusEvent;
import java.util.Enumeration;
import eric.JEricPanel;
import rene.dialogs.Warning;
import rene.gui.ButtonAction;
import rene.gui.Global;
import rene.gui.IconBar;
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;
public class FixedAngleObject extends PrimitiveLineObject implements
MoveableObject, SimulationObject, InsideObject {
protected PointObject P2;
static Count N = new Count();
double A, A1, A2, AA;
Expression E;
boolean Filled = false;
boolean Inverse = false;
boolean EditAborted = false;
boolean Dragable = false;
boolean Reduced = false;
public static final int NORMALSIZE = 1, SMALL = 0, LARGER = 2, LARGE = 3,
RECT = 4;
protected int DisplaySize = NORMALSIZE;
public FixedAngleObject(final Construction c, final PointObject p1,
final PointObject p2, final double x, final double y) {
super(c);
P1 = p1;
P2 = p2;
init(c, x, y);
Unit = Global.getParameter("unit.angle", "°");
}
@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(Cn.Solid);
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));
}
public void init(final Construction c, final double x, final double y,
final boolean invert) {
double dx = P1.getX() - P2.getX(), dy = P1.getY() - P2.getY();
A1 = Math.atan2(dy, dx);
dx = x - P2.getX();
dy = y - P2.getY();
A2 = Math.atan2(dy, dx);
A = A2 - A1;
if (A < 0) {
A += 2 * Math.PI;
} else if (A > 2 * Math.PI) {
A -= 2 * Math.PI;
}
if (Inverse && Obtuse) {
A = 2 * Math.PI - A;
}
if (invert && !Obtuse) {
if (A > Math.PI) {
A = 2 * Math.PI - A;
Inverse = true;
} else {
Inverse = false;
}
}
E = new Expression(""
+ round(A / Math.PI * 180, ZirkelCanvas.EditFactor), c, this);
validate();
setColor(ColorIndex, SpecialColor);
updateText();
}
public void init(final Construction c, final double x, final double y) {
init(c, x, y, true);
}
double xx[] = new double[4], yy[] = new double[4];
@Override
public void paint(final MyGraphics g, final ZirkelCanvas zc) {
if (!Valid || mustHide(zc)) {
return;
}
// compute middle of the screen:
final double xm = (zc.minX() + zc.maxX()) / 2, ym = (zc.minY() + zc
.maxY()) / 2;
// compute distance from middle to line:
final double d = (xm - X1) * DY - (ym - Y1) * DX;
// compute point with minimal distance
final double x = xm - d * DY, y = ym + d * DX;
// compute size of the screen
final double a = Math.max(zc.maxX() - zc.minX(), zc.maxY() - zc.minY());
if (Math.abs(d) > a) {
return;
}
// compute distance from closest point to source
final double b = (x - X1) * DX + (y - Y1) * DY;
// compute the two visible endpoints
double k1 = b - a;
final double k2 = b + a;
if (k1 < 0) {
k1 = 0;
}
if (k1 >= k2) {
return;
}
double c1 = zc.col(X1 + k1 * DX);
final double c2 = zc.col(X1 + k2 * DX);
double r1 = zc.row(Y1 + k1 * DY);
final double r2 = zc.row(Y1 + k2 * DY);
// paint:
g.setColor(this);
if (!Reduced) {
g.drawLine(c1, r1, c2, r2, this);
}
final double R = zc.col(getDisplaySize(zc)) - zc.col(0);
c1 = zc.col(X1) - R;
r1 = zc.row(Y1) - R;
final String s = AngleObject.translateToUnicode(getDisplayText());
double DA = (A / Math.PI * 180);
if (DA < 0) {
DA += 360;
} else if (DA >= 360) {
DA -= 360;
}
if (isStrongSelected() && g instanceof MainGraphics) {
((MainGraphics) g).drawMarkerArc(c1 + R, r1 + R, R, A1 / Math.PI
* 180, DA);
}
g.setColor(this);
if (Filled) {
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;
xx[0] = c1;
yy[0] = r1;
xx[0] = c1 + R;
yy[0] = r1 + R;
xx[1] = c1 + R + R * dx1;
yy[1] = r1 + R - R * dy1;
xx[2] = c1 + R + R * dx3;
yy[2] = r1 + R - R * dy3;
xx[3] = c1 + R + R * dx2;
yy[3] = r1 + R - R * dy2;
g.fillPolygon(xx, yy, 4, false, getColorType() != THICK, this);
g.setColor(this);
g.drawLine(xx[1], yy[1], xx[2], yy[2]);
g.drawLine(xx[2], yy[2], xx[3], yy[3]);
} else {
g.fillArc(c1, r1, 2 * R + 1, 2 * R + 1, A1 / Math.PI * 180, DA,
Selected || getColorType() == NORMAL,
getColorType() != THICK, true, this);
}
} else {
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;
xx[1] = c1 + R + R * dx1;
yy[1] = r1 + R - R * dy1;
xx[2] = c1 + R + R * dx3;
yy[2] = r1 + R - R * dy3;
xx[3] = c1 + R + R * dx2;
yy[3] = r1 + R - R * dy2;
g.setColor(this);
g.drawLine(xx[1], yy[1], xx[2], yy[2]);
g.drawLine(xx[2], yy[2], xx[3], yy[3]);
} else {
g.drawCircleArc(c1 + R, r1 + R, R, A1 / Math.PI * 180, DA,
this);
}
}
}
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 dof=Math.sqrt(XcOffset*XcOffset+YcOffset*YcOffset);
// TX1=zc.col(X1+dof*dx)-3;
// TY1=zc.row(Y1+dof*dy)-3;
// TX2=TX1+9;
// TY2=TY1+9;
// g.drawRect(zc.col(X1+dof*dx)-1,
// zc.row(Y1+dof*dy)-1, 3, 3);
// } else {
// TX1=zc.col(X1+zc.dx(R*AngleObject.LabelScale)*dx+XcOffset)-3;
// TY1=zc.row(Y1+zc.dy(R*AngleObject.LabelScale)*dy+YcOffset)-3;
// TX2=TX1+9;
// TY2=TY1+9;
// g.drawRect(zc.col(X1+zc.dx(R*AngleObject.LabelScale)*dx+XcOffset)-1,
// zc.row(Y1+zc.dy(R*AngleObject.LabelScale)*dy+YcOffset)-1, 3, 3);
// }
// } else {
if (KeepClose) {
final double dof = Math.sqrt(XcOffset * XcOffset + YcOffset
* YcOffset);
drawCenteredLabel(g, s, zc, X1 + dof * dx, Y1 + dof * dy, 0, 0);
} else {
drawCenteredLabel(g, s, zc, X1
+ zc.dx(R * AngleObject.LabelScale) * dx, Y1
+ zc.dy(R * AngleObject.LabelScale) * dy, XcOffset,
YcOffset);
}
// }
}
}
@Override
public boolean canKeepClose() {
return true;
}
@Override
public void setKeepClose(final double x, final double y) {
KeepClose = true;
XcOffset = x - X1;
YcOffset = y - Y1;
}
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() - X1, dy = P1.getY() - Y1;
R = Math.sqrt(dx * dx + dy * dy);
}
return R;
}
@Override
public String getTag() {
return "Angle";
}
@Override
public int getN() {
return N.next();
}
@Override
public void updateText() {
if (E == null || !E.isValid()) {
return;
}
setText(text3(Global.name("text.fixedangle"), P1.getName(), P2
.getName(), E.toString()));
}
@Override
public String getDisplayValue() {
return Global.getLocaleNumber(A / Math.PI * 180, "angles");
}
// public String getDisplayValue() {
// if (ZirkelCanvas.AnglesFactor<=2) {
// return ""+(int) (A/Math.PI*180+0.5);
// } else {
// return ""+round(A/Math.PI*180, ZirkelCanvas.AnglesFactor);
// }
// }
@Override
public void validate() {
if (!P1.valid() || !P2.valid()) {
Valid = false;
return;
} else {
X1 = P2.getX();
Y1 = P2.getY();
final double dx = P1.getX() - X1, dy = P1.getY() - Y1;
if (Math.sqrt(dx * dx + dy * dy) < 1e-9) {
Valid = false;
return;
}
A1 = Math.atan2(dy, dx);
boolean Negative = false;
try {
if (E != null && E.isValid()) {
A = E.getValue() / 180 * Math.PI;
}
if (Obtuse) {
if (Inverse) {
A = -A;
}
} else {
if (Inverse && Math.sin(A) > 0) {
A = -A;
}
if (!Inverse && Math.sin(A) < 0) {
A = -A;
}
}
if (A < 0) {
Negative = true;
}
while (A < 0) {
A = A + 2 * Math.PI;
}
while (A >= 2 * Math.PI) {
A = A - 2 * Math.PI;
}
A2 = A1 + A;
DX = Math.cos(A2);
DY = Math.sin(A2);
AA = A;
} catch (final Exception e) {
Valid = false;
return;
}
if (!Obtuse && A > Math.PI) {
A1 = A2;
A = 2 * Math.PI - A;
A2 = A1 + A;
} else if (Obtuse && Negative) {
A1 = A2;
A = 2 * Math.PI - A;
A2 = A1 + A;
}
Valid = true;
}
}
public double getLength() {
return A;
}
@Override
public void setFixed(final String s) {
E = new Expression(s, getConstruction(), this);
updateText();
}
@Override
public void round() {
try {
setFixed(round(E.getValue(), ZirkelCanvas.AnglesFactor) + "");
validate();
} catch (final Exception e) {
}
}
public void setEditFixed(final String s) {
E = new Expression(s, getConstruction(), this);
updateText();
}
@Override
public boolean canFix() {
return true;
}
@Override
public void printArgs(final XmlWriter xml) {
xml.printArg("first", P1.getName());
xml.printArg("root", P2.getName());
if (DisplaySize == SMALL) {
xml.printArg("display", "small");
}
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 (E.isValid()) {
xml.printArg("fixed", E.toString());
} else {
xml.printArg("fixed", "" + A / Math.PI * 180);
}
if (!Obtuse) {
xml.printArg("acute", "true");
}
if (Inverse) {
xml.printArg("inverse", "true");
}
if (Reduced) {
xml.printArg("reduced", "true");
}
if (Dragable) {
xml.printArg("dragable", "true");
}
super.printArgs(xml);
}
@Override
public boolean nearto(final int c, final int r, final ZirkelCanvas zc) {
if (!Valid && P2.valid()) {
return P2.nearto(c, r, zc);
}
if (!displays(zc)) {
return false;
}
// compute point at c,r
final double x = zc.x(c), y = zc.y(r);
// compute distance from x,y
final double d = (x - X1) * DY - (y - Y1) * DX;
final double e = (x - X1) * DX + (y - Y1) * DY;
// scale in screen coordinates
Value = Math.abs(zc.col(zc.minX() + d) - zc.col(zc.minX()));
if (!Reduced && Value < zc.selectionSize() && e > 0) {
return true;
}
final double dx = zc.x(c) - X1, dy = zc.y(r) - Y1;
final double size = zc.dx(zc.selectionSize());
final double rd = getDisplaySize(zc);
final double rr = Math.sqrt(dx * dx + dy * dy);
boolean near;
if (Filled || DisplaySize == RECT) {
near = (rr < rd + size);
} else {
near = (Math.abs(rr - 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 cc = 0.05;
if (A1 - cc < a && A2 + cc > a) {
return true;
}
a = a - 2 * Math.PI;
if (A1 - cc < a && A2 + cc > a) {
return true;
}
a = a + 4 * Math.PI;
if (A1 - cc < a && A2 + cc > a) {
return true;
}
return false;
}
@Override
public void setDisplaySize(final int i) {
DisplaySize = i;
}
@Override
public int getDisplaySize() {
return DisplaySize;
}
@Override
public Enumeration depending() {
super.depending();
depset(P1, P2);
final Enumeration e = E.getDepList().elements();
while (e.hasMoreElements()) {
DL.add((ConstructionObject) e.nextElement());
}
return DL.elements();
}
@Override
public void translate() {
P1 = (PointObject) P1.getTranslation();
P2 = (PointObject) P2.getTranslation();
try {
setFixed(E.toString());
E.translate();
} catch (final Exception e) {
}
}
@Override
public String getE() {
return E.toString();
}
@Override
public double getValue() throws ConstructionException {
if (!Valid) {
throw new InvalidException("exception.invalid");
} else {
return A / Math.PI * 180;
}
}
@Override
public void setFilled(final boolean flag) {
Filled = flag;
}
@Override
public boolean isFilled() {
return Filled;
}
@Override
public boolean isFilledForSelect() {
return false;
}
@Override
public boolean contains(final double x, final double y) {
final double a = (x - X1) * DX + (y - Y1) * DY;
if (a < 1e-9) {
return false;
}
return true;
}
@Override
public double project(final double x, final double y) {
final double h = super.project(x, y);
if (h < 0) {
return 0;
}
return h;
}
@Override
public Enumeration points() {
super.depending();
return depset(P2);
}
@Override
public void move(final double x, final double y) {
init(getConstruction(), x, y, true);
}
public boolean moveable() {
return Dragable; // E.isNumber();
}
@Override
public boolean isFixed() {
return true;
}
public boolean getInverse() {
return Inverse;
}
public void setInverse(final boolean inverse) {
Inverse = inverse;
}
public boolean isEditAborted() {
return EditAborted;
}
@Override
public boolean isDragable() {
return Dragable;
}
@Override
public void setDragable(final boolean f) {
Dragable = f;
}
public boolean isReduced() {
return Reduced;
}
public void setReduced(final boolean f) {
Reduced = f;
}
public boolean fixedByNumber() {
return (E != null && E.isNumber());
}
// For the simulate function:
/**
* Set the simulation value, remember the old value.
*/
public void setSimulationValue(final double x) {
A = x / 180 * Math.PI;
final Expression OldE = E;
E = null;
validate();
E = OldE;
}
/**
* Reset the old value.
*/
public void resetSimulationValue() {
validate();
}
public void startDrag(final double x, final double y) {
}
public void dragTo(final double x, final double y) {
move(x, y);
}
public double getOldX() {
return 0;
}
public double getOldY() {
return 0;
}
public double containsInside(final PointObject P) {
final double dx = P.getX() - X1, dy = P.getY() - Y1;
double a = Math.atan2(dy, dx);
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 = X1, y1 = Y1;
double xmin = x1, ymin = y1, dmin = 1e20;
double x2 = X1 + Math.cos(A1), y2 = Y1 + Math.sin(A1);
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 = X1 + Math.cos(A2);
y2 = Y1 + Math.sin(A2);
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;
}
}

View file

@ -0,0 +1,270 @@
/*
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: CircleObject.java
import eric.bar.JPropertiesBar;
import java.awt.Frame;
import java.util.Enumeration;
import rene.dialogs.Warning;
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.expression.Expression;
import rene.zirkel.expression.InvalidException;
public class FixedCircleObject extends PrimitiveCircleObject implements
MoveableObject, SimulationObject {
Expression E;
boolean EditAborted = false;
boolean Dragable = false;
public FixedCircleObject(final Construction c, final PointObject p1,
final double x, final double y) {
super(c, p1);
init(c, x, y);
}
public void init(final Construction c, final double x, final double y) {
E = new Expression(""
+ Math.sqrt((x - M.getX()) * (x - M.getX()) + (y - M.getY())
* (y - M.getY())), c, this);
validate();
updateText();
}
@Override
public String getTag() {
return "Circle";
}
@Override
public void updateText() {
if (E == null || !E.isValid()) {
return;
}
if (M.is3D()) setText(text2(Global.name("text.sphere"), M.getName(), ""
+ E.toString()));
else setText(text2(Global.name("text.fixedcircle"), M.getName(), ""
+ E.toString()));
}
@Override
public void validate() {
super.validate();
if (!M.valid()) {
Valid = false;
return;
}
Valid = true;
X = M.getX();
Y = M.getY();
if (E != null && !E.isValid()) {
return;
}
try {
if (E != null) {
R = E.getValue();
}
} catch (final Exception e) {
R = 0;
Valid = false;
}
if (R < -1e-10) {
Valid = false;
return;
}
}
@Override
public void printArgs(final XmlWriter xml) {
if (E.isValid()) {
xml.printArg("fixed", E.toString());
} else {
xml.printArg("fixed", "" + R);
}
if (Dragable) {
xml.printArg("dragable", "true");
}
super.printArgs(xml);
}
@Override
public boolean canFix() {
return true;
}
@Override
public boolean fixed() {
return true;
}
@Override
public void setFixed(final String s) {
E = new Expression(s, getConstruction(), this);
}
@Override
public void round() {
try {
setFixed(round(E.getValue(), ZirkelCanvas.LengthsFactor) + "");
validate();
} catch (final Exception e) {
}
}
@Override
public boolean nearto(final int c, final int r, final ZirkelCanvas zc) {
if (!Valid && M.valid()) {
return M.nearto(c, r, zc);
}
return super.nearto(c, r, zc);
}
public boolean isValidFix() {
return E.isValid();
}
@Override
public void translate() {
super.translate();
try {
setFixed(E.toString());
E.translate();
} catch (final Exception e) {
}
}
@Override
public String getStringLength() {
return E.toString();
}
@Override
public double getValue() throws ConstructionException {
if (!Valid) {
throw new InvalidException("exception.invalid");
} else {
return R;
}
}
@Override
public Enumeration depending() {
super.depending();
final Enumeration e = E.getDepList().elements();
while (e.hasMoreElements()) {
DL.add((ConstructionObject) e.nextElement());
}
return DL.elements();
}
@Override
public void move(final double x, final double y) {
init(getConstruction(), x, y);
}
public boolean moveable() {
return Dragable || M.moveable();
}
@Override
public boolean isFixed() {
return true;
}
public boolean isEditAborted() {
return EditAborted;
}
@Override
public boolean isDragable() {
return Dragable;
}
@Override
public void setDragable(final boolean f) {
Dragable = f;
}
public boolean fixedByNumber() {
return (E != null && E.isNumber());
}
// For the simulate function:
/**
* Set the simulation value, remember the old value.
*/
public void setSimulationValue(final double x) {
R = x;
final Expression OldE = E;
E = null;
validate();
E = OldE;
}
/**
* Reset the old value.
*/
public void resetSimulationValue() {
validate();
}
double x1, y1, x2, y2;
public void startDrag(final double x, final double y) {
x1 = M.getX();
y1 = M.getY();
x2 = x;
y2 = y;
}
public void dragTo(final double x, final double y) {
if (Dragable) {
move(x, y);
} else {
M.move(x1 + (x - x2), y1 + (y - y2));
}
}
public double getOldX() {
return 0;
}
public double getOldY() {
return 0;
}
@Override
public void snap(final ZirkelCanvas zc) {
if (moveable() && !Dragable) {
M.snap(zc);
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,33 @@
/*
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;
import rene.zirkel.construction.Construction;
public interface HeavyObject {
public void compute();
public boolean needsToRecompute();
public void searchDependencies(Construction c);
}

View file

@ -0,0 +1,171 @@
/*
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;
import eric.Media;
import java.awt.Image;
import java.util.Enumeration;
import rene.util.FileName;
import rene.util.xml.XmlWriter;
import rene.gui.Global;
import rene.zirkel.ZirkelCanvas;
import rene.zirkel.construction.Construction;
import rene.zirkel.construction.Count;
import rene.zirkel.graphics.MyGraphics;
public class ImageObject extends ConstructionObject {
PointObject P[];
static Count N=new Count();
String Filename;
Image I;
public ImageObject(final Construction c, final PointObject p[],
final String filename) {
super(c);
P=p;
Filename=FileName.filename(filename);
// Filename=filename;
updateText();
}
public String getFilename() {
return Filename;
}
@Override
public String getTag() {
return "Image";
}
@Override
public int getN() {
return N.next();
}
@Override
public void updateText() {
try {
final String Names[]=new String[P.length];
for (int i=0; i<P.length; i++) {
Names[i]=P[i].getName();
}
setText(textAny(Global.name("text.image"), Names));
} catch (final Exception e) {
}
}
@Override
public void validate() {
}
@Override
public void paint(final MyGraphics g, final ZirkelCanvas zc) {
if (!Valid||mustHide(zc)) {
return;
}
if (I==null) {
// I = zc.doLoadImage(Filename);
I=Media.getImage(Filename);
if (I==null||I.getWidth(zc)==0||I.getHeight(zc)==0) {
Valid=false;
return;
} else {
Valid=true;
}
}
if (P[1]==P[2]||P[0]==P[2]) {
I.getWidth(zc);
final double dx=P[1].getX()-P[0].getX(), dy=P[1].getY()
-P[0].getY();
g.drawImage(I, zc.col(P[0].getX()), zc.row(P[0].getY()), zc.col(P[1].getX()), zc.row(P[1].getY()), zc.col(P[0].getX()
+dy), zc.row(P[0].getY()-dx), zc);
} else {
g.drawImage(I, zc.col(P[0].getX()), zc.row(P[0].getY()), zc.col(P[1].getX()), zc.row(P[1].getY()), zc.col(P[2].getX()), zc.row(P[2].getY()), zc);
}
}
@Override
public boolean nearto(final int cc, final int rr, final ZirkelCanvas zc) {
if (!displays(zc)) {
return false;
}
return P[0].nearto(cc, rr, zc)||P[1].nearto(cc, rr, zc)
||P[2].nearto(cc, rr, zc);
}
@Override
public void printArgs(final XmlWriter xml) {
for (int i=0; i<P.length; i++) {
xml.printArg("point"+(i+1), P[i].getName());
}
xml.printArg("filename", FileName.filename(Filename));
}
@Override
public Enumeration depending() {
DL.reset();
for (final PointObject element : P) {
DL.add(element);
}
return DL.elements();
}
@Override
public void translate() {
for (int i=0; i<P.length; i++) {
P[i]=(PointObject) P[i].getTranslation();
}
}
@Override
public ConstructionObject copy(final double x, final double y) {
try {
final QuadricObject o=(QuadricObject) clone();
setTranslation(o);
o.P=new PointObject[P.length];
for (int i=0; i<P.length; i++) {
o.P[i]=P[i];
}
o.translateConditionals();
o.translate();
o.setName();
o.updateText();
o.setBreak(false);
o.setTarget(false);
return o;
} catch (final Exception e) {
return null;
}
}
@Override
public boolean onlynearto(final int x, final int y, final ZirkelCanvas zc) {
return nearto(x, y, zc);
}
@Override
public boolean hasUnit() {
return false;
}
}

View file

@ -0,0 +1,31 @@
/*
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;
public interface InsideObject {
/**
* Returns 0.5, if the point is on the boundary, and 1, if it is inside.
*/
public double containsInside(PointObject P);
public boolean keepInside(PointObject P);
}

View file

@ -0,0 +1,291 @@
/*
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: IntersectionObject.java
import java.util.Enumeration;
import rene.util.xml.XmlWriter;
import rene.gui.Global;
import rene.zirkel.ZirkelCanvas;
import rene.zirkel.construction.Construction;
import rene.zirkel.construction.Count;
import rene.zirkel.expression.Expression;
/**
* This is the parent class of various intersection objects. Intersections are
* points. Problems are multiple intersections and restrictions to keep one of
* them away or close to some other point. The most problematic intersections
* are between objects of type PointonObject.
*
* In case of two possible intersection points, there is also the option to
* switch from one object to the other in automatic tracks. This allows to run
* through all possible states of a construction.
*
* @author Rene
*/
public class IntersectionObject extends PointObject {
protected ConstructionObject P1, P2;
private static Count N = new Count();
protected Expression Away;
protected boolean StayAway = true;
protected boolean First;
protected boolean Switched;
protected boolean Restricted;
protected boolean Alternate;
public IntersectionObject(final Construction c,
final ConstructionObject p1, final ConstructionObject p2) {
super(c, 0, 0);
Moveable = false;
P1 = p1;
P2 = p2;
updateText();
First = true;
Switched = false;
Restricted = true;
Alternate = false;
}
@Override
public String getTag() {
return "Intersection";
}
@Override
public int getN() {
return N.next();
}
@Override
public boolean nearto(final int x, final int y, final ZirkelCanvas zc) {
if (!displays(zc))
return false;
final double c = zc.col(X), r = zc.row(Y);
final int size = (int) zc.selectionSize();
Value = Math.abs(x - c) + Math.abs(y - r);
return Value <= size * 5;
}
@Override
public void updateText() {
try {
setText(text2(Global.name("text.intersection"), P1.getName(), P2
.getName()));
} catch (final Exception e) {
}
}
public void setFirst(final boolean flag) {
First = flag;
}
public boolean isFirst() {
return First;
}
@Override
public void validate() {
if (!P1.valid() || !P2.valid())
Valid = false;
else
Valid = true;
}
public void validate(final double x, final double y) {
}
@Override
public void printArgs(final XmlWriter xml) {
xml.printArg("first", P1.getName());
xml.printArg("second", P2.getName());
if (getAway() != null) {
if (StayAway)
xml.printArg("awayfrom", getAway().getName());
else
xml.printArg("closeto", getAway().getName());
}
printType(xml);
if (!Restricted)
xml.printArg("valid", "true");
if (Alternate)
xml.printArg("alternate", "true");
}
public String away() {
if (getAway() != null)
return getAway().getName();
else
return "";
}
public boolean stayAway() {
return StayAway;
}
public boolean setAway(final String s, final boolean flag) {
Away = null;
if (s.equals(""))
return true;
if (Cn == null)
return true;
Away = new Expression("@\"" + s + "\"", Cn, this);
StayAway = flag;
return getAway() != null;
}
public boolean setAway(final String s) {
return setAway(s, true);
}
@Override
public Enumeration depending() {
super.depending();
return depset(P1, P2);
}
@Override
public void translate() {
P1 = P1.getTranslation();
P2 = P2.getTranslation();
if (getAway() != null) {
setAway(getAway().getName(), StayAway);
Away.translate();
}
}
public boolean isSwitchable() {
return false;
}
/**
* Check, if the other intersection is already visible and defined. In this
* case, we want to keep the intersection different from the other
* intersection point.
*/
public void autoAway() {
if (!autoAway(P1, P2))
autoAway(P2, P1);
}
boolean autoAway(final ConstructionObject o1, final ConstructionObject o2) {
if (o1 instanceof CircleObject) {
final PointObject p1 = ((CircleObject) o1).getP2();
if (p1.isHidden())
return false;
if (p1.dependsOn(o2) && !nearto(p1)) {
setAway(p1.getName());
return true;
} else if (o2 instanceof CircleObject) {
final PointObject p2 = ((CircleObject) o2).getP2();
if (p2.isHidden())
return false;
if (p1 == p2 && !nearto(p1)) {
setAway(p1.getName());
return true;
}
return false;
} else if (o2 instanceof PrimitiveLineObject) {
final Enumeration en = ((PrimitiveLineObject) o2).points();
while (en.hasMoreElements()) {
final ConstructionObject oo = (ConstructionObject) en
.nextElement();
if (oo instanceof PointObject) {
final PointObject o = (PointObject) oo;
if (o.isHidden())
return false;
if (p1 == o && !nearto(p1)) {
setAway(p1.getName());
return true;
}
}
}
}
} else if (o1 instanceof TwoPointLineObject) {
final PointObject p1 = ((TwoPointLineObject) o1).getP1();
if (!p1.isHidden() && p1.dependsOn(o2) && !nearto(p1)) {
setAway(p1.getName());
return true;
}
final PointObject p2 = ((TwoPointLineObject) o1).getP2();
if (!p2.isHidden() && p2.dependsOn(o2) && !nearto(p2)) {
setAway(p2.getName());
return true;
}
}
return false;
}
public void switchBack() {
if (Switched)
First = !First;
Switched = false;
}
public void doSwitch() {
Switched = !Switched;
First = !First;
}
public boolean isSwitched() {
return Switched;
}
public boolean isRestricted() {
return Restricted;
}
public void setRestricted(final boolean flag) {
Restricted = flag;
}
public PointObject getAway() {
return getPointObject(Away);
}
public void setAlternate(final boolean flag) {
Alternate = flag;
}
public boolean isAlternate() {
return Alternate;
}
/**
* Returns, if this intersection can alternate between two states, like
* CircleIntersection and LineCircleIntersection. Used by the dialog.
*/
public boolean canAlternate() {
return false;
}
public ConstructionObject getP1(){
return P1;
}
public ConstructionObject getP2(){
return P2;
}
}

View file

@ -0,0 +1,659 @@
/*
Copyright 2006 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;
import java.util.Enumeration;
import java.util.Vector;
import rene.gui.Global;
import rene.zirkel.ZirkelCanvas;
import rene.zirkel.construction.Construction;
import rene.zirkel.graphics.MyGraphics;
import rene.zirkel.graphics.PolygonDrawer;
import rene.zirkel.structures.Coordinates;
/**
*
* @author erichake
*/
public class JLocusTrackObject extends TrackObject implements HeavyObject {
Coordinates C;
PolygonDrawer pd;
double c0, r0, c, r;
ExpressionObject EO;
Vector RefreshList=new Vector();
Vector DriverObjectList=new Vector();
boolean Special=false;
double cx, cy, ww, wh;
long time=0;
public JLocusTrackObject(final Construction c, final ConstructionObject p,
final ConstructionObject po[], final int pn,
final ConstructionObject o, final PointObject pm) {
super(c);
P=p;
PN=pn;
for (int i=0; i<PN; i++) {
PO[i]=po[i];
}
O=o;
PM=pm;
validate();
updateText();
cx=c.getX();
cy=c.getY();
ww=c.getW();
wh=c.getH();
searchDependencies(c);
}
@Override
public void searchDependencies(final Construction c) {
RefreshList.clear();
DriverObjectList.clear();
if (O instanceof SegmentObject) {
searchDependencies(c, this, PM);
} else if (O instanceof ExpressionObject) {
searchDependencies(c, this, null);
} else if (O instanceof RayObject) {
searchDependencies(c, this, PM);
} else if (O instanceof PrimitiveLineObject) {
searchDependencies(c, this, PM);
} else if (O instanceof PrimitiveCircleObject) {
searchDependencies(c, this, PM);
} else if (O instanceof QuadricObject) {
searchDependencies(c, this, PM);
} else if (O instanceof TrackObject) {
searchDependencies(c, this, PM);
} else if (O instanceof AreaObject) {
searchDependencies(c, this, PM);
} else if (O instanceof FunctionObject) {
searchDependencies(c, this, PM);
}
NeedsRecompute=true;
}
public void searchDependencies(final Construction c,
final ConstructionObject o, final ConstructionObject avoid) {
if (o.RekValidating) {
return;
} // should not happen!
o.RekValidating=true;
Enumeration e=c.elements();
while (e.hasMoreElements()) {
((ConstructionObject) e.nextElement()).setRekFlag(false);
}
recursiveSearchDependencies(o, avoid);
e=c.elements();
while (e.hasMoreElements()) {
final ConstructionObject oc=(ConstructionObject) e.nextElement();
if (oc.isRekFlag()) {
RefreshList.addElement(oc);
if ((!(oc==P))&&(oc.isDriverObject())) {
DriverObjectList.addElement(oc);
}
}
}
o.RekValidating=false;
}
public void recursiveSearchDependencies(final ConstructionObject o,
final ConstructionObject avoid) {
if (o.isRekFlag()||o==avoid) {
return;
}
o.setRekFlag(true);
final ConstructionObject d[]=o.getDepArray();
for (final ConstructionObject element : d) {
recursiveSearchDependencies(element, avoid);
}
}
@Override
public boolean needsToRecompute() {
boolean needs=false;
final Enumeration pl=DriverObjectList.elements();
while (pl.hasMoreElements()) {
final DriverObject oc=(DriverObject) pl.nextElement();
if (oc.somethingChanged()) {
Global.addClearList(oc);
// ConstructionObject oo=(ConstructionObject) oc;
// System.out.println("needsRecompute :"+oo.getName());
needs=true;
}
}
if ((Cn.getX()!=cx)||(Cn.getY()!=cy)||(Cn.getW()!=ww)
||(Cn.getH()!=wh)) {
cx=Cn.getX();
cy=Cn.getY();
ww=Cn.getW();
wh=Cn.getH();
needs=true;
}
if (NeedsRecompute) {
NeedsRecompute=false;
return true;
}
return needs;
}
public synchronized void refresh() {
final Enumeration e=RefreshList.elements();
while (e.hasMoreElements()) {
final ConstructionObject oc=(ConstructionObject) e.nextElement();
oc.NeedsRecompute=true;
oc.validate();
}
}
private static double a=5, b=6, xmin=-b+0.0001;
private static void setConstants(final Construction c) {
final double dx=c.getW()*2;
final double dy=c.getH();
final double r=Math.sqrt(dx*dx+dy*dy);
a=r;
b=1.5*a;
xmin=-b+(b-a)/1000;
}
public static double fline(final double x) {
if (Math.abs(x)<a) {
return x;
} else {
final double s=Math.signum(x);
return s*(2*a-b)+((b-a)*(b-a))/(s*b-x);
}
}
private Coordinates oldC=new Coordinates();
@Override
public void addCoordinates(final Vector v, final ConstructionObject p) {
if (p.valid()) {
oldC=new Coordinates(p.getX(), p.getY());
v.addElement(oldC);
} else {
if (!Double.isNaN(oldC.X)) {
oldC=new Coordinates();
v.addElement(oldC);
}
}
}
public synchronized void docomputeCircle() {
double dt;
double a1;
final PrimitiveCircleObject CO=(PrimitiveCircleObject) O;
final double x=CO.getX(), y=CO.getY(), RO=CO.getR();
if (CO.hasRange()) {
a1=CO.getA1();
final double a2=CO.getA2();
double d=a2-a1;
while (d<0) {
d+=2*Math.PI;
}
while (d>=2*Math.PI) {
d-=2*Math.PI;
}
dt=d*DMin;
// I really don't understand why this is necessary for arc locuses :
a1+=0.00000000001;
} else {
dt=2*Math.PI*DMin;
a1=0;
}
final int nbsteps=(int) Math.round(1/DMin)+1;
for (int i=0; i<nbsteps; i++) {
PM.move(x+RO*Math.cos(a1+i*dt), y+RO
*Math.sin(a1+i*dt));
refresh();
addCoordinates(V, P);
}
// Try to do something with points inside circle... I will see later !
// if (PM.isInside()) {
// Special=true;
// double rvar=r/nbsteps;
// r=0;
// for (int i=0; i<nbsteps; i++) {
// PM.move(x+r*Math.cos(a1+i*dt), y+r*Math.sin(a1+i*dt));
// refresh();
// if (P.valid()) {
// addCoordinates(V, P);
// }
// r+=rvar;
// }
// } else {
//
// for (int i=0; i<nbsteps; i++) {
// PM.move(x+r*Math.cos(a1+i*dt), y+r*Math.sin(a1+i*dt));
// refresh();
// if (P.valid()) {
// addCoordinates(V, P);
// }
// }
// }
}
public synchronized void docomputeLine() {
Cn.shouldSwitch(false);
final PrimitiveLineObject l=(PrimitiveLineObject) O;
// System.out.println("zc.DX="+zc.DX+" zc.DY="+zc.DY);
// System.out.println("dx="+Cn.getW()*2+" dy="+Cn.getH());
setConstants(Cn);
final double da=-2*xmin*DMin;
final double lx=l.getX(), ly=l.getY(), ldx=l.getDX(), ldy=l.getDY();
double delta;
final int nbsteps=(int) Math.round(1/DMin)+1;
for (int i=0; i<nbsteps; i++) {
delta=fline(xmin+i*da);
PM.move(lx+ldx*delta, ly+ldy*delta);
refresh();
addCoordinates(V, P);
}
}
public synchronized void docomputeRay() {
Cn.shouldSwitch(false);
final PrimitiveLineObject l=(PrimitiveLineObject) O;
setConstants(Cn);
final double da=-xmin*DMin;
final double lx=l.getX(), ly=l.getY(), ldx=l.getDX(), ldy=l.getDY();
double delta;
final int nbsteps=(int) Math.round(1/DMin)+1;
for (int i=0; i<nbsteps; i++) {
delta=fline(i*da);
PM.move(lx+ldx*delta, ly+ldy*delta);
refresh();
addCoordinates(V, P);
}
}
public synchronized void docomputeSegments() {
Cn.shouldSwitch(false);
final PrimitiveLineObject l=(PrimitiveLineObject) O;
final double r=((SegmentObject) l).getLength();
final double lx=l.getX(), ly=l.getY(), ldx=r*l.getDX()*DMin, ldy=r
*l.getDY()*DMin;
final int nbsteps=(int) Math.round(1/(DMin))+1;
for (int i=0; i<nbsteps; i++) {
PM.move(lx+ldx*i, ly+ldy*i);
refresh();
addCoordinates(V, P);
}
}
/**
* Compute the locus of a point on conic The idea is to consider the first
* point A of the conic (first of five points) then imagine a unit circle
* centered on A, imagine a point B on this circle, then compute
* intersections between line (AB) and the conic. This will give continuous
* points set on the conic, then refresh to get the locus point.
*
* @param zc
*/
public synchronized void docomputeQuadric() {
Cn.shouldSwitch(false);
final QuadricObject q=(QuadricObject) O;
final double A=q.X[0], B=q.X[1], C=q.X[2], D=q.X[3], E=q.X[4], F=q.X[5];
final double dt=Math.PI*DMin;
// get the first of the five points defining the conic :
final double X1=q.P[0].getX();
final double Y1=q.P[0].getY();
double M=0, N2=0, P1=0;
final int nbsteps=(int) Math.round(1/DMin)+1;
// System.out.println("*******************");
for (int i=0; i<nbsteps; i++) {
M=-Math.sin(i*dt+0.01);
N2=Math.cos(i*dt+0.01);
P1=-(M*X1+N2*Y1);
double x1=0, x2=0, y1=0, y2=0;
final double part1=-2*B*M*P1-C*N2*N2+D*M*N2+E
*N2*P1;
final double part2=Math.abs(N2)
*Math.sqrt(-2*M*D*N2*C+4*P1*D*A*N2+4
*P1*M*B*C+4*E*M*N2*F-2*E*P1
*N2*C-2*E*P1*M*D-4*M*M*B*F
-4*P1*P1*A*B-4*A*N2*N2*F+N2
*N2*C*C+M*M*D*D+E*E*P1*P1);
final double part3=2*A*N2*N2+2*B*M*M+(-2*E)*M
*N2;
x1=(part1+part2)/part3;
y1=(-M*x1-P1)/N2;
x2=(part1-part2)/part3;
y2=(-M*x2-P1)/N2;
if (((x2-x1)/N2)<0) {
final double c1=x1, r1=y1;
x1=x2;
y1=y2;
x2=c1;
y2=r1;
}
if ((Math.abs(X1-x1)<1e-10)&&(Math.abs(X1-x1)<1e-10)) {
PM.move(x2, y2);
} else {
PM.move(x1, y1);
}
refresh();
addCoordinates(V, P);
}
}
public synchronized void docomputeExpression() {
Cn.shouldSwitch(false);
EO=(ExpressionObject) O;
if (!EO.isSlider()) {
return;
}
final int nbsteps=(int) Math.round(1/DMin)+1;
double oldCursor=EO.getSliderPosition();
for (int i=0; i<nbsteps; i++) {
EO.setSliderPosition(DMin*i);
refresh();
addCoordinates(V, P);
}
EO.setSliderPosition(oldCursor);
}
public synchronized void docomputeTrack() {
Cn.shouldSwitch(false);
final JLocusTrackObject TR=(JLocusTrackObject) O;
if (DMin!=TR.DMin) {
TR.DMin=DMin;
TR.compute();
}
final Enumeration e=TR.V.elements();
while (e.hasMoreElements()) {
C=(Coordinates) e.nextElement();
PM.move(C.X, C.Y);
refresh();
addCoordinates(V, P);
}
}
public synchronized void docomputeFunction() {
Cn.shouldSwitch(false);
final FunctionObject FO=(FunctionObject) O;
final Enumeration e=FO.V.elements();
while (e.hasMoreElements()) {
C=(Coordinates) e.nextElement();
PM.move(C.X, C.Y);
refresh();
addCoordinates(V, P);
}
}
public synchronized void docomputeArea() {
Cn.shouldSwitch(false);
final AreaObject poly=(AreaObject) O;
final int NVertex=poly.V.size();
int nbsteps=(int) Math.round(1/(DMin*NVertex));
if (nbsteps<2) {
nbsteps=2;
}
double xA, xB, yA, yB;
final PointObject ORIGIN=(PointObject) poly.V.get(0);
PointObject A=ORIGIN;
PointObject B=null;
for (int n=1; n<NVertex; n++) {
B=(PointObject) poly.V.get(n);
xA=A.getX();
yA=A.getY();
xB=B.getX();
yB=B.getY();
for (int i=0; i<=nbsteps; i++) {
PM.move(xA+i*(xB-xA)/nbsteps, yA+i*(yB-yA)
/nbsteps);
refresh();
addCoordinates(V, P);
}
A=B;
}
xA=A.getX();
yA=A.getY();
xB=ORIGIN.getX();
yB=ORIGIN.getY();
for (int i=0; i<=nbsteps; i++) {
PM.move(xA+i*(xB-xA)/nbsteps, yA+i*(yB-yA)/nbsteps);
refresh();
addCoordinates(V, P);
}
// double r=((SegmentObject) l).getLength();
// double lx=l.getX(), ly=l.getY(), ldx=r*l.getDX()*DMin,
// ldy=r*l.getDY()*DMin;
//
// int nbsteps=(int) Math.round(1/DMin)+1;
// for (int i=0; i<nbsteps; i++) {
// PM.move(lx+ldx*i, ly+ldy*i);
// refresh();
// if (P.valid()) {
// addCoordinates(V, P);
// }
// }
}
@Override
public synchronized void compute(final ZirkelCanvas zc) {
compute();
}
public synchronized void compute() {
if (Fixed&&!StartFix) {
return;
}
// System.out.println("compute track");
V=new Vector();
oldC=new Coordinates();
StartFix=false;
double x=0, y=0;
if (PM!=null) {
x=PM.getX();
y=PM.getY();
}
Cn.clearSwitches();
Cn.shouldSwitch(true);
DontProject=true;
// Running on a segment :
if (O instanceof SegmentObject) {
docomputeSegments();
// Running on a conic :
} else if (O instanceof QuadricObject) {
docomputeQuadric();
// Running on an track :
} else if (O instanceof JLocusTrackObject) {
docomputeTrack();
// Running on an area :
} else if (O instanceof AreaObject) {
docomputeArea();
// Running on an expression :
} else if (O instanceof ExpressionObject) {
docomputeExpression();
// Running on a ray :
} else if (O instanceof RayObject) {
docomputeRay();
// Running on a circle :
} else if (O instanceof PrimitiveCircleObject) {
docomputeCircle();
// Running on a line :
} else if (O instanceof PrimitiveLineObject) {
docomputeLine();
} else if (O instanceof FunctionObject) {
docomputeFunction();
}
DontProject=false;
// zc.getConstruction().shouldSwitch(false);
// zc.getConstruction().clearSwitches();
if (PM!=null) {
PM.move(x, y);
refresh();
}
Cn.dovalidate();
// zc.dovalidate();
}
// public void validate() {
// compute();
// }
// Paint the track
@Override
public void paint(final MyGraphics g, final ZirkelCanvas zc) {
if (!Valid||mustHide(zc)) {
return;
}
Coordinates C;
final Enumeration e=V.elements();
double c, r;
if (indicated()) {
final boolean sel=P.indicated();
P.setIndicated(true);
g.setColor(P);
P.setIndicated(sel);
} else {
g.setColor(this);
}
if (Special) {
while (e.hasMoreElements()) {
C=(Coordinates) e.nextElement();
PointObject.drawPoint(g, zc, this, C.X, C.Y, Type);
}
} else {
final PolygonDrawer pd=new PolygonDrawer(false,g, this);
if (e.hasMoreElements()) {
C=(Coordinates) e.nextElement();
c0=zc.col(C.X);
r0=zc.row(C.Y);
pd.startPolygon(c0, r0);
}
while (e.hasMoreElements()) {
C=(Coordinates) e.nextElement();
c=zc.col(C.X);
r=zc.row(C.Y);
if (Math.abs(pd.c()-c)<1000&&Math.abs(pd.r()-r)<1000) {
pd.drawTo(c, r);
} else {
pd.finishPolygon();
pd.startPolygon(c, r);
}
}
pd.finishPolygon();
}
}
@Override
public boolean isSpecial() {
return Special;
}
@Override
public void setSpecial(final boolean f) {
Special=f;
}
@Override
public boolean equals(final ConstructionObject o) {
if (!(o instanceof JLocusTrackObject)||!o.valid()) {
return false;
}
JLocusTrackObject loc=(JLocusTrackObject) o;
if (V.size()!=loc.V.size()) {
return false;
}
final Enumeration e1=V.elements();
final Enumeration e2=loc.V.elements();
while (e1.hasMoreElements()) {
Coordinates C1=(Coordinates) e1.nextElement();
Coordinates C2=(Coordinates) e2.nextElement();
if ((Math.abs(C1.X-C2.X)>1e-8)||Math.abs(C1.Y-C2.Y)>1e-8) {
return false;
}
}
return true;
}
@Override
public ConstructionObject copy(final double x, final double y) {
PointObject newPM=null;
if (PM!=null) {
newPM=(PointObject) PM.getTranslation();
}
final JLocusTrackObject jl=new JLocusTrackObject(Cn.getTranslation(),
P.getTranslation(), PO, PN, O.getTranslation(), newPM);
jl.setTargetDefaults();
return jl;
}
// public void translate() {
// if (PM!=null) {
// PM=(PointObject) PM.getTranslation();
// }
//
// O=O.getTranslation();
// P=P.getTranslation();
//
// searchDependencies(Cn.getTranslation());
// }
}

View file

@ -0,0 +1,115 @@
/*
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: LineCircleIntersectionObject.java
import rene.util.xml.XmlWriter;
import rene.zirkel.construction.Construction;
import rene.zirkel.structures.Coordinates;
public class LineCircleIntersectionObject extends IntersectionObject {
public LineCircleIntersectionObject(final Construction c,
final PrimitiveLineObject P1, final PrimitiveCircleObject P2,
final boolean first) {
super(c, P1, P2);
First = first;
validate();
}
@Override
public void updateCircleDep() {
((PrimitiveCircleObject) P2).addDep(this);
((PrimitiveLineObject) P1).addDep(this);
}
@Override
public void validate() {
final boolean oldvalid = Valid;
if (!P1.valid() || !P2.valid())
Valid = false;
else
Valid = true;
if (!Valid)
return;
final Coordinates c = PrimitiveLineObject.intersect(
(PrimitiveLineObject) P1, (PrimitiveCircleObject) P2);
if (c == null) {
if (oldvalid && getConstruction().shouldSwitch()) {
doSwitch();
if (!getConstruction().noteSwitch())
Switched = false;
} else if (oldvalid && Alternate && Away == null
&& getConstruction().canAlternate()) {
First = !First;
}
Valid = false;
return;
}
if (getAway() != null) {
final double x = getAway().getX(), y = getAway().getY();
final double r = (x - c.X) * (x - c.X) + (y - c.Y) * (y - c.Y);
final double r1 = (x - c.X1) * (x - c.X1) + (y - c.Y1) * (y - c.Y1);
boolean flag = (r > r1);
if (!StayAway)
flag = !flag;
if (flag) {
setXY(c.X, c.Y);
} else {
setXY(c.X1, c.Y1);
}
} else {
if (First) {
setXY(c.X, c.Y);
} else {
setXY(c.X1, c.Y1);
}
}
if (Restricted) {
if (!((PrimitiveLineObject) P1).contains(X, Y))
Valid = false;
if (!(((PrimitiveCircleObject) P2).getStart() == this || ((PrimitiveCircleObject) P2)
.getEnd() == this)
&& !((PrimitiveCircleObject) P2).contains(X, Y))
Valid = false;
}
}
@Override
public void printArgs(final XmlWriter xml) {
super.printArgs(xml);
if (First)
xml.printArg("which", "first");
else
xml.printArg("which", "second");
}
@Override
public boolean isSwitchable() {
return true;
}
@Override
public boolean canAlternate() {
return true;
}
}

View file

@ -0,0 +1,222 @@
/*
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;
import rene.zirkel.construction.Construction;
import rene.zirkel.structures.Coordinates;
// file: IntersectionObject.java
public class LineIntersectionObject extends IntersectionObject {
public LineIntersectionObject(final Construction c,
final PrimitiveLineObject P1, final PrimitiveLineObject P2) {
super(c, P1, P2);
validate();
}
@Override
public void updateCircleDep() {
((PrimitiveLineObject) P1).addDep(this);
((PrimitiveLineObject) P2).addDep(this);
}
@Override
public void validate() {
if(!P1.valid() || !P2.valid()) {
Valid = false;
} else {
Valid = true;
}
if(!Valid) {
return;
}
final Coordinates coord = PrimitiveLineObject.intersect((PrimitiveLineObject) P1, (PrimitiveLineObject) P2);
if(coord == null) {
Valid = false;
return;
}
setXY(coord.X, coord.Y);
if(Restricted) {
if (!((PrimitiveLineObject) P1).contains(X, Y))
Valid = false;
else if(!((PrimitiveLineObject) P2).contains(X, Y)) {
Valid = false;
}
}
/**
* En 3D
*
* On veut résoudre le système : (dans le membre de gauche l'équation de P1, dans celui de droite, l'équation de P2)
* x1 + a1s = x2 + a2t
* y1 + b1s = y2 + b2t
* z1 + c1s = z2 + c2t
*
* (x1;y1;z1) est un point de P1 et (x2;y2;z2) un point de P2
* et (a1;b1;c1) est un vd de P1 et (a2;b2;c2) est un vd de P2
*
* Ce système est équivalent à :
* a1s - a2t = x2 - x1 (L1)
* b1s - b2t = y2 - y1 (L2)
* c1s - c2t = z2 - z1 (L3)
*/
try {
if(((PrimitiveLineObject) P1).getP1().is3D() && ((PrimitiveLineObject) P2).getP1().is3D()) {
double x1 = ((PrimitiveLineObject) P1).getP1().getX3D();
double y1 = ((PrimitiveLineObject) P1).getP1().getY3D();
double z1 = ((PrimitiveLineObject) P1).getP1().getZ3D();
double x2 = ((PrimitiveLineObject) P2).getP1().getX3D();
double y2 = ((PrimitiveLineObject) P2).getP1().getY3D();
double z2 = ((PrimitiveLineObject) P2).getP1().getZ3D();
/**
* Si P2 ou P2 sont des parallèles, la méthode Pi.getP2() ne renvoie rien.
* Pour connaitre un vecteur directeur de P1, il suffit de connaitre
* sa parallèle, instance de TwoPointLineObject
*/
ConstructionObject p1 = P1;
if(p1 instanceof ParallelObject) {
do{
p1 = ((ParallelObject) p1).getL();
} while(!(p1 instanceof TwoPointLineObject));
}
double a1 = ((TwoPointLineObject) p1).getP2().getX3D() - ((TwoPointLineObject) p1).getP1().getX3D();
double b1 = ((TwoPointLineObject) p1).getP2().getY3D() - ((TwoPointLineObject) p1).getP1().getY3D();
double c1 = ((TwoPointLineObject) p1).getP2().getZ3D() - ((TwoPointLineObject) p1).getP1().getZ3D();
ConstructionObject p2 = P2;
if(p2 instanceof ParallelObject) {
do{
p2 = ((ParallelObject) p2).getL();
} while(!(p2 instanceof TwoPointLineObject));
}
double a2 = ((TwoPointLineObject) p2).getP2().getX3D() - ((TwoPointLineObject) p2).getP1().getX3D();
double b2 = ((TwoPointLineObject) p2).getP2().getY3D() - ((TwoPointLineObject) p2).getP1().getY3D();
double c2 = ((TwoPointLineObject) p2).getP2().getZ3D() - ((TwoPointLineObject) p2).getP1().getZ3D();
//(L1) et (L2)
double det = -a1*b2 + b1*a2;
double dets = -(x2-x1)*b2 + (y2-y1)*a2;
double dett = a1*(y2-y1) - b1*(x2-x1);
int choice = 1;
if(Math.abs(det)<1e-12) { //(L1) et (L3)
det = -a1*c2 + c1*a2;
dets = -(x2-x1)*c2 + (z2-z1)*a2;
dett = a1*(z2-z1) - c1*(x2-x1);
choice = 2;
}
if(Math.abs(det)<1e-12) { //(L2) et (L3)
det = -b1*c2 + c1*b2;
dets = -(y2-y1)*c2 + (z2-z1)*b2;
dett = b1*(z2-z1) - c1*(y2-y1);
choice = 3;
}
double s = dets/det, t = dett/det;
if ( (choice==1 && Math.abs(c1*s-c2*t-z2+z1)<1e-12)
|| (choice==2 && Math.abs(b1*s-b2*t-y2+y1)<1e-12)
|| (choice==3 && Math.abs(a1*s-a2*t-x2+x1)<1e-12)) {
setX3D(x1+a1*s);
setY3D(y1+b1*s);
setZ3D(z1+c1*s);
setIs3D(true);
//System.out.println(x1+a1*s);
//System.out.println(y1+b1*s);
//System.out.println(z1+c1*s);
//System.out.println("-------");
setSuperHidden(false);
} else {
setSuperHidden(true);
}
}
} catch(final Exception ex){}
/*
if( (P1 instanceof TwoPointLineObject && ((TwoPointLineObject) P1).getP1().is3D())
|| (P1 instanceof TwoPointLineObject && ((TwoPointLineObject) P1).getP2().is3D())
|| (P2 instanceof TwoPointLineObject && ((TwoPointLineObject) P2).getP1().is3D())
|| (P2 instanceof TwoPointLineObject && ((TwoPointLineObject) P2).getP2().is3D())) {
try { // Dibs intersection 3D
double a1=((TwoPointLineObject) P1).getP1().getX3D();
double b1=((TwoPointLineObject) P1).getP1().getY3D();
double c1=((TwoPointLineObject) P1).getP1().getZ3D();
double a2=((TwoPointLineObject) P1).getP2().getX3D();
double b2=((TwoPointLineObject) P1).getP2().getY3D();
double c2=((TwoPointLineObject) P1).getP2().getZ3D();
double a3=((TwoPointLineObject) P2).getP1().getX3D();
double b3=((TwoPointLineObject) P2).getP1().getY3D();
double c3=((TwoPointLineObject) P2).getP1().getZ3D();
double a4=((TwoPointLineObject) P2).getP2().getX3D();
double b4=((TwoPointLineObject) P2).getP2().getY3D();
double c4=((TwoPointLineObject) P2).getP2().getZ3D();
double det =(a2-a1)*(b3-b4)+(b2-b1)*(a4-a3);
double dets=(b3-b1)*(a4-a3)-(a3-a1)*(b4-b3);
double dett=(a2-a1)*(b3-b1)-(b2-b1)*(a3-a1);
int choice = 1;
if(Math.abs(det)<1e-12) {
det =(b2-b1)*(c3-c4)+(c2-c1)*(b4-b3);
dets=(c3-c1)*(b4-b3)-(b3-b1)*(c4-c3);
dett=(b2-b1)*(c3-c1)-(c2-c1)*(b3-b1);
choice = 2;
}
if(Math.abs(det)<1e-12) {
det =(a2-a1)*(c3-c4)+(c2-c1)*(a4-a3);
dets=(a3-a1)*(c3-c4)+(c3-c1)*(a4-a3);
dett=(a2-a1)*(c3-c1)-(c2-c1)*(a3-a1);
choice = 3;
}
double s, t;
s=dets/det;
t=dett/det;
if ( (choice==1 && Math.abs((c2-c1)*s-(c4-c3)*t-c3+c1)<1e-12)
|| (choice==2 && Math.abs((b2-b1)*s-(b4-b3)*t-b3+b1)<1e-12)
|| (choice==3 && Math.abs((a2-a1)*s-(a4-a3)*t-a3+a1)<1e-12)) {
setX3D(a1+s*(a2-a1));
setY3D(b1+s*(b2-b1));
setZ3D(c1+s*(c2-c1));
setIs3D(true);
setSuperHidden(false);
} else {
setSuperHidden(true);
}
} catch (final Exception ex) {
//System.err.println("Error : "+ex);
}
}
*/
}
}

View file

@ -0,0 +1,193 @@
/*
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: LineObject.java
import rene.util.xml.XmlWriter;
import rene.gui.Global;
import rene.zirkel.ZirkelCanvas;
import rene.zirkel.construction.Construction;
import rene.zirkel.construction.Count;
import rene.zirkel.graphics.MyGraphics;
import rene.zirkel.graphics.MainGraphics;
public class LineObject extends TwoPointLineObject {
static Count N = new Count();
public LineObject(final Construction c, final PointObject p1,
final PointObject p2) {
super(c, p1, p2);
validate();
updateText();
}
@Override
public String getTag() {
return "Line";
}
@Override
public void updateText() {
setText(text2(Global.name("text.line"), P1.getName(), P2.getName()));
}
@Override
public void validate() {
if (!P1.valid() || !P2.valid()) {
Valid = false;
return;
} else {
Valid = true;
X1 = P1.getX();
Y1 = P1.getY();
X2 = P2.getX();
Y2 = P2.getY();
// compute normalized vector in the direction of the line:
DX = X2 - X1;
DY = Y2 - Y1;
R = Math.sqrt(DX * DX + DY * DY);
if (R < 1e-10) {
Valid = false;
return;
}
DX /= R;
DY /= R;
}
}
@Override
public void paint(final MyGraphics g, final ZirkelCanvas zc) {
if (!Valid || mustHide(zc))
return;
if (!Partial || zc.showHidden()) {
super.paint(g, zc);
return;
}
// compute middle of the screen:
final double xm = (zc.minX() + zc.maxX()) / 2, ym = (zc.minY() + zc
.maxY()) / 2;
// compute distance from middle to line:
final double d = (xm - X1) * DY - (ym - Y1) * DX;
// compute point with minimal distance
final double x = xm - d * DY, y = ym + d * DX;
// compute size of the screen
final double a = Math.max(zc.maxX() - zc.minX(), zc.maxY() - zc.minY());
if (Math.abs(d) > a)
return;
// compute distance from closest point to source
final double b = (x - X1) * DX + (y - Y1) * DY;
// compute the two visible endpoints
k1 = b - a;
k2 = b + a;
k12valid = true;
final double dd = (zc.maxX() - zc.minX()) / 20;
double dmin = -dd, dmax = R + dd;
if (Dep != null) {
for (int i = 0; i < NDep; i++) {
if (!Dep[i].valid() || Dep[i].mustHide(zc))
continue;
final double s = project(Dep[i].getX(), Dep[i].getY());
if (s - dd < dmin)
dmin = s - dd;
else if (s + dd > dmax)
dmax = s + dd;
}
}
if (k1 < dmin)
k1 = dmin;
if (k2 > dmax)
k2 = dmax;
final double c1 = zc.col(X1 + k1 * DX), c2 = zc.col(X1 + k2 * DX), r1 = zc
.row(Y1 + k1 * DY), r2 = zc.row(Y1 + k2 * DY);
// paint:
if (isStrongSelected() && g instanceof MainGraphics) {
((MainGraphics) g).drawMarkerLine(c1, r1, c2, r2);
}
g.setColor(this);
g.drawLine(c1, r1, c2, r2, this);
final String s = getDisplayText();
if (!s.equals("")) {
g.setLabelColor(this);
setFont(g);
DisplaysText = true;
if (KeepClose) {
final double side = (YcOffset < 0) ? 1 : -1;
drawLabel(g, s, zc, X1 + XcOffset * DX, Y1 + XcOffset * DY,
side * DX, side * DY, 0, 0);
} else
drawLabel(g, s, zc, X1 + k2 * DX / 2, Y1 + k2 * DY / 2, DX, DY,
XcOffset, YcOffset);
}
}
@Override
public void printArgs(final XmlWriter xml) {
xml.printArg("from", P1.getName());
xml.printArg("to", P2.getName());
super.printArgs(xml);
}
@Override
public void setDefaults() {
super.setDefaults();
setPartial(Cn.PartialLines);
}
@Override
public void toggleHidden() {
if (Hidden) {
Partial = false;
Hidden = false;
} else {
if (Partial) {
Partial = false;
Hidden = true;
} else
Partial = true;
}
}
@Override
public boolean hasUnit() {
return false;
}
@Override
public boolean nearto(final int c, final int r, final ZirkelCanvas zc) {
if (!displays(zc))
return false;
if (zc.showHidden() || !Partial || Dep == null || !k12valid)
return super.nearto(c, r, zc);
// compute point at c,r
final double x = zc.x(c), y = zc.y(r);
// test, if on visible part
final double s = project(x, y);
if (s < k1 || s > k2)
return false;
// compute distance from x,y
final double d = (x - X1) * DY - (y - Y1) * DX;
// scale in screen coordinates
Value = Math.abs(zc.col(zc.minX() + d) - zc.col(zc.minX()));
return Value < zc.selectionSize() * 2;
}
}

View file

@ -0,0 +1,268 @@
/*
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: LineCircleIntersectionObject.java
import rene.util.xml.XmlWriter;
import rene.zirkel.construction.Construction;
import rene.zirkel.structures.Coordinates;
public class LineQuadricIntersectionObject extends IntersectionObject {
public LineQuadricIntersectionObject(final Construction c,
final PrimitiveLineObject P1, final QuadricObject P2,
final boolean first) {
super(c, P1, P2);
First = first;
validate();
}
// public void updateCircleDep ()
// { ((QuadricObject)P2).addDep(this);
// ((PrimitiveLineObject)P1).addDep(this);
// }
@Override
public void validate() {
final boolean oldvalid = Valid;
if (!P1.valid() || !P2.valid())
Valid = false;
else
Valid = true;
if (!Valid)
return;
final Coordinates c = PrimitiveLineObject.intersect(
(PrimitiveLineObject) P1, (QuadricObject) P2);
if (c == null) {
if (oldvalid && getConstruction().shouldSwitch()) {
doSwitch();
if (!getConstruction().noteSwitch())
Switched = false;
} else if (oldvalid && Alternate && Away == null
&& getConstruction().canAlternate()) {
First = !First;
}
Valid = false;
return;
}
double X1, Y1;
if (getAway() != null) {
final double x = getAway().getX(), y = getAway().getY();
final double r = (x - c.X) * (x - c.X) + (y - c.Y) * (y - c.Y);
final double r1 = (x - c.X1) * (x - c.X1) + (y - c.Y1) * (y - c.Y1);
boolean flag = (r > r1);
if (!StayAway)
flag = !flag;
if (flag) {
setXY(c.X, c.Y);
X1 = c.X1;
Y1 = c.Y1;
} else {
setXY(c.X1, c.Y1);
X1 = c.X;
Y1 = c.Y;
}
} else {
if (First) {
setXY(c.X, c.Y);
X1 = c.X1;
Y1 = c.Y1;
} else {
setXY(c.X1, c.Y1);
X1 = c.X;
Y1 = c.Y;
}
}
if (Restricted) {
if (!((PrimitiveLineObject) P1).contains(X, Y)) {
if (!((PrimitiveLineObject) P1).contains(X1, Y1)) {
Valid = false;
} else {
setXY(X1, Y1);
}
}
}
if (P1 instanceof TwoPointLineObject&&(((TwoPointLineObject) P1).getP1().is3D()||((TwoPointLineObject) P1).getP2().is3D())
||((QuadricObject) P2).getP()[0].is3D()||((QuadricObject) P2).getP()[1].is3D()||((QuadricObject) P2).getP()[2].is3D()||((QuadricObject) P2).getP()[3].is3D()||((QuadricObject) P2).getP()[4].is3D()) {
TwoPointLineObject ligne= (TwoPointLineObject) P1;
try {
double x1=((PointObject) ligne.getP1()).getX3D();
double y1=((PointObject) ligne.getP1()).getY3D();
double z1=((PointObject) ligne.getP1()).getZ3D();
double x2=((PointObject) ligne.getP2()).getX3D();
double y2=((PointObject) ligne.getP2()).getY3D();
double z2=((PointObject) ligne.getP2 ()).getZ3D();
double x_O=getConstruction().find("O").getX();
double x_X=getConstruction().find("X").getX();
double x_Y=getConstruction().find("Y").getX();
double x_Z=getConstruction().find("Z").getX();
double alpha1=(getX()-x_O-x1*(x_X-x_O)-y1*(x_Y-x_O)-z1*(x_Z-x_O))/((x2-x1)*(x_X-x_O)+(y2-y1)*(x_Y-x_O)+(z2-z1)*(x_Z-x_O));
if (x1==x2&&y1==y2) {
double y_O=getConstruction().find("O").getY();
double y_X=getConstruction().find("X").getY();
double y_Y=getConstruction().find("Y").getY();
double y_Z=getConstruction().find("Z").getY();
alpha1=(getY()-y_O-x1*(y_X-y_O)-y1*(y_Y-y_O)-z1*(y_Z-y_O))/((x2-x1)*(y_X-y_O)+(y2-y1)*(y_Y-y_O)+(z2-z1)*(y_Z-y_O));
}
final double xM=x1+alpha1*(x2-x1);
final double yM=y1+alpha1*(y2-y1);
final double zM=z1+alpha1*(z2-z1);
setX3D(xM);
setY3D(yM);
setZ3D(zM);
setIs3D(true);
//setFixed("x(O)+("+xM+")*(x(X)-x(O))+("+yM+")*(x(Y)-x(O))+("+z1+zM+")*(x(Z)-x(O))", "y(O)+("+xM+")*(y(X)-y(O))+("+yM+")*(y(Y)-y(O))+("+zM+")*(y(Z)-y(O))");
} catch (final Exception eBary) {
}
// si les intersections n'existent pas en 3D, on les rendra superhidden
try {
boolean isGood=false;
double a1=((QuadricObject) P2).getP()[0].getX3D();
double b1=((QuadricObject) P2).getP()[0].getY3D();
double c1=((QuadricObject) P2).getP()[0].getZ3D();
double a2=((QuadricObject) P2).getP()[1].getX3D();
double b2=((QuadricObject) P2).getP()[1].getY3D();
double c2=((QuadricObject) P2).getP()[1].getZ3D();
double a3=((QuadricObject) P2).getP()[2].getX3D();
double b3=((QuadricObject) P2).getP()[2].getY3D();
double c3=((QuadricObject) P2).getP()[2].getZ3D();
double a4=(a1+a2)/2, b4=(b1+b2)/2, c4=(c1+c2)/2;
double a5=(a1+a3)/2, b5=(b1+b3)/2, c5=(c1+c3)/2;
double a6=a2-a1, b6=b2-b1, c6=c2-c1;
double a7=a3-a1, b7=b3-b1, c7=c3-c1;
double a8=b6*c7-c6*b7, b8=c6*a7-a6*c7, c8=a6*b7-b6*a7;
double n8=Math.sqrt(a8*a8+b8*b8+c8*c8);
a8 /=n8; b8 /= n8; c8 /= n8; // on norme P8
double a9=b8*c6-c8*b6, b9=c8*a6-a8*c6, c9=a8*b6-b8*a6;
double a10=b7*c8-c7*b8, b10=c7*a8-a7*c8, c10=a7*b8-b7*a8;
double a11=a5-a4, b11=b5-b4, c11=c5-c4;
double det1=b9*a10-a9*b10;
double det2=a10*b11-b10*a11;
double a12=a4+det2/det1*a9, b12=b4+det2/det1*b9, c12=c4+det2/det1*c9; // centre
double rcarre=(a12-a1)*(a12-a1)+(b12-b1)*(b12-b1)+(c12-c1)*(c12-c1); //rayon^2
double a15=((PointObject) ligne.getP1()).getX3D();
double b15=((PointObject) ligne.getP1()).getY3D();
double c15=((PointObject) ligne.getP1()).getZ3D();
double a16=((PointObject) ligne.getP2()).getX3D();
double b16=((PointObject) ligne.getP2()).getY3D();
double c16=((PointObject) ligne.getP2 ()).getZ3D();
double a17=a16-a15, b17=b16-b15, c17=c16-c15;
double a18=a15-a12, b18=b15-b12, c18=c15-c12;
try {
double x3=-(Math.sqrt((c17*c17+b17*b17+a17*a17)*rcarre+(-b17*b17-a17*a17)*c18*c18+(2*b17*b18+2*a17*a18)*c17*c18+(-b18*b18-a18*a18)*c17*c17-a17*a17*b18*b18+2*a17*a18*b17*b18-a18*a18*b17*b17)+c17*c18+b17*b18+a17*a18)/(c17*c17+b17*b17+a17*a17);
double x4=(Math.sqrt((c17*c17+b17*b17+a17*a17)*rcarre+(-b17*b17-a17*a17)*c18*c18+(2*b17*b18+2*a17*a18)*c17*c18+(-b18*b18-a18*a18)*c17*c17-a17*a17*b18*b18+2*a17*a18*b17*b18-a18*a18*b17*b17)-c17*c18-b17*b18-a17*a18)/(c17*c17+b17*b17+a17*a17);
double a19=a15+x3*a17, b19=b15+x3*b17, c19=c15+x3*c17; // soluces potentielles
double a20=a15+x4*a17, b20=b15+x4*b17, c20=c15+x4*c17;
double a21=a19-a1, b21=b19-b1, c21=c19-c1;
double a22=a20-a1, b22=b20-b1, c22=c20-c1;
double pscal19 =a8*a21+b8*b21+c8*c21;
double pscal20 =a8*a22+b8*b22+c8*c22;
if (Math.abs(pscal19)<1e-8) { // OK pour P19
final double xO=getConstruction().find("O").getX();
final double yO=getConstruction().find("O").getY();
final double deltaxX=getConstruction().find("X").getX()-xO;
final double deltaxY=getConstruction().find("Y").getX()-xO;
final double deltaxZ=getConstruction().find("Z").getX()-xO;
final double deltayX=getConstruction().find("X").getY()-yO;
final double deltayY=getConstruction().find("Y").getY()-yO;
final double deltayZ=getConstruction().find("Z").getY()-yO;
double posx=xO+a19*deltaxX+b19*deltaxY+c19*deltaxZ; // coordonnées 2D
double posy=yO+a19*deltayX+b19*deltayY+c19*deltayZ;
double erreurcarre=(c.X-posx)*(c.X-posx)+(c.Y-posy)*(c.Y-posy);
double erreurcarre2=(c.X1-posx)*(c.X1-posx)+(c.Y1-posy)*(c.Y1-posy);
if (erreurcarre<1e-8||erreurcarre2<1e-8) {
isGood=true;
setX3D(a19);
setY3D(b19);
setZ3D(c19);
}
else if (Math.abs(pscal20)<1e-8) {
posx=xO+a20*deltaxX+b20*deltaxY+c20*deltaxZ; // coordonnées 2D
posy=yO+a20*deltayX+b20*deltayY+c20*deltayZ;
erreurcarre=(c.X-posx)*(c.X-posx)+(c.Y-posy)*(c.Y-posy);
erreurcarre2=(c.X1-posx)*(c.X1-posx)+(c.Y1-posy)*(c.Y1-posy);
if (erreurcarre<1e-8||erreurcarre2<1e-8) {
isGood=true;
setX3D(a20);
setY3D(b20);
setZ3D(c20);
}
}
}
else if (Math.abs(pscal20)<1e-8) { // OK pour P20
final double xO=getConstruction().find("O").getX();
final double yO=getConstruction().find("O").getY();
final double deltaxX=getConstruction().find("X").getX()-xO;
final double deltaxY=getConstruction().find("Y").getX()-xO;
final double deltaxZ=getConstruction().find("Z").getX()-xO;
final double deltayX=getConstruction().find("X").getY()-yO;
final double deltayY=getConstruction().find("Y").getY()-yO;
final double deltayZ=getConstruction().find("Z").getY()-yO;
double posx=xO+a20*deltaxX+b20*deltaxY+c20*deltaxZ; // coordonnées 2D
double posy=yO+a20*deltayX+b20*deltayY+c20*deltayZ;
double erreurcarre=(c.X-posx)*(c.X-posx)+(c.Y-posy)*(c.Y-posy);
double erreurcarre2=(c.X1-posx)*(c.X1-posx)+(c.Y1-posy)*(c.Y1-posy);
if (erreurcarre<1e-8||erreurcarre2<1e-8) {
isGood=true;
setX3D(a20);
setY3D(b20);
setZ3D(c20);
}
}
}
catch (final Exception ex) {
//setSuperHidden(true);
}
if (!isGood) {
setSuperHidden(true);
}
}
catch (final Exception ex) {
}
}
}
@Override
public void printArgs(final XmlWriter xml) {
super.printArgs(xml);
if (First)
xml.printArg("which", "first");
else
xml.printArg("which", "second");
}
@Override
public boolean isSwitchable() {
return true;
}
@Override
public boolean canAlternate() {
return true;
}
}

View file

@ -0,0 +1,121 @@
/*
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: MidpointObject.java
import java.util.Enumeration;
import rene.util.xml.XmlWriter;
import rene.gui.Global;
import rene.zirkel.construction.Construction;
import rene.zirkel.construction.Count;
public class MidpointObject extends PointObject {
PointObject P1, P2;
static Count N = new Count();
public MidpointObject(final Construction c, final PointObject p1,
final PointObject p2) {
super(c, 0, 0);
P1 = p1;
P2 = p2;
Moveable = false;
validate();
updateText();
}
// public void setName ()
// {
//
// if (Cn.LongNames)
// Name=Global.name("name."+getTag())+" "+getN();
// else
// Name=Global.name("name.short."+getTag())+getN();
// // System.out.println("nom="+Name);
//
// }
@Override
public String getTag() {
return "Midpoint";
}
@Override
public int getN() {
return N.next();
}
@Override
public void updateText() {
try {
setText(text2(Global.name("text.midpoint"), P1.getName(), P2
.getName()));
} catch (final Exception e) {
}
}
@Override
public void validate() {
if (!P1.valid() || !P2.valid())
Valid = false;
else {
Valid = true;
setXY((P1.getX() + P2.getX()) / 2, (P1.getY() + P2.getY()) / 2);
if (P1.is3D()&&P2.is3D()) {
setXYZ((P1.getX3D() + P2.getX3D()) / 2, (P1.getY3D() + P2.getY3D()) / 2, (P1.getZ3D() + P2.getZ3D()) / 2);
setIs3D(true);
}
}
}
@Override
public void printArgs(final XmlWriter xml) {
xml.printArg("first", P1.getName());
xml.printArg("second", P2.getName());
printType(xml);
}
@Override
public Enumeration depending() {
super.depending();
DL.add(P1);
DL.add(P2);
return DL.elements();
}
@Override
public void translate() {
P1 = (PointObject) P1.getTranslation();
P2 = (PointObject) P2.getTranslation();
}
public PointObject getP1() {
return P1;
}
public PointObject getP2() {
return P2;
}
}

View file

@ -0,0 +1,38 @@
/*
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;
public interface MoveableObject {
public void move(double x, double y);
public void startDrag(double x, double y);
public void dragTo(double x, double y);
// public boolean hasChanged();
public double getOldX();
public double getOldY();
public boolean moveable();
}

View file

@ -0,0 +1,150 @@
/*
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: ParallelObject.java
import java.util.Enumeration;
import rene.util.xml.XmlWriter;
import rene.gui.Global;
import rene.zirkel.ZirkelCanvas;
import rene.zirkel.construction.Construction;
import rene.zirkel.construction.Count;
public class ParallelObject extends PrimitiveLineObject implements
MoveableObject {
protected PrimitiveLineObject L;
static Count N = new Count();
public ParallelObject(final Construction c, final PrimitiveLineObject l,
final PointObject p) {
super(c);
P1 = p;
L = l;
validate();
updateText();
}
@Override
public String getTag() {
return "Parallel";
}
@Override
public int getN() {
return N.next();
}
@Override
public void updateText() {
setText(text2(Global.name("text.parallel"), P1.getName(), L.getName()));
}
@Override
public void validate() {
if (!P1.valid() || !L.valid())
Valid = false;
else if (L instanceof SegmentObject
&& ((SegmentObject) L).getLength() == 0) {
Valid = false;
} else {
Valid = true;
X1 = P1.getX();
Y1 = P1.getY();
DX = L.getDX();
DY = L.getDY();
}
}
@Override
public void printArgs(final XmlWriter xml) {
xml.printArg("point", P1.getName());
xml.printArg("line", L.getName());
super.printArgs(xml);
}
@Override
public Enumeration depending() {
super.depending();
return depset(P1, L);
}
@Override
public void translate() {
P1 = (PointObject) P1.getTranslation();
L = (PrimitiveLineObject) L.getTranslation();
}
@Override
public boolean contains(final PointObject p) {
return p == P1;
}
@Override
public boolean hasUnit() {
return false;
}
public void dragTo(final double x, final double y) {
P1.move(x1 + (x - x3), y1 + (y - y3));
}
@Override
public void move(final double x, final double y) {
}
public boolean moveable() {
if (P1.moveable())
return true;
return false;
}
double x1, y1, x2, y2, x3, y3;
public void startDrag(final double x, final double y) {
x1 = P1.getX();
y1 = P1.getY();
x3 = x;
y3 = y;
}
public double getOldX() {
return 0;
}
public double getOldY() {
return 0;
}
@Override
public void snap(final ZirkelCanvas zc) {
if (moveable()) {
P1.snap(zc);
}
}
public PrimitiveLineObject getL(){
return L;
}
}

View file

@ -0,0 +1,175 @@
/*
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: PlumbObject.java
import java.util.Enumeration;
import rene.util.xml.XmlWriter;
import rene.gui.Global;
import rene.zirkel.ZirkelCanvas;
import rene.zirkel.construction.Construction;
import rene.zirkel.construction.Count;
public class PlumbObject extends PrimitiveLineObject implements MoveableObject {
PrimitiveLineObject L;
static Count N = new Count();
protected boolean Restricted = false;
public PlumbObject(final Construction c, final PrimitiveLineObject l,
final PointObject p) {
super(c);
P1 = p;
L = l;
validate();
updateText();
}
@Override
public String getTag() {
return "Plumb";
}
@Override
public int getN() {
return N.next();
}
@Override
public void updateText() {
setText(text2(Global.name("text.plumb"), P1.getName(), L.getName()));
}
@Override
public void validate() {
if (!P1.valid() || !L.valid())
Valid = false;
else {
Valid = true;
X1 = P1.getX();
Y1 = P1.getY();
DX = -L.getDY();
DY = L.getDX();
if (L instanceof SegmentObject
&& ((SegmentObject) L).getLength() == 0) {
Valid = false;
}
if (Restricted) {
if (!L.contains(X1, Y1))
Valid = false;
}
}
}
@Override
public void printArgs(final XmlWriter xml) {
xml.printArg("point", P1.getName());
xml.printArg("line", L.getName());
if (!Restricted)
xml.printArg("valid", "true");
super.printArgs(xml);
}
public boolean isRestricted() {
return Restricted;
}
public void setRestricted(final boolean flag) {
Restricted = flag;
}
public boolean canRestrict() {
return (L instanceof SegmentObject) || (L instanceof RayObject);
}
@Override
public void setMainParameter(boolean b) {
MainParameter = true;
}
@Override
public Enumeration depending() {
super.depending();
return depset(P1, L);
}
@Override
public void translate() {
P1 = (PointObject) P1.getTranslation();
L = (PrimitiveLineObject) L.getTranslation();
}
@Override
public boolean contains(final PointObject p) {
return p == P1;
}
@Override
public boolean hasUnit() {
return false;
}
public void dragTo(final double x, final double y) {
P1.move(x1 + (x - x3), y1 + (y - y3));
}
@Override
public void move(final double x, final double y) {
}
public boolean moveable() {
if (P1.moveable()) {
return true;
}
return false;
}
double x1, y1, x2, y2, x3, y3;
public void startDrag(final double x, final double y) {
x1 = P1.getX();
y1 = P1.getY();
x3 = x;
y3 = y;
}
public double getOldX() {
return 0;
}
public double getOldY() {
return 0;
}
@Override
public void snap(final ZirkelCanvas zc) {
if (moveable()) {
P1.snap(zc);
}
}
public PrimitiveLineObject getL(){
return L;
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,32 @@
/*
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;
public interface PointonObject {
public void repulse(PointObject P);
public void project(PointObject P);
public void project(PointObject P, double alpha);
public boolean canInteresectWith(ConstructionObject o);
}

View file

@ -0,0 +1,237 @@
/*
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;
import rene.util.xml.XmlWriter;
import rene.zirkel.construction.Construction;
import rene.zirkel.expression.Secant;
/**
* An intersection between two object that can bind points on them. The
* intersection is computed by projecting the point to both objects and
* predicting the intersection point.
*
* @author Rene
*/
public class PointonObjectIntersectionObject extends IntersectionObject {
public double Eps = 1e-5;
private boolean xAxisFunctionIntersection = false,
yAxisFunctionIntersection = false;
private FunctionObject F = null;
public PointonObjectIntersectionObject(final Construction c,
final ConstructionObject p1, final ConstructionObject p2) {
super(c, p1, p2);
if ((p1 instanceof AxisObject) && (p2 instanceof FunctionObject)) {
F = (FunctionObject) p2;
if (F.getEX().toString().equals("x")) {
final AxisObject ax = ((AxisObject) p1);
if (ax.DX == 1) {
xAxisFunctionIntersection = true;
} else {
yAxisFunctionIntersection = true;
}
}
} else if ((p2 instanceof AxisObject) && (p1 instanceof FunctionObject)) {
F = (FunctionObject) p1;
if (F.getEX().toString().equals("x")) {
final AxisObject ax = ((AxisObject) p2);
if (ax.DX == 1) {
xAxisFunctionIntersection = true;
} else {
yAxisFunctionIntersection = true;
}
}
}
}
@Override
public void validate(final double x, final double y) {
setXY(x, y);
validate();
}
@Override
public void printArgs(final XmlWriter xml) {
xml.printArg("first", P1.getName());
xml.printArg("second", P2.getName());
xml.printArg("x", "" + getX());
xml.printArg("y", "" + getY());
if (getAway() != null) {
if (StayAway) {
xml.printArg("awayfrom", getAway().getName());
} else {
xml.printArg("closeto", getAway().getName());
}
}
printType(xml);
if (!Restricted) {
xml.printArg("valid", "true");
}
}
/**
* Troublesome function to intersect two objects. This is done by projecting
* the intersection point to each of the objects in turn.
*
* To speed up the convergence, a line intersection is computed, where the
* lines approximate the objects.
*/
@Override
public void validate() {
// if ((P1==null)||(P2==null)) {
// System.out.println(this.getName());
// }
if (!P1.valid() || !P2.valid()) {
Valid = false;
} else {
Valid = true;
}
if (!Valid) {
return;
}
if (yAxisFunctionIntersection) {
try {
setXY(0, F.evaluateF(0));
return;
} catch (final Exception ex) {
}
}
if (xAxisFunctionIntersection) {
try {
double xn = 0;
for (int i = 0; i < 5; i++) {
double distold = projectOnce();
if (!Valid) {
return;
}
final double dist1 = projectOnce();
if (dist1 >= distold && dist1 < Eps) {
break;
}
distold = dist1;
double a = x1 - x;
double b = y1 - y;
double s = Math.max(Math.abs(a), Math.abs(b));
if (Math.abs(s) > 1e-13) {
a /= s;
}
b /= s;
double c = X - x1;
double d = Y - y1;
s = Math.max(Math.abs(c), Math.abs(d));
if (Math.abs(s) > 1e-13) {
c /= s;
}
d /= s;
final double e = a * x1 + b * y1;
final double f = c * X + d * Y;
final double det = a * d - c * b;
if (Math.abs(det) > 1e-13) {
xn = (e * d - f * b) / det;
final double dist2 = projectOnce();
if (dist2 < dist1) {
distold = dist2;
}
}
}
setXY(Secant.compute(F, xn - 1e-1, xn + 1e-1, 1e-10), 0);
return;
} catch (final Exception ex) {
}
}
double distold = projectOnce();
if (!Valid) {
return;
}
for (int i = 0; i < 10; i++) {
final double dist1 = projectOnce();
if (dist1 >= distold && dist1 < Eps) {
return;
}
distold = dist1;
double a = (x1 - x), b = (y1 - y);
double s = Math.max(Math.abs(a), Math.abs(b));
if (Math.abs(s) > 1e-13) {
a /= s;
}
b /= s;
double c = (X - x1), d = (Y - y1);
s = Math.max(Math.abs(c), Math.abs(d));
if (Math.abs(s) > 1e-13) {
c /= s;
}
d /= s;
final double e = a * x1 + b * y1, f = c * X + d * Y;
final double det = a * d - c * b;
if (Math.abs(det) > 1e-13) {
final double xn = (e * d - f * b) / det;
final double yn = (a * f - c * e) / det;
final double xold = X, yold = Y;
setXY(xn, yn);
final double dist2 = projectOnce();
if (dist2 > dist1) // interpolation does not work
{
setXY(xold, yold);
} else {
distold = dist2;
}
}
}
Valid = false;
}
double x, y, x1, y1;
public double projectOnce() {
x = X;
y = Y;
// System.out.println("Before: "+X+" "+Y);
((PointonObject) P1).project(this);
// System.out.println("Projected to "+P1.getName()+": "+X+" "+Y);
final double dist = Math.max(Math.abs(X - x), Math.abs(Y - y));
x1 = X;
y1 = Y;
((PointonObject) P2).project(this);
// System.out.println("Projected to "+P2.getName()+": "+X+" "+Y);
final double dist1 = Math.max(Math.abs(X - x1), Math.abs(Y - y1));
return Math.max(dist, dist1);
}
@Override
public boolean moveable() {
return true;
}
}

View file

@ -0,0 +1,988 @@
/*
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: PrimitiveCircleObject.java
import java.awt.Color;
import java.awt.Rectangle;
import java.util.Enumeration;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import rene.gui.Global;
import rene.util.xml.XmlWriter;
import rene.zirkel.ZirkelCanvas;
import rene.zirkel.construction.Construction;
import rene.zirkel.construction.Count;
import rene.zirkel.expression.Expression;
import rene.zirkel.expression.ExpressionColor;
import rene.zirkel.graphics.MyGraphics;
import rene.zirkel.graphics.MainGraphics;
import rene.zirkel.structures.Coordinates;
public class PrimitiveCircleObject extends ConstructionObject implements
PointonObject, InsideObject {
protected double X, Y, R;
static Count N=new Count();
boolean Partial=false;
PointObject Dep[]; // array for points, depending on the circle for partial
// display
int NDep; // number of points in Dep
PointObject M; // The midpoint
boolean Filled=false;
String StartPtName=null, EndPtName=null; // Border points name for Arcs
PointObject StartPt=null, EndPt=null; // Border points for Arcs
// PointObject RealCorrespondingStartPt=null; // for 3 pts Arcs only
boolean isArc3pts=false;
double A1, A2, A;
boolean Arc=true;
// Seulement pour les droites hyperboliques :
private double oldStartX=Double.NaN;
private double oldStartY=Double.NaN;
public PrimitiveCircleObject(final Construction c, final PointObject p) {
super(c);
setColor(ColorIndex, SpecialColor);
M=p;
Unit=Global.getParameter("unit.length", "");
}
public void validate() {
super.validate();
// Gestion de la continuité des droites sur le cercle horizon :
if (isDPLineObject()) {
// Premier passage, mémorisation de l'extrémité Start de l'arc
if (Double.isNaN(oldStartX)) {
oldStartX=getStart().getX();
oldStartY=getStart().getY();
} else {
final double d1=(oldStartX-getStart().getX())*(oldStartX-getStart().getX())
+(oldStartY-getStart().getY())*(oldStartY-getStart().getY());
final double d2=(oldStartX-getEnd().getX())*(oldStartX-getEnd().getX())
+(oldStartY-getEnd().getY())*(oldStartY-getEnd().getY());
// Si Start et End se sont échangés, on remet dans l'ordre (cela fonctionne
// car ce sont des arcs 180°) :
if (d2<d1) {
PointObject P=StartPt;
StartPt=EndPt;
EndPt=P;
}
oldStartX=getStart().getX();
oldStartY=getStart().getY();
}
}
}
public void setMR(final PointObject p1, final double r) {
M=p1;
R=r;
}
@Override
public void setDefaults() {
setShowName(Global.getParameter("options.circle.shownames", false));
setShowValue(Global.getParameter("options.circle.showvalues", false));
setColor(Global.getParameter("options.circle.color", 0), Global.getParameter("options.circle.pcolor", (ExpressionColor) null, this));
setColorType(Global.getParameter("options.circle.colortype", 0));
setFilled(Global.getParameter("options.circle.filled", false));
setSolid(Global.getParameter("options.circle.solid", false));
setHidden(Cn.Hidden);
setObtuse(Cn.Obtuse);
// setSolid(Cn.Solid);
setLarge(Cn.LargeFont);
setBold(Cn.BoldFont);
setPartial(Cn.Partial);
Cn.updateCircleDep();
}
@Override
public void setTargetDefaults() {
if (isDPLineObject()) {
setShowName(Global.getParameter("options.line.shownames", false));
setShowValue(Global.getParameter("options.line.showvalues", false));
setColor(Global.getParameter("options.line.color", 0), Global.getParameter("options.line.pcolor", (ExpressionColor) null, this));
setColorType(Global.getParameter("options.line.colortype", 0));
setFilled(Global.getParameter("options.line.filled", false));
setSolid(Global.getParameter("options.line.solid", false));
} else if (isDPSegmentObject()) {
setShowName(Global.getParameter("options.segment.shownames", false));
setShowValue(Global.getParameter("options.segment.showvalues", false));
setColor(Global.getParameter("options.segment.color", 0), Global.getParameter("options.segment.pcolor", (ExpressionColor) null, this));
setColorType(Global.getParameter("options.segment.colortype", 0));
setFilled(Global.getParameter("options.segment.filled", false));
setSolid(Global.getParameter("options.segment.solid", false));
} else {
setShowName(Global.getParameter("options.circle.shownames", false));
setShowValue(Global.getParameter("options.circle.showvalues", false));
setColor(Global.getParameter("options.circle.color", 0), Global.getParameter("options.circle.pcolor", (ExpressionColor) null, this));
setColorType(Global.getParameter("options.circle.colortype", 0));
setFilled(Global.getParameter("options.circle.filled", false));
setSolid(Global.getParameter("options.circle.solid", false));
}
}
@Override
public String getTag() {
return "Circle";
}
@Override
public int getN() {
return N.next();
}
@Override
public void paint(final MyGraphics g, final ZirkelCanvas zc) {
if (!Valid||mustHide(zc)) {
return;
}
final double c1=zc.col(X-R), c2=zc.col(X+R), r1=zc.row(Y+R), r2=zc.row(Y-R), r=(r2-r1)/2;
double ssa=1/Math.sqrt(2), ssb=-ssa;
// paint:
if (!zc.showHidden()&&Dep!=null&&NDep>0&&Partial
&&!hasRange()) // partial display
{
// System.out.println("partial display");
for (int i=0; i<NDep; i++) {
if (!Dep[i].valid()
||((!zc.isPreview())&&(Dep[i].mustHide(zc)))) {
continue;
}
double A=Math.atan2(Dep[i].getY()-Y, Dep[i].getX()-X);
if (A<0) {
A+=2*Math.PI;
}
final double a=A/Math.PI*180;
if (visible(zc)) {
if (isStrongSelected()&&g instanceof MainGraphics) {
((MainGraphics) g).drawMarkerArc((c1+c2)/2.0,
(r1+r2)/2.0, r, a-10, 20);
}
g.setColor(this);
g.drawCircleArc(c1+r, r1+r, r, a-10, 20, this);
}
if (i==0) {
final String s=getDisplayText();
if (!s.equals("")) {
g.setLabelColor(this);
DisplaysText=true;
final double sx=Math.cos(A-0.1);
final double sy=Math.sin(A-0.1);
drawLabel(g, s, zc, X+sx*R, Y+sy*R, sy, -sx,
XcOffset, YcOffset);
}
}
}
} else {
if (hasRange()) // arc display
{
computeSOE();
if (visible(zc)) {
if (isStrongSelected()&&g instanceof MainGraphics) {
((MainGraphics) g).drawMarkerArc((c1+c2)/2.0,
(r1+r2)/2.0, r, A1/Math.PI*180, A
/Math.PI*180);
}
g.setColor(this);
if (Filled) {
g.fillArc(c1, r1, c2-c1, r2-r1, A1/Math.PI*180,
A/Math.PI*180, Selected
||(getColorType()!=THIN),
getColorType()!=THICK, Arc, this);
} else if (visible(zc)) {
g.drawCircleArc(c1+r, r1+r, r, A1/Math.PI*180,
A/Math.PI*180, this);
}
}
ssa=Math.cos(A1+A/2);
ssb=Math.sin(A1+A/2);
} else if (Filled) {
if (visible(zc)) {
if (isStrongSelected()&&g instanceof MainGraphics) {
((MainGraphics) g).drawMarkerArc((c1+c2)/2.0,
(r1+r2)/2.0, r, 0, 360);
}
g.setColor(this);
g.fillOval(c1, r1, c2-c1, r2-r1, Indicated||Selected
||(getColorType()==NORMAL),
getColorType()!=THICK, this);
}
} else // full unfilled display
{
if (visible(zc)) {
if (isStrongSelected()&&g instanceof MainGraphics) {
((MainGraphics) g).drawMarkerArc((c1+c2)/2.0,
(r1+r2)/2.0, r, 0, 360);
}
g.setColor(this);
if (tracked()) {
zc.UniversalTrack.drawTrackCircle(this, c1+r, r1+r,
r);
}
g.drawCircle(c1+r, r1+r, r, this);
}
}
final String s=getDisplayText();
if (!s.equals("")) {
g.setLabelColor(this);
DisplaysText=true;
drawLabel(g, s, zc, X+ssa*R, Y+ssb*R, -ssa, ssb,
XcOffset, YcOffset);
}
}
}
@Override
public String getDisplayValue() {
// return ""+round(R,ZirkelCanvas.LengthsFactor);
return Global.getLocaleNumber(R, "lengths");
}
@Override
public String getEquation() {
return "(x"+helpDisplayNumber(false, -X)+")^2+"+"(y"
+helpDisplayNumber(false, -Y)+")^2="
+helpDisplayNumber(true, R*R);
}
@Override
public boolean isInRect(Rectangle r, ZirkelCanvas zc) {
double Xest=M.getX()+getR(), Yest=M.getY();
double Xnord=M.getX(), Ynord=M.getY()+getR();
double Xouest=M.getX()-getR(), Youest=M.getY();
double Xsud=M.getX(), Ysud=M.getY()-getR();
boolean b=r.contains(zc.col(Xest), zc.row(Yest));
b=b&&r.contains(zc.col(Xnord), zc.row(Ynord));
b=b&&r.contains(zc.col(Xouest), zc.row(Youest));
b=b&&r.contains(zc.col(Xsud), zc.row(Ysud));
return b;
}
@Override
public boolean nearto(final int c, final int r, final ZirkelCanvas zc) {
return nearto(c, r, false, zc);
}
@Override
public boolean nearto(final int c, final int r, final boolean ignorefill,
final ZirkelCanvas zc) {
if (!displays(zc)) {
return false;
}
final double x=zc.x(c)-X, y=zc.y(r)-Y;
if (!ignorefill&&Filled) {
final double d=Math.sqrt(x*x+y*y);
if (d<R) {
Value=0;
}
return d<R;
} else if (hasRange()) {
computeSOE();
double a=Math.atan2(y, x);
if (a<0) {
a+=2*Math.PI;
}
a-=A1;
if (a<0) {
a+=2*Math.PI;
}
final double d=Math.abs(Math.sqrt(x*x+y*y)-R);
if (a<=A+0.01) {
Value=Math.abs(zc.col(zc.minX()+d)-zc.col(zc.minX()));
}
return Value<zc.selectionSize()&&a<=A+0.01;
} // partial display:
else if (!zc.showHidden()&&NDep>0&&Partial) {
double d=Math.abs(Math.sqrt(x*x+y*y)-R);
Value=Math.abs(zc.col(zc.minX()+d)-zc.col(zc.minX()));
if (Math.abs(zc.col(zc.minX()+d)-zc.col(zc.minX()))>=zc.selectionSize()) {
return false;
}
d=Math.PI/18;
double a=Math.atan2(y, x);
if (a<0) {
a+=2*Math.PI;
}
for (int i=0; i<NDep; i++) {
if (!Dep[i].valid()||Dep[i].mustHide(zc)) {
continue;
}
double A=Math.atan2(Dep[i].getY()-Y, Dep[i].getX()-X);
if (A<0) {
A+=2*Math.PI;
}
double h=a-A;
if (h>2*Math.PI) {
h-=2*Math.PI;
}
if (h<-2*Math.PI) {
h+=2*Math.PI;
}
if (Math.abs(h)<d) {
return true;
}
}
return false;
} else {
final double d=Math.abs(Math.sqrt(x*x+y*y)-R);
Value=Math.abs(zc.col(zc.minX()+d)-zc.col(zc.minX()));
return Math.abs(zc.col(zc.minX()+d)-zc.col(zc.minX()))<zc.selectionSize();
}
}
@Override
public boolean onlynearto(final int c, final int r, final ZirkelCanvas zc) {
if (R<zc.dx(3*zc.pointSize())) {
return true;
}
if (hasRange()) {
double A1=Math.atan2(getStart().getY()-Y, getStart().getX()-X);
if (A1<0) {
A1+=2*Math.PI;
}
double A2=Math.atan2(getEnd().getY()-Y, getEnd().getX()-X);
if (A2<0) {
A2+=2*Math.PI;
}
double A=A2-A1;
if (A>=2*Math.PI) {
A-=2*Math.PI;
}
if (A<0) {
A+=2*Math.PI;
}
if (!Obtuse&&A>Math.PI) {
A1=A2;
A=2*Math.PI-A;
A2=A1+A;
}
if (A*R<zc.dx(6*zc.pointSize())) {
return true;
}
}
return false;
}
@Override
public double getX() {
return X;
}
@Override
public double getY() {
return Y;
}
@Override
public double getR() {
return R;
}
public static Coordinates intersect(final PrimitiveCircleObject c1,
final PrimitiveCircleObject c2) {
double dx=c2.X-c1.X, dy=c2.Y-c1.Y;
final double r=Math.sqrt(dx*dx+dy*dy);
if (r>c1.R+c2.R+1e-10) {
return null;
}
if (r<=1e-10) {
return new Coordinates(c1.X, c1.Y, c1.X, c1.Y);
}
final double l=(r*r+c1.R*c1.R-c2.R*c2.R)/(2*r);
dx/=r;
dy/=r;
final double x=c1.X+l*dx, y=c1.Y+l*dy;
double h=c1.R*c1.R-l*l;
if (h<-1e-10) {
return null;
}
if (h<0) {
h=0;
} else {
h=Math.sqrt(h);
}
return new Coordinates(x+h*dy, y-h*dx, x-h*dy, y+h*dx);
}
@Override
public boolean equals(final ConstructionObject o) {
if (!(o instanceof PrimitiveCircleObject)||!o.valid()) {
return false;
}
final PrimitiveCircleObject l=(PrimitiveCircleObject) o;
return equals(X, l.X)&&equals(Y, l.Y)&&equals(R, l.R);
}
@Override
public void setPartial(final boolean flag) {
if (flag==Partial) {
return;
}
Partial=flag;
if (flag) // depending objects no longer needed
{
Dep=new PointObject[16];
NDep=0;
} else {
Dep=null;
}
}
/**
* Add a point that depends on the circle. Dep is used for partial display.
*
* @param p
*/
public void addDep(final PointObject p) {
if (!Partial||hasRange()||Dep==null||NDep>=Dep.length) {
return;
}
Dep[NDep++]=p;
}
@Override
public void clearCircleDep() {
NDep=0;
}
@Override
public boolean isPartial() {
return Partial;
}
@Override
public void printArgs(final XmlWriter xml) {
xml.printArg("midpoint", M.getName());
if (Partial) {
xml.printArg("partial", "true");
}
if (Filled) {
xml.printArg("filled", "true");
}
if (getStart()!=null) {
xml.printArg("start", getStart().getName());
}
if (getEnd()!=null) {
xml.printArg("end", getEnd().getName());
}
if (!Obtuse) {
xml.printArg("acute", "true");
}
if (!Arc) {
xml.printArg("chord", "true");
}
super.printArgs(xml);
}
/**
* Need to setup the Dep array.
*/
@Override
public ConstructionObject copy(final double x, final double y) {
final PrimitiveCircleObject o=(PrimitiveCircleObject) super.copy(0, 0);
if (o.Partial) {
o.Dep=new PointObject[16];
o.NDep=0;
} else {
o.Dep=null;
}
return o;
}
// public void setDefaults ()
// { super.setDefaults();
// setPartial(Cn.Partial);
// }
/**
* A circle depends on its midpoint at least. Other circles depen on more
* points! No circle depends on Start and End.
*/
@Override
public Enumeration depending() {
super.depending();
DL.add(M);
return DL.elements();
}
/**
* A circle will mark the midpoint as secondary parameter.
*/
@Override
public Enumeration secondaryParams() {
DL.reset();
return depset(M);
}
@Override
public void toggleHidden() {
if (Hidden) {
Hidden=false;
} else {
if (Partial) {
setPartial(false);
Hidden=true;
} else {
setPartial(true);
}
}
}
public PointObject getP1() {
return M;
}
@Override
public void setFilled(final boolean flag) {
Filled=flag;
}
@Override
public boolean isFilled() {
return Filled;
}
@Override
public boolean isFilledForSelect() {
return Filled;
}
@Override
public void translate() {
M=(PointObject) M.getTranslation();
if (hasRange()) {
StartPt=(PointObject) StartPt.getTranslation();
EndPt=(PointObject) EndPt.getTranslation();
StartPtName=StartPt.getName();
EndPtName=EndPt.getName();
}
}
public void setRange(final String s1, final String s2) {
StartPtName=s1;
EndPtName=s2;
setRange((PointObject) Cn.find(StartPtName), (PointObject) Cn.find(EndPtName));
}
public void setRange(PointObject p1, PointObject p2) {
StartPt=p1;
EndPt=p2;
}
public PointObject getStart() {
if ((StartPt==null)&&(StartPtName!=null)) {
StartPt=(PointObject) Cn.find(StartPtName);
}
return StartPt;
}
public PointObject getEnd() {
if ((EndPt==null)&&(EndPtName!=null)) {
EndPt=(PointObject) Cn.find(EndPtName);
}
return EndPt;
}
public double getA1() {
return A1;
}
public double getA2() {
return A2;
}
public boolean hasRange() {
return getStart()!=null&&getEnd()!=null;
}
public void clearRange() {
StartPt=EndPt=null;
StartPtName=EndPtName=null;
}
@Override
public boolean maybeTransparent() {
return true;
}
@Override
public boolean locallyLike(final ConstructionObject o) {
if (!(o instanceof PrimitiveCircleObject)) {
return false;
}
return (equals(X, ((PrimitiveCircleObject) o).X)
&&equals(Y, ((PrimitiveCircleObject) o).Y)&&equals(R,
((PrimitiveCircleObject) o).R));
}
public boolean getArc() {
return Arc;
}
public void setArc(final boolean flag) {
Arc=flag;
}
public void detectArc3Pts() {
/* L'arc défini par trois points est issue d'une macro-construction.
* Par nécessité, les extrémités de l'arc sont des points construits
* qui "Sautent" en s'échangeant lorsque le cercle support change de
* "courbure". La formule en x se trouvant par exemple dans le getStart
* de l'arc est : if(a(C,A,B)<180,x(A),x(C))
* Pour tester le produit vectoriel OA^OC, il faut récupérer les "vraies"
* extrémités A et C, à savoir les points qui ont servi à créer l'arc.
* Cela se fait par une regExp.
*/
if (hasRange()) {
String st=getStart().getEX();
String reg="\\Qif(a(\\E[^,]*,[^,]*,[^\\)]*\\Q)<180,x(\\E([^\\)]*)\\Q),x(\\E([^\\)]*)\\)\\)";
Matcher m=Pattern.compile(reg).matcher(st);
// if (m.find()) {
// PointObject RealStartPt=(PointObject) Cn.find(m.group(1));
// PointObject RealEndPt=(PointObject) Cn.find(m.group(2));
// if (getStart().equals(RealStartPt)) {
// RealCorrespondingStartPt=StartPt;
// } else {
// RealCorrespondingStartPt=EndPt;
// }
// isArc3pts=true;
// System.out.println(RealCorrespondingStartPt.getName()+" "+getStart().getName());
// }
isArc3pts=m.find();
}
}
// Pour les arcs de cercles, calcule l'angle A=SOE avec S=start et E=end
public double computeSOE() {
A1=Math.atan2(getStart().getY()-Y, getStart().getX()-X);
if (A1<0) {
A1+=2*Math.PI;
}
A2=Math.atan2(getEnd().getY()-Y, getEnd().getX()-X);
if (A2<0) {
A2+=2*Math.PI;
}
if (A2<A1) {
A2+=2*Math.PI;
}
A=A2-A1;
if (!Obtuse&&A>Math.PI+1e-10) {
A1=A2;
if (A1>=2*Math.PI) {
A1-=2*Math.PI;
}
A=2*Math.PI-A;
A2=A1+A;
}
if (Partial) {
A1-=10/180.0*Math.PI;
A+=20/180.0*Math.PI;
}
return A;
}
// Pour les arcs de cercles, calcule l'angle A=SOP avec S=start et P=le point passé en param
public double computeSOP(PointObject P) {
double AS=Math.atan2(getStart().getY()-Y, getStart().getX()-X);
if (AS<0) {
AS+=2*Math.PI;
}
double AP=Math.atan2(P.getY()-Y, P.getX()-X);
if (AP<0) {
AP+=2*Math.PI;
}
if (AP<AS) {
AP+=2*Math.PI;
}
double AA=AP-AS;
if (!Obtuse&&AA>Math.PI+1e-10) {
AA=2*Math.PI-AA;
}
if (Partial) {
AA+=20/180.0*Math.PI;
}
return AA;
}
/**
* Test, if the projection of (x,y) to the arc contains that point.
*/
public boolean contains(final double x, final double y) {
if (!hasRange()) {
return true;
}
computeSOE();
double a=Math.atan2(y-Y, x-X);
if (a<0) {
a+=2*Math.PI;
}
double d=a-A1;
if (d<0) {
d+=2*Math.PI;
}
return d<A+0.0001;
}
public void project(final PointObject P) {
double dx=P.getX()-getX(), dy=P.getY()-getY();
final double r=Math.sqrt(dx*dx+dy*dy);
double X=0, Y=0;
if (r<1e-10) {
X=getX()+getR();
Y=getY();
} else {
X=getX()+dx/r*getR();
Y=getY()+dy/r*getR();
}
double Alpha=Math.atan2(P.getY()-getY(), P.getX()-getX());
if (hasRange()&&getStart()!=P&&getEnd()!=P) {
if (Alpha<0) {
Alpha+=2*Math.PI;
}
computeSOE();
final double a1=getA1(), a2=getA2();
if (Alpha<a1) {
Alpha+=2*Math.PI;
}
if (Alpha>a2) {
if (2*Math.PI-(Alpha-a1)<Alpha-a2) {
Alpha=a1;
} else {
Alpha=a2;
}
}
X=getX()+getR()*Math.cos(Alpha);
Y=getY()+getR()*Math.sin(Alpha);
}
P.setXY(X, Y);
P.setA(Alpha);
if (hasRange()&&(StartPt!=P)&&(EndPt!=P)&&(P.isPointOn())) {
double soe=computeSOE();
double sop=computeSOP(P);
if (soe!=0) {
P.setAlpha(sop/soe);
// if (isArc3pts&&!StartPt.equals(RealCorrespondingStartPt)) {
// P.setAlpha(1-sop/soe);
// }
}
}
}
@Override
public int getDistance(final PointObject P) {
final double dx=P.getX()-getX(), dy=P.getY()-getY();
final double r=Math.sqrt(dx*dx+dy*dy);
double X=0, Y=0;
if (r<1e-10) {
X=getX()+getR();
Y=getY();
} else {
X=getX()+dx/r*getR();
Y=getY()+dy/r*getR();
}
double Alpha=Math.atan2(P.getY()-getY(), P.getX()-getX());
if (hasRange()&&getStart()!=P&&getEnd()!=P) {
if (Alpha<0) {
Alpha+=2*Math.PI;
}
computeSOE();
final double a1=getA1(), a2=getA2();
if (Alpha<a1) {
Alpha+=2*Math.PI;
}
if (Alpha>a2) {
if (2*Math.PI-(Alpha-a1)<Alpha-a2) {
Alpha=a1;
} else {
Alpha=a2;
}
}
X=getX()+getR()*Math.cos(Alpha);
Y=getY()+getR()*Math.sin(Alpha);
}
final double d=Math.sqrt((P.getX()-X)*(P.getX()-X)
+(P.getY()-Y)*(P.getY()-Y));
return (int) Math.round(d*Cn.getPixel());
}
public double det(PointObject M, PointObject N) {
double determinant=(M.getX()-X)*(N.getY()-Y)-(M.getY()-Y)*(N.getX()-X);
return determinant;
}
public void project(final PointObject P, final double alpha) {
if (hasRange()&&(StartPt!=P)&&(EndPt!=P)&&(P.isPointOn())) {
detectArc3Pts();
double soe=computeSOE();
double k=P.getAlpha();
// if (isArc3pts&&!StartPt.equals(RealCorrespondingStartPt)) {
// k=1-k;
// }
double sop=soe*k;
// Rotation du vecteur OS d'angle sop :
PointObject start=getStart();
double xx=(start.getX()-getX())*Math.cos(sop)-(start.getY()-getY())*Math.sin(sop);
double yy=(start.getX()-getX())*Math.sin(sop)+(start.getY()-getY())*Math.cos(sop);
double unit=getR()/(Math.sqrt((start.getX()-getX())*(start.getX()-getX())+(start.getY()-getY())*(start.getY()-getY())));
double x0=getX()+xx*unit, y0=getY()+yy*unit;
// if (isArc3pts&&!StartPt.equals(RealCorrespondingStartPt)) {
//
// }
// Gestion de la continuité du déplacement d'un point sur objet sur un arc de cercle
// Si les extrémités de l'arc s'échangent, il faut un coef. barycentrique égal à
// 1-k :
if (isArc3pts) {
sop=soe*(1-k);
xx=(start.getX()-getX())*Math.cos(sop)-(start.getY()-getY())*Math.sin(sop);
yy=(start.getX()-getX())*Math.sin(sop)+(start.getY()-getY())*Math.cos(sop);
unit=getR()/(Math.sqrt((start.getX()-getX())*(start.getX()-getX())+(start.getY()-getY())*(start.getY()-getY())));
double x1=getX()+xx*unit, y1=getY()+yy*unit;
double d0=(P.getX()-x0)*(P.getX()-x0)+(P.getY()-y0)*(P.getY()-y0);
double d1=(P.getX()-x1)*(P.getX()-x1)+(P.getY()-y1)*(P.getY()-y1);
if (d0>d1) {
x0=x1;
y0=y1;
}
}
// Coordonnées du point P :
P.setXY(x0, y0);
if (!Obtuse) {
// S'il s'agit d'un arc180, il faut que Start,P et End
// soient sur l'arc dans le même ordre, on étudie donc
// le produit des déterminants :
if (det(getStart(), getEnd())*det(getStart(), P)<0) {
k=-k;
P.setAlpha(k);
sop=soe*k;
// Rotation du vecteur OS d'angle sop :
start=getStart();
xx=(start.getX()-getX())*Math.cos(sop)-(start.getY()-getY())*Math.sin(sop);
yy=(start.getX()-getX())*Math.sin(sop)+(start.getY()-getY())*Math.cos(sop);
// Coordonnées du point P :
P.setXY(getX()+xx*unit, getY()+yy*unit);
}
}
// System.out.println("**** detSOE="+det(getStart(), getEnd())+" : detSOP="+det(getStart(), P));
// System.out.println("k="+k);
} else {
final double dx=P.getX()-getX(), dy=P.getY()-getY();
final double r=Math.sqrt(dx*dx+dy*dy);
double X=0, Y=0;
if (r<1e-10) {
X=getX()+getR();
Y=getY();
} else {
X=getX()+dx/r*getR();
Y=getY()+dy/r*getR();
}
if (hasRange()&&getStart()!=P&&getEnd()!=P) {
double Alpha=P.getAlpha();
if (Alpha<0) {
Alpha+=2*Math.PI;
}
if (Alpha>=2*Math.PI) {
Alpha-=2*Math.PI;
}
computeSOE();
final double a1=getA1(), a2=getA2();
if (Alpha<a1) {
Alpha+=2*Math.PI;
}
if (Alpha>a2) {
if (2*Math.PI-(Alpha-a1)<Alpha-a2) {
Alpha=a1;
} else {
Alpha=a2;
}
}
P.setA(Alpha);
X=getX()+getR()*Math.cos(Alpha);
Y=getY()+getR()*Math.sin(Alpha);
} else {
X=getX()+getR()*Math.cos(alpha);
Y=getY()+getR()*Math.sin(alpha);
}
P.setXY(X, Y);
}
}
public double containsInside(final PointObject P) {
final double dx=P.getX()-X, dy=P.getY()-Y;
final double r=Math.sqrt(dx*dx+dy*dy);
if (r<R*(1-1e-10)) {
return 1;
}
if (r<R*(1+1e-10)) {
return 0.5;
}
return 0;
}
public boolean keepInside(final PointObject P) {
final double dx=P.getX()-X, dy=P.getY()-Y;
final double r=Math.sqrt(dx*dx+dy*dy);
double f=1;
if (Filled&&ColorType==THIN) {
f=0.9999;
}
if (r<R*f||R<1e-10) {
return true;
}
P.setXY(X+dx/r*(R*f), Y+dy/r*(R*f));
return false;
}
public boolean canInteresectWith(final ConstructionObject o) {
return true;
}
public void repulse(final PointObject P) {
project(P);
}
}

View file

@ -0,0 +1,467 @@
/*
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: PrimitiveLineObject.java
import java.awt.Checkbox;
import java.awt.Color;
import java.awt.Frame;
import java.awt.TextField;
import java.awt.event.FocusEvent;
import java.util.Enumeration;
import eric.JEricPanel;
import rene.gui.Global;
import rene.gui.IconBar;
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.expression.ExpressionColor;
import rene.zirkel.graphics.MyGraphics;
import rene.zirkel.graphics.MainGraphics;
import rene.zirkel.structures.Coordinates;
public class PrimitiveLineObject extends ConstructionObject implements
PointonObject {
protected double X1, Y1, DX, DY;
protected double DX3D=0;
protected double DY3D=0;
protected double DZ3D=0;
protected PointObject P1;
PointObject Dep[];
int NDep;
boolean Partial = false;
public PrimitiveLineObject(final Construction c) {
super(c);
setColor(ColorIndex, SpecialColor);
}
public PrimitiveLineObject(final Construction c, final String Nme) {
super(c, Nme);
setColor(ColorIndex, SpecialColor);
}
public void setP1DXDY(final PointObject p, final double dx, final double dy) {
P1 = p;
DX = dx;
DY = dy;
X1 = P1.getX();
Y1 = P1.getY();
}
@Override
public void setDefaults() {
setShowName(Global.getParameter("options.line.shownames", false));
setShowValue(Global.getParameter("options.line.showvalues", false));
setColor(Global.getParameter("options.line.color", 0), Global
.getParameter("options.line.pcolor", (ExpressionColor) null, this));
setColorType(Global.getParameter("options.line.colortype", 0));
setHidden(Cn.Hidden);
setObtuse(Cn.Obtuse);
setSolid(Cn.Solid);
setLarge(Global.getParameter("options.line.large", false));
setBold(Global.getParameter("options.line.bold", false));
}
@Override
public void setTargetDefaults() {
setShowName(Global.getParameter("options.line.shownames", false));
setShowValue(Global.getParameter("options.line.showvalues", false));
setColor(Global.getParameter("options.line.color", 0), Global
.getParameter("options.line.pcolor", (ExpressionColor) null, this));
setColorType(Global.getParameter("options.line.colortype", 0));
setLarge(Global.getParameter("options.line.large", false));
setBold(Global.getParameter("options.line.bold", false));
}
@Override
public String getTag() {
return "Line";
}
double k1, k2;
boolean k12valid = false;
@Override
public void paint(final MyGraphics g, final ZirkelCanvas zc) {
if (!Valid || mustHide(zc)) {
return;
}
// compute middle of the screen:
final double xm = (zc.minX() + zc.maxX()) / 2, ym = (zc.minY() + zc
.maxY()) / 2;
// compute distance from middle to line:
final double d = (xm - X1) * DY - (ym - Y1) * DX;
// compute point with minimal distance
final double x = xm - d * DY, y = ym + d * DX;
// compute size of the screen
final double a = Math.max(zc.maxX() - zc.minX(), zc.maxY() - zc.minY());
if (Math.abs(d) > a) {
return;
}
// compute distance from closest point to source
final double b = (x - X1) * DX + (y - Y1) * DY;
// compute the two visible endpoints
k1 = b - a;
k2 = b + a;
k12valid = true;
if (Partial && Dep != null && !zc.showHidden()) {
final double dd = (zc.maxX() - zc.minX()) / 20;
double dmin = -dd, dmax = +dd;
if (Dep != null) {
for (int i = 0; i < NDep; i++) {
if (!Dep[i].valid() || Dep[i].mustHide(zc)) {
continue;
}
final double s = project(Dep[i].getX(), Dep[i].getY());
if (s - dd < dmin) {
dmin = s - dd;
} else if (s + dd > dmax) {
dmax = s + dd;
}
}
}
if (k1 < dmin) {
k1 = dmin;
}
if (k2 > dmax) {
k2 = dmax;
}
}
final double c1 = zc.col(X1 + k1 * DX), c2 = zc.col(X1 + k2 * DX), r1 = zc
.row(Y1 + k1 * DY), r2 = zc.row(Y1 + k2 * DY);
// paint:
if (isStrongSelected() && g instanceof MainGraphics) {
((MainGraphics) g).drawMarkerLine(c1, r1, c2, r2);
}
g.setColor(this);
if (tracked())
zc.UniversalTrack.drawTrackLine(this, c1, r1, c2, r2);
g.drawLine(c1, r1, c2, r2, this);
final String s = getDisplayText();
if (!s.equals("")) {
g.setLabelColor(this);
setFont(g);
DisplaysText = true;
if (KeepClose) {
final double side = (YcOffset < 0) ? 1 : -1;
drawLabel(g, s, zc, X1 + XcOffset * DX, Y1 + XcOffset * DY,
side * DX, side * DY, 0, 0);
} else {
drawLabel(g, s, zc, x + a / 5 * DX, y + a / 5 * DY, DX, DY,
XcOffset, YcOffset);
}
}
}
@Override
public boolean canKeepClose() {
return true;
}
@Override
public void setKeepClose(final double x, final double y) {
KeepClose = true;
XcOffset = (x - X1) * DX + (y - Y1) * DY;
YcOffset = (x - X1) * DY - (y - Y1) * DX;
}
@Override
public boolean nearto(final int c, final int r, final ZirkelCanvas zc) {
if (!displays(zc)) {
return false;
}
// compute point at c,r
final double x = zc.x(c), y = zc.y(r);
// compute distance from x,y
final double d = (x - X1) * DY - (y - Y1) * DX;
// scale in screen coordinates
Value = Math.abs(zc.col(zc.minX() + d) - zc.col(zc.minX()));
return Value < zc.selectionSize() * 2;
}
@Override
public boolean onlynearto(final int c, final int r, final ZirkelCanvas zc) {
return false;
}
public static Coordinates intersect(final PrimitiveLineObject l1,
final PrimitiveLineObject l2) // compute the intersection
// coordinates of two lines
{
final double det = -l1.DX * l2.DY + l1.DY * l2.DX;
if (Math.abs(det) < 1e-10) {
return null;
}
final double a = (-(l2.X1 - l1.X1) * l2.DY + (l2.Y1 - l1.Y1) * l2.DX)
/ det;
return new Coordinates(l1.X1 + a * l1.DX, l1.Y1 + a * l1.DY);
}
public static Coordinates intersect(final PrimitiveLineObject l,
final PrimitiveCircleObject c) // compute the intersection
// coordinates of a line with a
// circle
{
double x = c.getX(), y = c.getY();
final double r = c.getR();
final double d = (x - l.X1) * l.DY - (y - l.Y1) * l.DX;
if (Math.abs(d) > r + 1e-10) {
return null;
}
x -= d * l.DY;
y += d * l.DX;
double h = r * r - d * d;
if (h > 0) {
h = Math.sqrt(h);
} else {
h = 0;
}
return new Coordinates(x + h * l.DX, y + h * l.DY, x - h * l.DX, y - h
* l.DY);
}
public static Coordinates intersect(final PrimitiveLineObject l,
final QuadricObject q) {
// compute the intersection coordinates of a line with a quadric
// done with XCAS :
// System.out.println("l.DX="+l.DX+" l.DY="+l.DY);
final double M = -l.DY, N2 = l.DX, P = -(M * l.X1 + N2 * l.Y1);
// System.out.println("M="+M+" N2="+N2+" P="+P);
final double A = q.X[0], B = q.X[1], C = q.X[2], D = q.X[3], E = q.X[4], F = q.X[5];
double x1 = 0, x2 = 0, y1 = 0, y2 = 0;
if (N2 != 0) {
final double part1 = -2 * B * M * P - C * N2 * N2 + D * M * N2 + E
* N2 * P;
final double part2 = Math.abs(N2)
* Math.sqrt(-2 * M * D * N2 * C + 4 * P * D * A * N2 + 4
* P * M * B * C + 4 * E * M * N2 * F - 2 * E * P
* N2 * C - 2 * E * P * M * D - 4 * M * M * B * F
- 4 * P * P * A * B - 4 * A * N2 * N2 * F + N2 * N2
* C * C + M * M * D * D + E * E * P * P);
final double part3 = 2 * A * N2 * N2 + 2 * B * M * M + (-2 * E) * M
* N2;
x1 = (part1 + part2) / part3;
if (Double.isNaN(x1)) {
return null;
}
y1 = (-M * x1 - P) / N2;
x2 = (part1 - part2) / part3;
y2 = (-M * x2 - P) / N2;
if (((x2 - x1) / l.DX) < 0) {
return new Coordinates(x2, y2, x1, y1);
}
} else {
x1 = -P / M;
x2 = x1;
final double part1 = -D * M * M + E * M * P;
final double part2 = Math.abs(M)
* Math.sqrt(4 * P * M * B * C - 2 * E * P * M * D - 4 * M
* M * B * F - 4 * P * P * A * B + M * M * D * D + E
* E * P * P);
final double part3 = 2 * M * M * B;
y1 = (part1 + part2) / part3;
if (Double.isNaN(y1)) {
return null;
}
y2 = (part1 - part2) / part3;
if (((y2 - y1) / l.DY) < 0) {
return new Coordinates(x2, y2, x1, y1);
}
}
return new Coordinates(x1, y1, x2, y2);
}
public double getDX() {
return DX;
}
public double getDY() {
return DY;
}
public double getDX3D() {
return DX3D;
}
public double getDY3D() {
return DY3D;
}
public double getDZ3D() {
return DZ3D;
}
@Override
public double getX() {
return X1;
}
@Override
public double getY() {
return Y1;
}
@Override
public String getEquation() {
double y = DX, x = -DY;
double c = y * Y1 + x * X1;
if (c < 0) {
c = -c;
x = -x;
y = -y;
}
if (Math.abs(x) < 1e-10 && y < 0) {
c = -c;
x = -x;
y = -y;
} else if (Math.abs(y) < 1e-10 && x < 0) {
c = -c;
x = -x;
y = -y;
}
final String s = helpDisplayValue(true, x, "x");
return s + helpDisplayValue(s.equals(""), y, "y") + "="
+ ((Math.abs(c) < 1e-10) ? "0" : helpDisplayNumber(true, c));
}
/**
* Test, if the projection of (x,y) to the line contains that point.
*/
public boolean contains(final double x, final double y) {
return true;
}
@Override
public void printArgs(final XmlWriter xml) {
if (Partial) {
xml.printArg("partial", "true");
}
}
public double project(final double x, final double y) {
return (x - X1) * DX + (y - Y1) * DY;
}
@Override
public boolean equals(final ConstructionObject o) {
if (!(o instanceof PrimitiveLineObject) || !o.valid()) {
return false;
}
final PrimitiveLineObject l = (PrimitiveLineObject) o;
return equals(DX * l.DY - DY * l.DX, 0)
&& equals((X1 - l.X1) * DY - (Y1 - l.Y1) * DX, 0);
}
public PointObject getP1() {
return P1;
}
public Enumeration points() {
return depending();
}
@Override
public boolean locallyLike(final ConstructionObject o) {
if (!(o instanceof PrimitiveLineObject)) {
return false;
}
return (equals(DX, ((PrimitiveLineObject) o).DX) && equals(DY,
((PrimitiveLineObject) o).DY))
|| (equals(-DX, ((PrimitiveLineObject) o).DX) && equals(-DY,
((PrimitiveLineObject) o).DY));
}
@Override
public boolean isPartial() {
return Partial;
}
@Override
public void setPartial(final boolean partial) {
if (Partial == partial) {
return;
}
Partial = partial;
if (partial) {
Dep = new PointObject[16];
NDep = 0;
} else {
Dep = null;
}
}
public void addDep(final PointObject p) {
if (!Partial || Dep == null || NDep >= Dep.length) {
return;
}
Dep[NDep++] = p;
}
@Override
public void clearCircleDep() {
NDep = 0;
}
@Override
public int getDistance(final PointObject P) {
final double h = project(P.getX(), P.getY());
final double dx = P.getX() - (getX() + h * getDX());
final double dy = P.getY() - (getY() + h * getDY());
final double d = Math.sqrt(dx * dx + dy * dy);
return (int) Math.round(d * Cn.getPixel());
}
public void project(final PointObject P) {
final double h = project(P.getX(), P.getY());
P.setXY(getX() + h * getDX(), getY() + h * getDY());
P.setA(h);
}
public void project(final PointObject P, final double alpha) {
P.setXY(getX() + alpha * getDX(), getY() + alpha * getDY());
}
public boolean canInteresectWith(final ConstructionObject o) {
return true;
}
public void repulse(final PointObject P) {
project(P);
}
}

View file

@ -0,0 +1,829 @@
/*
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: QuadricObject.java
import java.util.ArrayList;
import java.util.Enumeration;
import rene.util.xml.XmlWriter;
import rene.gui.Global;
import rene.zirkel.ZirkelCanvas;
import rene.zirkel.construction.Construction;
import rene.zirkel.construction.Count;
import rene.zirkel.expression.ExpressionColor;
import rene.zirkel.expression.Quartic;
import rene.zirkel.graphics.MyGraphics;
import rene.zirkel.graphics.PolygonDrawer;
import rene.zirkel.structures.Complex;
import rene.zirkel.structures.CoordinatesXY;
public class QuadricObject extends ConstructionObject implements PointonObject,
MoveableObject {
public PointObject P[];
static Count N=new Count();
public double X[];
public QuadricObject(final Construction c, final PointObject p[]) {
super(c);
P=p;
validate();
updateText();
}
@Override
public void setDefaults() {
setShowName(Global.getParameter("options.quadric.shownames", false));
setShowValue(Global.getParameter("options.quadric.showvalues", false));
setColor(Global.getParameter("options.quadric.color", 0), Global.getParameter("options.circle.pcolor", (ExpressionColor) null, this));
setColorType(Global.getParameter("options.quadric.colortype", 0));
setHidden(Cn.Hidden);
//setObtuse(Cn.Obtuse);
//setSolid(Cn.Solid);
setLarge(Cn.LargeFont);
setBold(Cn.BoldFont);
//setPartial(Cn.Partial);
}
@Override
public void setTargetDefaults() {
setShowName(Global.getParameter("options.quadric.shownames", false));
setShowValue(Global.getParameter("options.quadric.showvalues", false));
setColor(Global.getParameter("options.quadric.color", 0), Global.getParameter("options.circle.pcolor", (ExpressionColor) null, this));
setColorType(Global.getParameter("options.quadric.colortype", 0));
}
@Override
public String getTag() {
return "Quadric";
}
@Override
public int getN() {
return N.next();
}
@Override
public void updateText() {
try {
final String Names[]=new String[P.length];
for (int i=0; i<P.length; i++) {
Names[i]=P[i].getName();
}
if (P[0].is3D()&&P[1].is3D()&&P[2].is3D()&&P[3].is3D()&&P[4].is3D()) setText(Global.name("text.circle3D"));
else setText(textAny(Global.name("text.quadric"), Names));
} catch (final Exception e) {
}
}
private static final double cub2=Math.pow(2, 1.0/3.0);
public static ArrayList<CoordinatesXY> intersect(final QuadricObject quad1,
final QuadricObject quad2) {
ArrayList<CoordinatesXY> points=new ArrayList<CoordinatesXY>();
// coeffs de x^2, xy, y^2, x, y et Cte :
double a=quad1.X[0], b=quad1.X[4], c=quad1.X[1], d=quad1.X[2], e=quad1.X[3], f=quad1.X[5];
double aa=quad2.X[0], bb=quad2.X[4], cc=quad2.X[1], dd=quad2.X[2], ee=quad2.X[3], ff=quad2.X[5];
// System.out.println("*************");
// System.out.println("a="+a);
// System.out.println("b="+b);
// System.out.println("c="+c);
// System.out.println("d="+d);
// System.out.println("e="+e);
// System.out.println("f="+f);
// System.out.println("aa="+aa);
// System.out.println("bb="+bb);
// System.out.println("cc="+cc);
// System.out.println("dd="+dd);
// System.out.println("ee="+ee);
// System.out.println("ff="+ff);
double k1=-aa*b*bb*c+a*bb*bb*c+aa*aa*c*c+aa*b*b*cc-a*b*bb*cc-2*a*aa*c*cc+a*a*cc*cc;
double k2=bb*bb*c*d-b*bb*cc*d-2*aa*c*cc*d+2*a*cc*cc*d-b*bb*c*dd+2*aa*c*c*dd+b*b*cc*dd-2*a*c*cc*dd-aa*bb*c*e+2*aa*b*cc*e-a*bb*cc*e-aa*b*c*ee+2*a*bb*c*ee-a*b*cc*ee;
double k3=cc*cc*d*d-2*c*cc*d*dd+c*c*dd*dd-bb*cc*d*e-bb*c*dd*e+2*b*cc*dd*e+aa*cc*e*e+2*bb*c*d*ee-b*cc*d*ee-b*c*dd*ee-aa*c*e*ee-a*cc*e*ee+a*c*ee*ee+bb*bb*c*f-b*bb*cc*f-2*aa*c*cc*f+2*a*cc*cc*f-b*bb*c*ff+2*aa*c*c*ff+b*b*cc*ff-2*a*c*cc*ff;
double k4=cc*dd*e*e-cc*d*e*ee-c*dd*e*ee+c*d*ee*ee+2*cc*cc*d*f-2*c*cc*dd*f-bb*cc*e*f+2*bb*c*ee*f-b*cc*ee*f-2*c*cc*d*ff+2*c*c*dd*ff-bb*c*e*ff+2*b*cc*e*ff-b*c*ee*ff;
double k5=-cc*e*ee*f+c*ee*ee*f+cc*cc*f*f+cc*e*e*ff-c*e*ee*ff-2*c*cc*f*ff+c*c*ff*ff;
double u1=k2/(4*k1);
double u2=k2*k2/(4*k1*k1)-2*k3/(3*k1);
double u3=k2*k2/(2*k1*k1)-4*k3/(3*k1);
double u4=-k2*k2*k2/(k1*k1*k1)+4*k2*k3/(k1*k1)-8*k4/k1;
double p1=k3*k3-3*k2*k4+12*k1*k5;
double p2=2*k3*k3*k3-9*k2*k3*k4+27*k1*k4*k4+27*k2*k2*k5-72*k1*k3*k5;
// System.out.println("*************");
// System.out.println("k1="+k1);
// System.out.println("k2="+k2);
// System.out.println("k3="+k3);
// System.out.println("k4="+k4);
// System.out.println("k5="+k5);
Complex q1=new Complex(-4*p1*p1*p1+p2*p2).sqrt();
q1=Complex.plus(q1, new Complex(p2, 0));
q1=q1.sqrt3();
// System.out.println("q1="+q1.real()+" + "+q1.img()+" I");
Complex r1=Complex.div(new Complex(cub2*p1), Complex.mult(new Complex(3*k1), q1));
r1=Complex.plus(r1, Complex.div(q1, new Complex(3*cub2*k1)));
Complex sa=Complex.plus(new Complex(u2), r1);
sa=Complex.div(sa.sqrt(), 2);
Complex sb=Complex.minus(new Complex(u3), r1);
sb=Complex.minus(sb, Complex.div(new Complex(u4), Complex.mult(8, sa)));
sb=Complex.div(sb.sqrt(), 2);
Complex sc=Complex.minus(new Complex(u3), r1);
sc=Complex.plus(sc, Complex.div(new Complex(u4), Complex.mult(8, sa)));
sc=Complex.div(sc.sqrt(), 2);
Complex[] X=new Complex[4];
Complex cu1=new Complex(-u1);
X[0]=Complex.minus(cu1, sa);
X[0]=Complex.minus(X[0], sb);
X[1]=Complex.minus(cu1, sa);
X[1]=Complex.plus(X[1], sb);
X[2]=Complex.plus(cu1, sa);
X[2]=Complex.minus(X[2], sc);
X[3]=Complex.plus(cu1, sa);
X[3]=Complex.plus(X[3], sc);
// System.out.println("*************");
// System.out.println("x1 = "+X[0].real()+" + "+X[0].img()+" I");
// System.out.println("x2 = "+X[1].real()+" + "+X[1].img()+" I");
// System.out.println("x3 = "+X[2].real()+" + "+X[2].img()+" I");
// System.out.println("x4 = "+X[3].real()+" + "+X[3].img()+" I");
// Recherche des ordonnées des points d'intersection :
double A=c, B, C, AA=cc, BB, CC;
for (int i=0; i<4; i++) {
if (Math.abs(X[i].img())>1E-10) {
points.add(new CoordinatesXY());
} else {
B=b*X[i].real()+e;
C=a*X[i].real()*X[i].real()+d*X[i].real()+f;
BB=bb*X[i].real()+ee;
CC=aa*X[i].real()*X[i].real()+dd*X[i].real()+ff;
double denom=A*BB-B*AA;
if (Math.abs(denom)<1E-20) {
points.add(new CoordinatesXY());
} else {
double y=(C*AA-A*CC)/denom;//formula by Dominique Tournès
points.add(new CoordinatesXY(X[i].real(), y));
}
// System.out.println("*************");
// System.out.println("x["+i+"]="+X[i].real());
// System.out.println("y["+i+"]="+y);
// System.out.println("A*BB-B*AA="+(A*BB-B*AA));
}
}
// System.out.println("*************");
// for (int i=0;i<points.size();i++){
// CoordinatesXY coords=points.get(i);
// System.out.println("point "+i+" : "+coords.X+" "+coords.Y);
// }
return points;
}
@Override
public void validate() {
for (int i=0; i<P.length; i++) {
if (!P[i].valid()) {
Valid=false;
return;
}
}
Valid=true;
// Baue Koeffizientenmatrix auf (x^2,y^2,x,y,xy,1):
final double A[][]=new double[5][6];
for (int i=0; i<5; i++) {
final double x=P[i].getX(), y=P[i].getY();
A[i][0]=x*x;
A[i][1]=y*y;
A[i][2]=x;
A[i][3]=y;
A[i][4]=x*y;
A[i][5]=1;
double sum=0;
for (int j=0; j<6; j++) {
sum+=A[i][j]*A[i][j];
}
sum=Math.sqrt(sum);
for (int j=0; j<6; j++) {
A[i][j]/=sum;
}
}
// Gauflverfahren, um auf untere Dreiecksmatrix zu kommen
int r=0;
final int colindex[]=new int[6]; // Index der Stufe oder -1 (keine
// Stufe)
// Iteration ¸ber alle Spalten:
for (int c=0; c<6; c++) {
if (r>=5) // Schema schon fertig
{
colindex[c]=-1;
continue;
}
// Berechne Pivotelement mit spaltenweiser Maximumssuche
double max=Math.abs(A[r][c]);
int imax=r;
for (int i=r+1; i<5; i++) {
final double h=Math.abs(A[i][c]);
if (h>max) {
max=h;
imax=i;
}
}
if (max>1e-13) { // Vertausche Zeilen:
if (imax!=r) {
final double h[]=A[imax];
A[imax]=A[r];
A[r]=h;
}
// Mache restliche Spalte zu 0:
for (int i=r+1; i<5; i++) {
final double lambda=A[i][c]/A[r][c];
for (int j=c+1; j<6; j++) {
A[i][j]-=lambda*A[r][j];
}
}
colindex[c]=r;
r++;
} else {
colindex[c]=-1;
}
}
// Berechne die x-Werte:
X=new double[6];
for (int j=5; j>=0; j--) {
if (colindex[j]<0) {
X[j]=1;
} else {
double h=0;
final int i=colindex[j];
for (int k=j+1; k<6; k++) {
h+=A[i][k]*X[k];
}
X[j]=-h/A[i][j];
}
}
// Normalisiere
double sum=0;
for (int i=0; i<=5; i++) {
sum+=Math.abs(X[i]);
}
if (sum<1e-10) {
Valid=false;
}
for (int i=0; i<=5; i++) {
X[i]/=sum;
// Ce qui suit ressemble à un gag, pourtant il semble que l'epsilon au lieu de 0 en coeffs permet
// de surmonter les effets de bord dans des cas particuliers (ex. hyperbole equilatère/parabole)
// sans pour autant porter atteinte à la précision des coordonnées des points d'intersections
// qui restent fiables à 1e-12, soit la précision maximale affichée du logiciel :
X[i]=n(X[i]);
}
}
private static double n(double x) {
if (Math.abs(x)<1E-16) {
double sign=(Math.signum(x)<0)?-1:1;
return 1.0E-16*sign;
}
return x;
}
@Override
public void paint(final MyGraphics g, final ZirkelCanvas zc) {
if (!Valid||mustHide(zc)) {
return;
}
g.setColor(this);
// Draw the lower part of the quadrik (minus the root):
final double start=zc.minX();
double x=start;
final double end=zc.maxX();
final double h=zc.dx(zc.getOne());
boolean valid=false, ptext=false;
double c0=0, r0=0;
double ctext=20, rtext=20;
final PolygonDrawer pd=new PolygonDrawer(true,g, this);
// Draw the lower part of the quadric (plus the root):
while (x<=end) {
try {
final double y=computeLower(x);
final double c=zc.col(x), r=zc.row(y);
if (valid) {//en ajoutant r>0, la ligne verticale disparaissait; elle est réapparue!
pd.drawTo(c, r);
if (!ptext&&r0-r>c-c0&&zc.isInside(x, y)) {
ctext=c;
rtext=r;
ptext=true;
}
} else {
pd.startPolygon(c, r);
}
c0=c;
r0=r;
valid=true;
} catch (final RuntimeException e) {
valid=false;
}
x+=h;
}
pd.finishPolygon();
// Draw the upper part of the quadric (plus the root):
x=start-2*h;
valid=false;
while (x<=end+2*h) {
try {
final double y=computeUpper(x);
final double c=zc.col(x), r=zc.row(y);
if (valid) {
pd.drawTo(c, r);
// Try to find a position for the label:
if (!ptext&&r0-r>c-c0&&zc.isInside(x, y)) {
ctext=c;
rtext=r;
ptext=true;
}
} else // left edge of quadric, connect with lower part
{
try {
final double y1=computeLower(x);
if (x>=start-h&&x<=end+h) {
g.drawLine(c, zc.row(y1), c, r, this);
}
} catch (final RuntimeException e) {
}
pd.startPolygon(c, r);
}
c0=c;
r0=r;
valid=true;
} catch (final RuntimeException e) // no points in that range
{
if (valid) // we just left the right edge of the quadric
{
try {
final double y1=computeLower(x-h);
if (x-h>=start-h&&x-h<=end+h) {
g.drawLine(c0, zc.row(y1), c0, r0, this);
}
} catch (final RuntimeException ex) {
}
}
valid=false;
}
x+=h;
}
pd.finishPolygon();
final String s=getDisplayText();
if (!s.equals("")) {
g.setLabelColor(this);
setFont(g);
DisplaysText=true;
TX1=ctext+zc.col(XcOffset)-zc.col(0);
TY1=rtext+zc.row(YcOffset)-zc.row(0);
drawLabel(g, s);
}
}
static public final String Tags[]={"x^2", "y^2", "x", "y", "xy"};
// public String getDisplayValue() {
// String s="";
// for (int i=0; i<5; i++) {
// s=s+helpDisplayValue(i==0, -X[i], Tags[i]);
// }
// return s+"="+roundDisplay(X[5]);
// }
@Override
public String getDisplayValue() {
String s="";
s+="("+Global.getLocaleNumber(-X[0], "length");
s+="*";
s+=Tags[0]+")";
for (int i=1; i<5; i++) {
s+="+";
s+="("+Global.getLocaleNumber(-X[i], "length");
s+="*";
s+=Tags[i]+")";
// s=s+helpDisplayValue(i==0, -X[i], Tags[i]);
}
return s+"="+Global.getLocaleNumber(X[5], "length");
// return s+"="+roundDisplay(X[5]);
}
@Override
public String getEquation() {
return getDisplayValue();
}
@Override
public boolean nearto(final int cc, final int rr, final ZirkelCanvas zc) {
if (!displays(zc)) {
return false;
}
final int size=(int) zc.selectionSize();
final double start=zc.minX();
double x=start;
final double end=zc.maxX();
final double h=zc.dx(zc.getOne());
while (x<=end) {
try {
final double y=computeUpper(x);
final double c=zc.col(x), r=zc.row(y);
if (Math.abs(cc-c)<=size*3/2
&&Math.abs(rr-r)<=size*3/2) {
return true;
}
} catch (final Exception e) {
}
try {
final double y=computeLower(x);
final double c=zc.col(x), r=zc.row(y);
if (Math.abs(cc-c)<=size*3/2
&&Math.abs(rr-r)<=size*3/2) {
return true;
}
} catch (final Exception e) {
}
x+=h;
}
return false;
}
public double computeUpper(final double x) {
if (Math.abs(X[1])>1e-13) {
final double p=(X[3]+x*X[4])/X[1], q=(X[0]*x*x+X[2]
*x+X[5])
/X[1];
final double h=p*p/4-q;
if (h<0) {
throw new RuntimeException("");
}
return -p/2+Math.sqrt(h);
} else {
return -(X[0]*x*x+X[2]*x+X[5])/(X[3]+X[4]*x);
}
}
public double computeLower(final double x) {
if (Math.abs(X[1])>1e-13) {
final double p=(X[3]+x*X[4])/X[1], q=(X[0]*x*x+X[2]
*x+X[5])
/X[1];
final double h=p*p/4-q;
if (h<0) {
throw new RuntimeException("");
}
return -p/2-Math.sqrt(h);
} else {
throw new RuntimeException("");
}
}
@Override
public void printArgs(final XmlWriter xml) {
for (int i=0; i<P.length; i++) {
xml.printArg("point"+(i+1), P[i].getName());
}
}
@Override
public Enumeration secondaryParams() {
DL.reset();
for (final PointObject element : P) {
DL.add(element);
}
return DL.elements();
}
@Override
public Enumeration depending() {
DL.reset();
for (final PointObject element : P) {
// System.out.println(element.getName());
DL.add(element);
}
return DL.elements();
}
@Override
public void translate() {
for (int i=0; i<P.length; i++) {
P[i]=(PointObject) P[i].getTranslation();
}
}
@Override
public ConstructionObject copy(final double x, final double y) {
try {
final QuadricObject o=(QuadricObject) clone();
setTranslation(o);
o.P=new PointObject[P.length];
for (int i=0; i<P.length; i++) {
o.P[i]=P[i];
}
o.translateConditionals();
o.translate();
o.setName();
o.updateText();
o.setBreak(false);
// o.setTarget(false); Dibs
return o;
} catch (final Exception e) {
return null;
}
}
@Override
public boolean onlynearto(final int x, final int y, final ZirkelCanvas zc) {
return false;
}
@Override
public boolean equals(final ConstructionObject o) {
if (!(o instanceof QuadricObject)||!o.valid()) {
return false;
}
try {
for (int i=0; i<6; i++) {
if (!equals(X[i], ((QuadricObject) o).X[i])) {
return false;
}
}
} catch (final RuntimeException e) {
return false;
}
return true;
}
@Override
public boolean hasUnit() {
return false;
}
public void keepBaricentricCoords(final PointObject P) {
if (!P.isPointOn()) {
return;
}
if (P.BarycentricCoordsInitialzed) {
final PointObject AA=this.P[0];
final PointObject BB=this.P[1];
final PointObject CC=this.P[2];
final double xa=AA.getX(), ya=AA.getY();
final double xb=BB.getX(), yb=BB.getY();
final double xc=CC.getX(), yc=CC.getY();
final double xm=xa+P.Gx*(xb-xa)+P.Gy*(xc-xa);
final double ym=ya+P.Gx*(yb-ya)+P.Gy*(yc-ya);
P.move(xm, ym);
} else {
P.computeBarycentricCoords();
}
}
@Override
public int getDistance(final PointObject P) {
final double a=X[0], b=X[1], c=X[2], d=X[3], e=X[4], r=X[5];
final double xc=P.getX(), yc=P.getY();
if (Math.abs(a*xc*xc+b*yc*yc+c*xc+d*yc+e*xc*yc
+r)<1e-13) // close enough
{
return 0;
}
final double t[]=new double[5], s[]=new double[5];
// Coefficients for fourth order polynomial for lambda (Lagrange factor)
// Minimize (x-xc)^2+(y-yc)^2 with a*x^2+b*y^2+c*x+d*y+e*x*y+r=0
// Computed with Maple
t[0]=a*e*e*d*d-4*a*b*b*c*c+4*a*e*d*b
*c-4*b*a*a*d*d+b*c*c*e*e-c
*Math.pow(e, 3)*d+r*Math.pow(e, 4)-8*r*e*e*b
*a+16*r*b*b*a*a;
t[1]=8*b*b*c*c+8*a*a*d*d-8*e*d*b*c-8
*a*d*c*e+8*r*e*e*b+8*a*b*c*c+8*b
*a*d*d+8*r*e*e*a-32*r*b*b*a-32*r
*b*a*a;
t[2]=12*e*d*c+16*r*b*b-4*b*d*d-8*r*e*e
+4*e*e*d*yc+16*b*b*xc*c-16*b*c*c
-16*a*d*d-4*a*c*c+16*r*a*a+16*a*a
*d*yc+4*xc*e*e*c-8*e*d*b*xc-8*e*yc
*b*c-8*a*d*xc*e-8*a*yc*c*e+16*a*b
*b*xc*xc-4*a*e*e*yc*yc+16*b*a*a*yc
*yc-4*b*xc*xc*e*e+4*Math.pow(e, 3)*yc*xc
+64*r*b*a-16*a*b*xc*e*yc;
t[3]=-32*r*b+8*d*d+8*c*c+16*e*d*xc+8*e
*e*yc*yc+8*xc*xc*e*e-32*r*a-32*b*xc
*c+16*e*yc*c-32*a*d*yc-32*a*b*xc*xc
-32*b*a*yc*yc;
t[4]=16*b*yc*yc+16*d*yc+16*c*xc+16*xc*e*yc
+16*r+16*a*xc*xc;
final int k=Quartic.solve(t, s);
// System.out.println(k+"Solutions found.");
double dmin=1e30, xmin=xc, ymin=yc;
for (int i=0; i<k; i++) // Choose closest solution of Lagrange
// equation
{
final double l=s[i];
// Solve for x,y when lambda is known.
// Computed with Maple
final double px=-(-e*d+4*b*l*xc-2*e*l*yc-4
*l*l*xc+2*b*c-2*l*c)
/(-e*e+4*b*a-4*b*l-4*l*a+4*l*l);
final double py=-(2*a*d+4*a*l*yc-2*l*d-4*l
*l*yc-2*l*xc*e-c*e)
/(-e*e+4*b*a-4*b*l-4*l*a+4*l*l);
final double dist=(px-xc)*(px-xc)+(py-yc)*(py-yc);
if (dist<dmin) {
dmin=dist;
xmin=px;
ymin=py;
}
}
final double dd=Math.sqrt((P.getX()-xmin)*(P.getX()-xmin)
+(P.getY()-ymin)*(P.getY()-ymin));
return (int) Math.round(dd*Cn.getPixel());
}
public void project(final PointObject P) {
keepBaricentricCoords(P);
final double a=X[0], b=X[1], c=X[2], d=X[3], e=X[4], r=X[5];
final double xc=P.getX(), yc=P.getY();
if (Math.abs(a*xc*xc+b*yc*yc+c*xc+d*yc+e*xc*yc
+r)<1e-13) // close enough
{
return;
}
final double t[]=new double[5], s[]=new double[5];
// Coefficients for fourth order polynomial for lambda (Lagrange factor)
// Minimize (x-xc)^2+(y-yc)^2 with a*x^2+b*y^2+c*x+d*y+e*x*y+r=0
// Computed with Maple
t[0]=a*e*e*d*d-4*a*b*b*c*c+4*a*e*d*b
*c-4*b*a*a*d*d+b*c*c*e*e-c
*Math.pow(e, 3)*d+r*Math.pow(e, 4)-8*r*e*e*b
*a+16*r*b*b*a*a;
t[1]=8*b*b*c*c+8*a*a*d*d-8*e*d*b*c-8
*a*d*c*e+8*r*e*e*b+8*a*b*c*c+8*b
*a*d*d+8*r*e*e*a-32*r*b*b*a-32*r
*b*a*a;
t[2]=12*e*d*c+16*r*b*b-4*b*d*d-8*r*e*e
+4*e*e*d*yc+16*b*b*xc*c-16*b*c*c
-16*a*d*d-4*a*c*c+16*r*a*a+16*a*a
*d*yc+4*xc*e*e*c-8*e*d*b*xc-8*e*yc
*b*c-8*a*d*xc*e-8*a*yc*c*e+16*a*b
*b*xc*xc-4*a*e*e*yc*yc+16*b*a*a*yc
*yc-4*b*xc*xc*e*e+4*Math.pow(e, 3)*yc*xc
+64*r*b*a-16*a*b*xc*e*yc;
t[3]=-32*r*b+8*d*d+8*c*c+16*e*d*xc+8*e
*e*yc*yc+8*xc*xc*e*e-32*r*a-32*b*xc
*c+16*e*yc*c-32*a*d*yc-32*a*b*xc*xc
-32*b*a*yc*yc;
t[4]=16*b*yc*yc+16*d*yc+16*c*xc+16*xc*e*yc
+16*r+16*a*xc*xc;
final int k=Quartic.solve(t, s);
// System.out.println(k+"Solutions found.");
double dmin=1e30, xmin=xc, ymin=yc;
for (int i=0; i<k; i++) // Choose closest solution of Lagrange
// equation
{
final double l=s[i];
// Solve for x,y when lambda is known.
// Computed with Maple
final double px=-(-e*d+4*b*l*xc-2*e*l*yc-4
*l*l*xc+2*b*c-2*l*c)
/(-e*e+4*b*a-4*b*l-4*l*a+4*l*l);
final double py=-(2*a*d+4*a*l*yc-2*l*d-4*l
*l*yc-2*l*xc*e-c*e)
/(-e*e+4*b*a-4*b*l-4*l*a+4*l*l);
final double dist=(px-xc)*(px-xc)+(py-yc)*(py-yc);
if (dist<dmin) {
dmin=dist;
xmin=px;
ymin=py;
}
}
P.move(xmin, ymin);
}
public void project(final PointObject P, final double alpha) {
project(P);
}
public void dragTo(final double x, final double y) {
for (int i=0; i<5; i++) {
P[i].move(xd[i]+(x-x1), yd[i]+(y-y1));
}
}
@Override
public void move(final double x, final double y) {
}
public boolean moveable() {
for (int i=0; i<5; i++) {
if (!P[i].moveable()) {
return false;
}
}
return true;
}
double xd[], yd[], x1, y1;
public void startDrag(final double x, final double y) {
if (xd==null) {
xd=new double[5];
yd=new double[5];
}
for (int i=0; i<5; i++) {
xd[i]=P[i].getX();
yd[i]=P[i].getY();
}
x1=x;
y1=y;
}
public double getOldX() {
return 0;
}
public double getOldY() {
return 0;
}
@Override
public void snap(final ZirkelCanvas zc) {
if (moveable()) {
for (int i=0; i<5; i++) {
P[i].snap(zc);
}
}
}
public boolean canInteresectWith(final ConstructionObject o) {
return true;
}
public void repulse(final PointObject P) {
project(P);
}
public PointObject[] getP() {
return P;
}
}

View file

@ -0,0 +1,296 @@
/*
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: LineCircleIntersectionObject.java
import java.util.ArrayList;
import java.util.Collections;
import rene.util.xml.XmlWriter;
import rene.zirkel.construction.Construction;
import rene.zirkel.structures.Coordinates4;
import rene.zirkel.structures.CoordinatesXY;
public class QuadricQuadricIntersectionObject extends IntersectionObject {
private int Rank; //numéro de l'intersection, à savoir 0,1,2 ou 3
public QuadricQuadricIntersectionObject(final Construction c,
final QuadricObject P1, final QuadricObject P2,
final int rank) {
super(c, P1, P2);
Rank=rank;
validate();
}
// public void updateCircleDep ()
// { ((QuadricObject)P2).addDep(this);
// ((PrimitiveLineObject)P1).addDep(this);
// }
@Override
public void validate() {
final boolean oldvalid=Valid;
if (!P1.valid()||!P2.valid()) {
Valid=false;
} else {
Valid=true;
}
if (!Valid) {
return;
}
final ArrayList<CoordinatesXY> c=QuadricObject.intersect((QuadricObject) P1, (QuadricObject) P2);
Collections.sort(c);
if (Double.isNaN(c.get(Rank).X)) {
if (oldvalid&&getConstruction().shouldSwitch()) {
doSwitch();
if (!getConstruction().noteSwitch()) {
Switched=false;
}
}
;
Valid=false;
return;
}
setXY(c.get(Rank).X, c.get(Rank).Y);
if (((QuadricObject) P1).getP()[0].is3D()||((QuadricObject) P1).getP()[1].is3D()||((QuadricObject) P1).getP()[2].is3D()||((QuadricObject) P1).getP()[3].is3D()||((QuadricObject) P1).getP()[4].is3D()||
((QuadricObject) P2).getP()[0].is3D()||((QuadricObject) P2).getP()[1].is3D()||((QuadricObject) P2).getP()[2].is3D()||((QuadricObject) P2).getP()[3].is3D()||((QuadricObject) P2).getP()[4].is3D()) {
try {
double x0=((QuadricObject) P1).getP()[0].getX3D();
double y0=((QuadricObject) P1).getP()[0].getY3D();
double z0=((QuadricObject) P1).getP()[0].getZ3D();
double x1=((QuadricObject) P1).getP()[1].getX3D();
double y1=((QuadricObject) P1).getP()[1].getY3D();
double z1=((QuadricObject) P1).getP()[1].getZ3D();
double x2=((QuadricObject) P1).getP()[2].getX3D();
double y2=((QuadricObject) P1).getP()[2].getY3D();
double z2=((QuadricObject) P1).getP()[2].getZ3D();
double x_O=getConstruction().find("O").getX();
double x_X=getConstruction().find("X").getX();
double x_Y=getConstruction().find("Y").getX();
double x_Z=getConstruction().find("Z").getX();
double y_O=getConstruction().find("O").getY();
double y_X=getConstruction().find("X").getY();
double y_Y=getConstruction().find("Y").getY();
double y_Z=getConstruction().find("Z").getY();
double coeffa=(x1-x0)*(x_X-x_O)+(y1-y0)*(x_Y-x_O)+(z1-z0)*(x_Z-x_O);
double coeffb=(x2-x0)*(x_X-x_O)+(y2-y0)*(x_Y-x_O)+(z2-z0)*(x_Z-x_O);
double coeffc=(x1-x0)*(y_X-y_O)+(y1-y0)*(y_Y-y_O)+(z1-z0)*(y_Z-y_O);
double coeffd=(x2-x0)*(y_X-y_O)+(y2-y0)*(y_Y-y_O)+(z2-z0)*(y_Z-y_O);
double coeffe=getX()-x_O-x0*(x_X-x_O)-y0*(x_Y-x_O)-z0*(x_Z-x_O);
double coefff=getY()-y_O-x0*(y_X-y_O)-y0*(y_Y-y_O)-z0*(y_Z-y_O);
double alpha1=(coeffe*coeffd-coefff*coeffb)/(coeffa*coeffd-coeffb*coeffc);
double beta1=(coeffa*coefff-coeffc*coeffe)/(coeffa*coeffd-coeffb*coeffc);
final double xM=x0+alpha1*(x1-x0)+beta1*(x2-x0);
final double yM=y0+alpha1*(y1-y0)+beta1*(y2-y0);
final double zM=z0+alpha1*(z1-z0)+beta1*(z2-z0);
setX3D(xM);
setY3D(yM);
setZ3D(zM);
setIs3D(true);
} catch (final Exception eBary) {
}
// si les intersections n'existent pas en 3D, on les rendra superhidden
try { // Dibs intersection 3D de cercles
double a1=((QuadricObject) P1).getP()[0].getX3D();
double b1=((QuadricObject) P1).getP()[0].getY3D();
double c1=((QuadricObject) P1).getP()[0].getZ3D();
double a2=((QuadricObject) P1).getP()[1].getX3D();
double b2=((QuadricObject) P1).getP()[1].getY3D();
double c2=((QuadricObject) P1).getP()[1].getZ3D();
double a3=((QuadricObject) P1).getP()[2].getX3D();
double b3=((QuadricObject) P1).getP()[2].getY3D();
double c3=((QuadricObject) P1).getP()[2].getZ3D();
double a1b=((QuadricObject) P2).getP()[0].getX3D();
double b1b=((QuadricObject) P2).getP()[0].getY3D();
double c1b=((QuadricObject) P2).getP()[0].getZ3D();
double a2b=((QuadricObject) P2).getP()[1].getX3D();
double b2b=((QuadricObject) P2).getP()[1].getY3D();
double c2b=((QuadricObject) P2).getP()[1].getZ3D();
double a3b=((QuadricObject) P2).getP()[2].getX3D();
double b3b=((QuadricObject) P2).getP()[2].getY3D();
double c3b=((QuadricObject) P2).getP()[2].getZ3D();
double a4=(a1+a2)/2, b4=(b1+b2)/2, c4=(c1+c2)/2;
double a4b=(a1b+a2b)/2, b4b=(b1b+b2b)/2, c4b=(c1b+c2b)/2;
double a5=(a1+a3)/2, b5=(b1+b3)/2, c5=(c1+c3)/2;
double a5b=(a1b+a3b)/2, b5b=(b1b+b3b)/2, c5b=(c1b+c3b)/2;
double a6=a2-a1, b6=b2-b1, c6=c2-c1;
double a6b=a2b-a1b, b6b=b2b-b1b, c6b=c2b-c1b;
double a7=a3-a1, b7=b3-b1, c7=c3-c1;
double a7b=a3b-a1b, b7b=b3b-b1b, c7b=c3b-c1b;
double a8=b6*c7-c6*b7, b8=c6*a7-a6*c7, c8=a6*b7-b6*a7;
double a8b=b6b*c7b-c6b*b7b, b8b=c6b*a7b-a6b*c7b, c8b=a6b*b7b-b6b*a7b;
double a9=b8*c6-c8*b6, b9=c8*a6-a8*c6, c9=a8*b6-b8*a6;
double a9b=b8b*c6b-c8b*b6b, b9b=c8b*a6b-a8b*c6b, c9b=a8b*b6b-b8b*a6b;
double a10=b7*c8-c7*b8, b10=c7*a8-a7*c8, c10=a7*b8-b7*a8;
double a10b=b7b*c8b-c7b*b8b, b10b=c7b*a8b-a7b*c8b, c10b=a7b*b8b-b7b*a8b;
double a11=a5-a4, b11=b5-b4, c11=c5-c4;
double a11b=a5b-a4b, b11b=b5b-b4b, c11b=c5b-c4b;
double det1=b9*a10-a9*b10;
double det1b=b9b*a10b-a9b*b10b;
double det2=a10*b11-b10*a11;
double det2b=a10b*b11b-b10b*a11b;
double a12=a4+det2/det1*a9, b12=b4+det2/det1*b9, c12=c4+det2/det1*c9; // centre
double a12b=a4b+det2b/det1b*a9b, b12b=b4b+det2b/det1b*b9b, c12b=c4b+det2b/det1b*c9b;
double rcarre=(a12-a1)*(a12-a1)+(b12-b1)*(b12-b1)+(c12-c1)*(c12-c1); //rayons^2
double rbcarre=(a12b-a1)*(a12b-a1)+(b12b-b1)*(b12b-b1)+(c12b-c1)*(c12b-c1);
double n8=Math.sqrt(a8*a8+b8*b8+c8*c8);
double n8b=Math.sqrt(a8b*a8b+b8b*b8b+c8b*c8b);
a8 /=n8; b8 /= n8; c8 /= n8; // on norme P8
a8b /=n8b; b8b /= n8b; c8b /= n8b;
double a13=b8*c8b-c8*b8b, b13=c8*a8b-a8*c8b, c13=a8*b8b-b8*a8b; // pvect de pvects
double n13carre=a13*a13+b13*b13+c13*c13;
if (n13carre<1e-9) { // coplanaires
double dcentrescarre=(a12b-a12)*(a12b-a12)+(b12b-b12)*(b12b-b12)+(c12b-c12)*(c12b-c12);
double abs=(dcentrescarre+rcarre-rbcarre)/(2*Math.sqrt(dcentrescarre));
if (rcarre-abs*abs<=0) {
setSuperHidden(true);
}
else {
double ord=Math.sqrt(rcarre-abs*abs);
double a14=a12b-a12, b14=b12b-b12, c14=c12b-c12;
double a15=b8*c14-c8*b14, b15=c8*a14-a8*c14, c15=a8*b14-b8*a14;
double n14=Math.sqrt(a14*a14+b14*b14+c14*c14);
double n15=Math.sqrt(a15*a15+b15*b15+c15*c15);
a14/=n14; b14/=n14; c14/=n14;
a15/=n15; b15/=n15; c15/=n15;
double a16=a12+abs*a14+ord*a15, b16=b12+abs*b14+ord*b15, c16=c12+abs*c14+ord*c15;
double a17=a12+abs*a14-ord*a15, b17=b12+abs*b14-ord*b15, c17=c12+abs*c14-ord*c15;
final double xO=getConstruction().find("O").getX();
final double yO=getConstruction().find("O").getY();
final double deltaxX=getConstruction().find("X").getX()-xO;
final double deltaxY=getConstruction().find("Y").getX()-xO;
final double deltaxZ=getConstruction().find("Z").getX()-xO;
final double deltayX=getConstruction().find("X").getY()-yO;
final double deltayY=getConstruction().find("Y").getY()-yO;
final double deltayZ=getConstruction().find("Z").getY()-yO;
double posx=xO+a16*deltaxX+b16*deltaxY+c16*deltaxZ; // coordonnées 2D
double posy=yO+a16*deltayX+b16*deltayY+c16*deltayZ;
double erreurcarre=(c.get(Rank).X-posx)*(c.get(Rank).X-posx)+(c.get(Rank).Y-posy)*(c.get(Rank).Y-posy);
if (erreurcarre<1e-8) {
setX3D(a16);
setY3D(b16);
setZ3D(c16);
}
posx=xO+a17*deltaxX+b17*deltaxY+c17*deltaxZ; // coordonnées 2D 2eme sol
posy=yO+a17*deltayX+b17*deltayY+c17*deltayZ;
erreurcarre=(c.get(Rank).X-posx)*(c.get(Rank).X-posx)+(c.get(Rank).Y-posy)*(c.get(Rank).Y-posy);
if (erreurcarre<1e-8) {
setX3D(a17);
setY3D(b17);
setZ3D(c17);
}
}
}
else { // pas coplanaires
boolean isGood=false;
double a14=a1b-a1, b14=b1b-b1, c14=c1b-c1;
double x1=(a14*(b7*c6b-b6b*c7)+a6b*(b14*c7-b7*c14)+a7*(b6b*c14-b14*c6b))/(a6*(b7*c6b-b6b*c7)+a6b*(b6*c7-b7*c6)+a7*(b6b*c6-b6*c6b));
double x2=(a14*(b6b*c6-b6*c6b)+a6*(b14*c6b-b6b*c14)+a6b*(b6*c14-b14*c6))/(a6*(b7*c6b-b6b*c7)+a6b*(b6*c7-b7*c6)+a7*(b6b*c6-b6*c6b));
double y1=(a6b*(b7b*c7-b7*c7b)+a7*(b6b*c7b-b7b*c6b)+a7b*(b7*c6b-b6b*c7)+a14*(b7*c6b-b6b*c7)+a6b*(b14*c7-b7*c14)+a7*(b6b*c14-b14*c6b))/(a6*(b7*c6b-b6b*c7)+a6b*(b6*c7-b7*c6)+a7*(b6b*c6-b6*c6b));
double y2=(a6*(b7b*c6b-b6b*c7b)+a6b*(b6*c7b-b7b*c6)+a7b*(b6b*c6-b6*c6b)+a14*(b6b*c6-b6*c6b)+a6*(b14*c6b-b6b*c14)+a6b*(b6*c14-b14*c6))/(a6*(b7*c6b-b6b*c7)+a6b*(b6*c7-b7*c6)+a7*(b6b*c6-b6*c6b));
double a15=a1+x1*a6+x2*a7, b15=b1+x1*b6+x2*b7, c15=c1+x1*c6+x2*c7;
double a16=a1+y1*a6+y2*a7, b16=b1+y1*b6+y2*b7, c16=c1+y1*c6+y2*c7;
double a17=a16-a15, b17=b16-b15, c17=c16-c15;
double a18=a15-a12, b18=b15-b12, c18=c15-c2;
try {
double x3=-(Math.sqrt((c17*c17+b17*b17+a17*a17)*rcarre+(-b17*b17-a17*a17)*c18*c18+(2*b17*b18+2*a17*a18)*c17*c18+(-b18*b18-a18*a18)*c17*c17-a17*a17*b18*b18+2*a17*a18*b17*b18-a18*a18*b17*b17)+c17*c18+b17*b18+a17*a18)/(c17*c17+b17*b17+a17*a17);
double x4=(Math.sqrt((c17*c17+b17*b17+a17*a17)*rcarre+(-b17*b17-a17*a17)*c18*c18+(2*b17*b18+2*a17*a18)*c17*c18+(-b18*b18-a18*a18)*c17*c17-a17*a17*b18*b18+2*a17*a18*b17*b18-a18*a18*b17*b17)-c17*c18-b17*b18-a17*a18)/(c17*c17+b17*b17+a17*a17);
double a19=a15+x3*a17, b19=b15+x3*b17, c19=c15+x3*c17; // soluces potentielles
double a20=a15+x4*a17, b20=b15+x4*b17, c20=c15+x4*c17;
double db19carre=(a19-a12b)*(a19-a12b)+(b19-b12b)*(b19-b12b)+(c19-c12b)*(c19-c12b);
double db20carre=(a20-a12b)*(a20-a12b)+(b20-b12b)*(b20-b12b)+(c20-c12b)*(c20-c12b);
if (Math.abs(db19carre-rbcarre)<1e-10) { // OK pour P19
final double xO=getConstruction().find("O").getX();
final double yO=getConstruction().find("O").getY();
final double deltaxX=getConstruction().find("X").getX()-xO;
final double deltaxY=getConstruction().find("Y").getX()-xO;
final double deltaxZ=getConstruction().find("Z").getX()-xO;
final double deltayX=getConstruction().find("X").getY()-yO;
final double deltayY=getConstruction().find("Y").getY()-yO;
final double deltayZ=getConstruction().find("Z").getY()-yO;
double posx=xO+a19*deltaxX+b19*deltaxY+c19*deltaxZ; // coordonnées 2D
double posy=yO+a19*deltayX+b19*deltayY+c19*deltayZ;
double erreurcarre=(c.get(Rank).X-posx)*(c.get(Rank).X-posx)+(c.get(Rank).Y-posy)*(c.get(Rank).Y-posy);
if (erreurcarre<1e-8) {
isGood=true;
setX3D(a19);
setY3D(b19);
setZ3D(c19);
}
else if (Math.abs(db20carre-rbcarre)<1e-8) {
posx=xO+a20*deltaxX+b20*deltaxY+c20*deltaxZ; // coordonnées 2D
posy=yO+a20*deltayX+b20*deltayY+c20*deltayZ;
erreurcarre=(c.get(Rank).X-posx)*(c.get(Rank).X-posx)+(c.get(Rank).Y-posy)*(c.get(Rank).Y-posy);
if (erreurcarre<1e-8) {
isGood=true;
setX3D(a20);
setY3D(b20);
setZ3D(c20);
}
}
}
else if (Math.abs(db20carre-rbcarre)<1e-8) { // OK pour P20
final double xO=getConstruction().find("O").getX();
final double yO=getConstruction().find("O").getY();
final double deltaxX=getConstruction().find("X").getX()-xO;
final double deltaxY=getConstruction().find("Y").getX()-xO;
final double deltaxZ=getConstruction().find("Z").getX()-xO;
final double deltayX=getConstruction().find("X").getY()-yO;
final double deltayY=getConstruction().find("Y").getY()-yO;
final double deltayZ=getConstruction().find("Z").getY()-yO;
double posx=xO+a20*deltaxX+b20*deltaxY+c20*deltaxZ; // coordonnées 2D
double posy=yO+a20*deltayX+b20*deltayY+c20*deltayZ;
double erreurcarre=(c.get(Rank).X-posx)*(c.get(Rank).X-posx)+(c.get(Rank).Y-posy)*(c.get(Rank).Y-posy);
if (erreurcarre<1e-10) {
isGood=true;
setX3D(a20);
setY3D(b20);
setZ3D(c20);
}
}
}
catch (final Exception ex) {
setSuperHidden(true);
}
if (!isGood) setSuperHidden(true);
}
} catch (final Exception ex) {
}
}
}
@Override
public void printArgs(final XmlWriter xml) {
super.printArgs(xml);
xml.printArg("which", ""+Rank);
}
@Override
public boolean isSwitchable() {
return false;
}
@Override
public boolean canAlternate() {
return true;
}
}

View file

@ -0,0 +1,305 @@
/*
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: SegmentObject.java
import rene.gui.Global;
import rene.util.xml.XmlWriter;
import rene.gui.Global;
import rene.zirkel.ZirkelCanvas;
import rene.zirkel.construction.Construction;
import rene.zirkel.construction.Count;
import rene.zirkel.graphics.MyGraphics;
import rene.zirkel.graphics.MainGraphics;
import rene.zirkel.structures.Coordinates;
public class RayObject extends TwoPointLineObject {
static Count N = new Count();
public RayObject(final Construction c, final PointObject p1,
final PointObject p2) {
super(c, p1, p2);
validate();
updateText();
}
@Override
public String getTag() {
return "Ray";
}
@Override
public int getN() {
return N.next();
}
@Override
public void setDefaults() {
setShowName(Global.getParameter("options.line.shownames", false));
setShowValue(Global.getParameter("options.line.showvalues", false));
setColor(Global.getParameter("options.line.color", 0));
setColorType(Global.getParameter("options.line.colortype", 0));
setHidden(Cn.Hidden);
setObtuse(Cn.Obtuse);
setSolid(Cn.Solid);
setLarge(Global.getParameter("options.line.large", false));
setBold(Global.getParameter("options.line.bold", false));
}
@Override
public void setTargetDefaults() {
setShowName(Global.getParameter("options.line.shownames", false));
setShowValue(Global.getParameter("options.line.showvalues", false));
setColor(Global.getParameter("options.line.color", 0));
setColorType(Global.getParameter("options.line.colortype", 0));
setLarge(Global.getParameter("options.line.large", false));
setBold(Global.getParameter("options.line.bold", false));
}
@Override
public void updateText() {
setText(text2(Global.name("text.ray"), P1.getName(), P2.getName()));
}
@Override
public void validate() {
// if ((P1==null)) {
// System.out.println(this.getName()+" : "+P2.getName());
// }
// if ((P2==null)) {
// System.out.println(this.getName()+" : "+P1.getName());
// }
if (!P1.valid() || !P2.valid()) {
Valid = false;
return;
} else {
Valid = true;
X1 = P1.getX();
Y1 = P1.getY();
X2 = P2.getX();
Y2 = P2.getY();
// compute normalized vector in the direction of the line:
DX = X2 - X1;
DY = Y2 - Y1;
R = Math.sqrt(DX * DX + DY * DY);
if (R < 1e-10) {
Valid = false;
return;
}
DX /= R;
DY /= R;
}
}
@Override
public void paint(final MyGraphics g, final ZirkelCanvas zc) {
if (!Valid || mustHide(zc))
return;
// compute middle of the screen:
final double xm = (zc.minX() + zc.maxX()) / 2, ym = (zc.minY() + zc
.maxY()) / 2;
// compute distance from middle to line:
final double d = (xm - X1) * DY - (ym - Y1) * DX;
// compute point with minimal distance
final double x = xm - d * DY, y = ym + d * DX;
// compute size of the screen
final double a = Math.max(zc.maxX() - zc.minX(), zc.maxY() - zc.minY());
if (Math.abs(d) > a)
return;
// compute distance from closest point to source
final double b = (x - X1) * DX + (y - Y1) * DY;
// compute the two visible endpoints
k1 = b - a;
k2 = b + a;
k12valid = true;
if (k1 < 0)
k1 = 0;
if (k1 >= k2)
return;
if (Partial && !zc.showHidden() && Dep != null) {
final double dd = (zc.maxX() - zc.minX()) / 20;
double dmin = -dd, dmax = R + dd;
for (int i = 0; i < NDep; i++) {
if (!Dep[i].valid() || Dep[i].mustHide(zc))
continue;
final double s = project(Dep[i].getX(), Dep[i].getY());
if (s - dd < dmin)
dmin = s - dd;
else if (s + dd > dmax)
dmax = s + dd;
}
if (k1 < dmin)
k1 = dmin;
if (k2 > dmax)
k2 = dmax;
}
final double c1 = zc.col(X1 + k1 * DX), c2 = zc.col(X1 + k2 * DX), r1 = zc
.row(Y1 + k1 * DY), r2 = zc.row(Y1 + k2 * DY);
// paint:
if (isStrongSelected() && g instanceof MainGraphics) {
((MainGraphics) g).drawMarkerLine(c1, r1, c2, r2);
}
g.setColor(this);
if (visible(zc)) {
if (tracked())
zc.UniversalTrack.drawTrackLine(this, c1, r1, c2, r2);
g.drawLine(c1, r1, c2, r2, this);
}
final String s = getDisplayText();
if (!s.equals("")) {
g.setLabelColor(this);
DisplaysText = true;
double c = -b + a / 5;
if (c < -a / 5)
c = -a / 5;
else if (c > a / 5)
c = a / 5;
if (c < -b + a / 10)
c = -b + a / 10;
if (KeepClose) {
final double side = (YcOffset < 0) ? 1 : -1;
drawLabel(g, s, zc, X1 + XcOffset * (X2 - X1), Y1 + XcOffset
* (Y2 - Y1), side * DX, side * DY, 0, 0);
} else
drawLabel(g, s, zc, x + c * DX, y + c * DY, DX, DY, XcOffset,
YcOffset);
}
}
@Override
public boolean canKeepClose() {
return true;
}
@Override
public void setKeepClose(final double x, final double y) {
KeepClose = true;
XcOffset = (x - X1) / R * DX + (y - Y1) / R * DY;
YcOffset = (x - X1) / R * DY - (y - Y1) / R * DX;
}
@Override
public String getDisplayValue() {
return Global.getLocaleNumber(R, "lengths");
}
//
// public String getDisplayValue ()
// { return ""+round(R,ZirkelCanvas.LengthsFactor);
// }
@Override
public boolean nearto(final int c, final int r, final ZirkelCanvas zc) {
if (!displays(zc))
return false;
// compute point at c,r
final double x = zc.x(c), y = zc.y(r);
// compute distance from line
double d = (x - X1) * DY - (y - Y1) * DX;
// compute offset
final double o = (x - X1) * DX + (y - Y1) * DY, o1 = (X2 - X1) * DX
+ (Y2 - Y1) * DY;
if (o1 > 0) {
if (o < 0)
d = Math.sqrt((x - X1) * (x - X1) + (y - Y1) * (y - Y1));
} else {
if (o > 0)
d = Math.sqrt((x - X1) * (x - X1) + (y - Y1) * (y - Y1));
}
// test, if on visible part
final double s = project(x, y);
if (s < k1 || s > k2)
return false;
// scale in screen coordinates
Value = Math.abs(zc.col(zc.minX() + d) - zc.col(zc.minX()));
return Value < zc.selectionSize() * 2;
}
@Override
public void printArgs(final XmlWriter xml) {
xml.printArg("from", P1.getName());
xml.printArg("to", P2.getName());
super.printArgs(xml);
}
@Override
public boolean contains(final double x, final double y) {
final double a = (x - X1) * DX + (y - Y1) * DY;
if (a < 1e-9)
return false;
return true;
}
@Override
public double project(final double x, final double y) {
final double h = super.project(x, y);
if (h < 0)
return 0;
return h;
}
@Override
public boolean equals(final ConstructionObject o) {
if (!(o instanceof RayObject) || !o.valid())
return false;
final RayObject l = (RayObject) o;
return equals(X1, l.X1) && equals(Y1, l.Y1) && equals(DX, l.DX)
&& equals(DY, l.DY);
}
public static Coordinates intersect(final PrimitiveLineObject l1,
final PrimitiveLineObject l2)
// compute the intersection coordinates of two lines
{
final double det = -l1.DX * l2.DY + l1.DY * l2.DX;
if (Math.abs(det) < 1e-10)
return null;
final double a = (-(l2.X1 - l1.X1) * l2.DY + (l2.Y1 - l1.Y1) * l2.DX)
/ det;
return new Coordinates(l1.X1 + a * l1.DX, l1.Y1 + a * l1.DY);
}
public static Coordinates intersect(final PrimitiveLineObject l,
final PrimitiveCircleObject c)
// compute the intersection coordinates of a line with a circle
{
double x = c.getX(), y = c.getY();
final double r = c.getR();
final double d = (x - l.X1) * l.DY - (y - l.Y1) * l.DX;
if (Math.abs(d) > r + 1e-10)
return null;
x -= d * l.DY;
y += d * l.DX;
double h = r * r - d * d;
if (h > 0)
h = Math.sqrt(h);
else
h = 0;
return new Coordinates(x + h * l.DX, y + h * l.DY, x - h * l.DX, y - h
* l.DY);
}
}

View file

@ -0,0 +1,747 @@
/*
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: SegmentObject.java
import java.awt.Rectangle;
import java.util.Enumeration;
import rene.gui.Global;
import rene.util.xml.XmlWriter;
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.MainGraphics;
import rene.zirkel.graphics.MyGraphics;
/**
* @author Rene Class for segments, derived from LineObject, TwoPointLineObject.
* Segments override various methods from lines. They have a length.
* Also the length can be fixed.
*/
public class SegmentObject extends TwoPointLineObject {
static Count N = new Count();
protected boolean Is3D; //Dibs : 3D ?
protected double X3D1, Y3D1, Z3D1, X3D2, Y3D2, Z3D2, DX3D, DY3D, DZ3D; //Dibs
protected boolean Fixed = false; // fixed length?
protected boolean Fixed3D = false; // fixed length?
Expression E; // expression to fix the length.
Expression E3D;
boolean ExpressionFailed; // invalid expression?
public boolean Arrow; // draw as arrow.
int code_symbol = 0;
public SegmentObject(final Construction c, final PointObject p1,
final PointObject p2) {
super(c, p1, p2);
if (p1.is3D()&&p2.is3D()) Is3D=true;
Arrow = false;
validate();
updateText();
Unit = Global.getParameter("unit.length", "");
}
@Override
public String getCDPDisplayValue(){
return Global.getLocaleNumber(R, "lengths");
}
@Override
public String getTag() {
return "Segment";
}
@Override
public int getN() {
return N.next();
}
// public void setDefaults ()
// { Arrow=Cn.Vectors;
// super.setDefaults();
// }
@Override
public void setDefaults() {
//Arrow = Cn.Vectors; //plus nécessaire
setShowName(Global.getParameter("options.segment.shownames", false));
setShowValue(Global.getParameter("options.segment.showvalues", false));
setColor(Global.getParameter("options.segment.color", 0), Global
.getParameter("options.segment.pcolor", (ExpressionColor) null, this));
setColorType(Global.getParameter("options.segment.colortype", 0));
setHidden(Cn.Hidden);
setObtuse(Cn.Obtuse);
setSolid(Cn.Solid);
setLarge(Global.getParameter("options.segment.large", false));
setBold(Global.getParameter("options.segment.bold", false));
}
@Override
public void setTargetDefaults() {
setShowName(Global.getParameter("options.segment.shownames", false));
setShowValue(Global.getParameter("options.segment.showvalues", false));
setColor(Global.getParameter("options.segment.color", 0), Global
.getParameter("options.segment.pcolor", (ExpressionColor) null, this));
setColorType(Global.getParameter("options.segment.colortype", 0));
setLarge(Global.getParameter("options.segment.large", false));
setBold(Global.getParameter("options.segment.bold", false));
}
@Override
public void updateText() {
if (!Fixed) {
setText(text2(Global.name("text.segment"), P1.getName(), P2
.getName()));
} else {
if (E == null) {
setText(text3(Global.name("text.segment.fixed"), P1.getName(),
P2.getName(), "" + round(R)));
} else {
setText(text3(Global.name("text.segment.fixed"), P1.getName(),
P2.getName(), "\"" + E.toString() + "\""));
}
}
}
@Override
public void validate() {
ExpressionFailed = false;
if (!P1.valid() || !P2.valid()) {
Valid = false;
return;
} else {
Valid = true;
X1 = P1.getX();
Y1 = P1.getY();
X2 = P2.getX();
Y2 = P2.getY();
// compute normalized vector in the direction of the line:
DX = X2 - X1;
DY = Y2 - Y1;
R = Math.sqrt(DX * DX + DY * DY);
// System.out.println("X1="+X1+" Y1="+Y1+" | X2="+X2+" Y2="+Y2+" R="+R);
if (P1.is3D()&&P2.is3D()) Is3D=true; // Dibs last updated
if (Is3D) { //Dibs
X3D1 = P1.getX3D();
Y3D1 = P1.getY3D();
Z3D1 = P1.getZ3D();
X3D2 = P2.getX3D();
Y3D2 = P2.getY3D();
Z3D2 = P2.getZ3D();
DX3D = X3D2-X3D1;
DY3D = Y3D2-Y3D1;
DZ3D = Z3D2-Z3D1;
R3D = Math.sqrt(DX3D * DX3D + DY3D * DY3D + DZ3D * DZ3D);
}
// if fixed, move the moveable endpoint.
if (Fixed && E != null&&!is3D()) {
try {
final double FixedR = E.getValue();
// System.out.println(R+" "+FixedR);
if (FixedR < 1e-8) {
R = 0;
ExpressionFailed = true;
Valid = false;
return;
}
boolean movefirst = P1.moveableBy(this), movesecond = P2
.moveableBy(this);
if (P2.getBound() != null) {
final ConstructionObject bound = P2.getBound();
if (bound instanceof RayObject) {
if (((RayObject) bound).getP1() == P1) {
movesecond = true;
}
}
} else if (P1.getBound() != null) {
final ConstructionObject bound = P1.getBound();
if (bound instanceof RayObject) {
if (((RayObject) bound).getP1() == P2) {
movefirst = true;
movesecond = false;
}
}
}
if (movesecond) {
if (R < 1e-10) {
P2.move(X1 + FixedR, Y1);
} else {
P2.move(X1 + FixedR * DX / R, Y1 + FixedR * DY / R);
}
P1.setUseAlpha(false);
// System.out.println("Move "+P2.getName());
} else if (movefirst) {
if (R < 1e-10) {
P1.move(X2 - FixedR, Y2);
} else {
P1.move(X2 - FixedR * DX / R, Y2 - FixedR * DY / R);
}
P2.setUseAlpha(false);
// System.out.println("Move "+P1.getName());
} else {
Fixed = false; // no moveable endpoint!
}
if (Fixed) {
X1 = P1.getX();
Y1 = P1.getY();
X2 = P2.getX();
Y2 = P2.getY();
DX = X2 - X1;
DY = Y2 - Y1;
R = Math.sqrt(DX * DX + DY * DY);
P2.movedBy(this);
P1.movedBy(this);
}
} catch (final Exception e) {
ExpressionFailed = true;
Valid = false;
R = 0;
R3D=0;
return;
}
}
else if (Fixed3D && E3D != null) { // pour plus tard...
try {
final double FixedR3D = E3D.getValue();
if (FixedR3D < 1e-8) {
R3D = 0;
ExpressionFailed = true;
Valid = false;
return;
}
boolean movefirst = P1.moveableBy(this), movesecond = P2
.moveableBy(this);
if (P2.getBound() != null) {
final ConstructionObject bound = P2.getBound();
if (bound instanceof RayObject) {
if (((RayObject) bound).getP1() == P1) {
movesecond = true;
}
}
} else if (P1.getBound() != null) {
final ConstructionObject bound = P1.getBound();
if (bound instanceof RayObject) {
if (((RayObject) bound).getP1() == P2) {
movefirst = true;
movesecond = false;
}
}
}
if (movesecond) {
if (R3D < 1e-10) {
P2.move3D(X3D1 + FixedR3D, Y3D1, Z3D1);
} else {
P2.move3D(X3D1 + FixedR3D * DX3D / R3D, Y3D1 + FixedR3D * DY3D / R3D, Z3D1 + FixedR3D * DZ3D / R3D);
}
P1.setUseAlpha(false);
// System.out.println("Move "+P2.getName());
} else if (movefirst) {
if (R < 1e-10) {
P1.move3D(X3D2 - FixedR3D, Y3D2, Z3D2);
} else {
P1.move3D(X3D2 - FixedR3D * DX3D / R3D, Y3D2 - FixedR3D * DY3D / R3D, Z3D2 - FixedR3D * DZ3D / R3D);
}
P2.setUseAlpha(false);
// System.out.println("Move "+P1.getName());
} else {
Fixed3D = false; // no moveable endpoint!
}
if (Fixed3D) {
X3D1 = P1.getX3D();
Y3D1 = P1.getY3D();
Z3D1 = P1.getZ3D();
X3D2 = P2.getX3D();
Y3D2 = P2.getY3D();
Z3D2 = P2.getZ3D();
DX3D = X3D2-X3D1;
DY3D = Y3D2-Y3D1;
DZ3D = Z3D2-Z3D1;
R3D = Math.sqrt(DX3D * DX3D + DY3D * DY3D + DZ3D * DZ3D);
P2.movedBy(this);
P1.movedBy(this);
}
} catch (final Exception e) {
ExpressionFailed = true;
Valid = false;
R = 0;
R3D=0;
return;
}
}
// See of the length is too small.
if (R < 1e-10) {
R = 0;
DX = 1;
DY = 0;
} else {
DX /= R;
DY /= R;
}
if (R3D < 1e-10) {
R3D = 0;
DX3D = 1;
DY3D = 0;
DZ3D=0;
} else {
DX3D /= R3D;
DY3D /= R3D;
}
}
}
@Override
public void paint(final MyGraphics g, final ZirkelCanvas zc) {
if (!Valid || mustHide(zc)) {
return;
}
final double c1 = zc.col(X1), r1 = zc.row(Y1), c2 = zc.col(X2), r2 = zc
.row(Y2);
if (visible(zc)) {
if (isStrongSelected() && g instanceof MainGraphics) {
((MainGraphics) g).drawMarkerLine(c1, r1, c2, r2);
}
g.setColor(this);
if (tracked()) {
zc.UniversalTrack.drawTrackLine(this, c1, r1, c2, r2);
}
g.drawLine(c1, r1, c2, r2, this);
if (code_symbol > 0) {
// length of the tick mark :
final double rr = 7*Cn.getOne();
// distance between two marks :
final double dd = 3*Cn.getOne();
// oblique de la marque :
final double ob = 2*Cn.getOne();
final double cM = (c1 + c2) / 2, rM = (r1 + r2) / 2;
final double A = c2 - cM, B = r2 - rM;
final double sqrt2 = Math.sqrt(B * B + A * A);
final double xx1 = -(rr * B) / sqrt2 + cM - ob * A / sqrt2;
final double yy1 = (rr * A) / sqrt2 + rM - ob * B / sqrt2;
final double xx2 = (rr * B) / sqrt2 + cM + ob * A / sqrt2;
final double yy2 = -(rr * A) / sqrt2 + rM + ob * B / sqrt2;
final double xt = dd * A / sqrt2, yt = dd * B / sqrt2;
switch (code_symbol) {
case 1:
g.drawLine(xx1, yy1, xx2, yy2, this);
break;
case 2:
g.drawLine(xx1 - xt, yy1 - yt, xx2 - xt, yy2 - yt, this);
g.drawLine(xx1 + xt, yy1 + yt, xx2 + xt, yy2 + yt, this);
break;
case 3:
g.drawLine(xx1 - 2 * xt, yy1 - 2 * yt, xx2 - 2 * xt, yy2
- 2 * yt, this);
g.drawLine(xx1, yy1, xx2, yy2, this);
g.drawLine(xx1 + 2 * xt, yy1 + 2 * yt, xx2 + 2 * xt, yy2
+ 2 * yt, this);
break;
case 4:
g.drawLine(xx1 - 3 * xt, yy1 - 3 * yt, xx2 - 3 * xt, yy2
- 3 * yt, this);
g.drawLine(xx1 - xt, yy1 - yt, xx2 - xt, yy2 - yt, this);
g.drawLine(xx1 + xt, yy1 + yt, xx2 + xt, yy2 + yt, this);
g.drawLine(xx1 + 3 * xt, yy1 + 3 * yt, xx2 + 3 * xt, yy2
+ 3 * yt, this);
break;
case 5:
g.drawLine(xx1 - 2 * xt, yy1 - 2 * yt, xx2 + 2 * xt, yy2
+ 2 * yt, this);
g.drawLine(xx1 + 2 * xt, yy1 + 2 * yt, xx2 - 2 * xt, yy2
- 2 * yt, this);
break;
case 6:
g.drawCircle(cM, rM, 2 * dd, this);
break;
}
}
if (Arrow) // draw as arrow!
{
final double a = Math.PI * 0.9;
final double r = zc.dx(Cn.getOne()*Global.getParameter(
"arrowsize", 15)); // 10 pixel on the screen
final double[] cols = new double[3];
cols[0] = c2;
cols[1] = zc
.col(X2 + (DX * Math.cos(a) + DY * Math.sin(a)) * r);
cols[2] = zc.col(X2 + (DX * Math.cos(-a) + DY * Math.sin(-a))
* r);
final double[] rows = new double[3];
rows[0] = r2;
rows[1] = zc.row(Y2 + (-DX * Math.sin(a) + DY * Math.cos(a))
* r);
rows[2] = zc.row(Y2 + (-DX * Math.sin(-a) + DY * Math.cos(-a))
* r);
g.fillPolygon(cols, rows, 3, true, false, this);
}
}
final String s = getDisplayText();
if (!s.equals("")) {
g.setLabelColor(this);
setFont(g);
DisplaysText = true;
if (KeepClose) {
final double side = (YcOffset < 0) ? 1 : -1;
drawLabel(g, s, zc, X1 + XcOffset * (X2 - X1), Y1 + XcOffset
* (Y2 - Y1), side * DX, side * DY, 0, 0);
} else {
drawLabel(g, s, zc, (X1 + X2) / 2, (Y1 + Y2) / 2, DX, DY,
XcOffset, YcOffset);
}
}
}
@Override
public boolean canKeepClose() {
return true;
}
@Override
public void setKeepClose(final double x, final double y) {
KeepClose = true;
XcOffset = (x - X1) / R * DX + (y - Y1) / R * DY;
YcOffset = (x - X1) / R * DY - (y - Y1) / R * DX;
}
// public String getDisplayValue ()
// { return
// eric.JGlobals.fixDecimal(""+round(R,ZirkelCanvas.LengthsFactor));
// }
@Override
public String getDisplayValue() {
// return ""+round(R,ZirkelCanvas.LengthsFactor);
if (!Is3D) return Global.getLocaleNumber(R, "lengths");
else return Global.getLocaleNumber(R3D, "lengths");
}
@Override
public boolean isInRect(Rectangle r, ZirkelCanvas zc){
return ((r.contains(zc.col(P1.getX()),zc.row(P1.getY())))&&
(r.contains(zc.col(P2.getX()),zc.row(P2.getY()))));
}
/**
* see, if a point is on the segment or near to it.
*/
@Override
public boolean nearto(final int c, final int r, final ZirkelCanvas zc) {
if (ExpressionFailed && P1.valid()) {
return P1.nearto(c, r, zc);
}
if (ExpressionFailed && P2.valid()) {
return P2.nearto(c, r, zc);
}
if (!displays(zc)) {
return false;
}
// compute point at c,r
final double x = zc.x(c), y = zc.y(r);
// compute distance from line
double d = (x - X1) * DY - (y - Y1) * DX;
// compute offset
final double o = (x - X1) * DX + (y - Y1) * DY, o1 = (X2 - X1) * DX
+ (Y2 - Y1) * DY;
if (o1 > 0) {
if (o > o1) {
d = Math.sqrt((x - X2) * (x - X2) + (y - Y2) * (y - Y2));
} else if (o < 0) {
d = Math.sqrt((x - X1) * (x - X1) + (y - Y1) * (y - Y1));
}
} else {
if (o < o1) {
d = Math.sqrt((x - X2) * (x - X2) + (y - Y2) * (y - Y2));
} else if (o > 0) {
d = Math.sqrt((x - X1) * (x - X1) + (y - Y1) * (y - Y1));
}
}
// scale in screen coordinates
Value = Math.abs(zc.col(zc.minX() + d) - zc.col(zc.minX())) * 0.9;
return Value < zc.selectionSize();
}
/**
* true, if the segment is too small.
*/
@Override
public boolean onlynearto(final int c, final int r, final ZirkelCanvas zc) {
return R < zc.dx(3 *zc.pointSize());
}
@Override
public void printArgs(final XmlWriter xml) {
xml.printArg("from", P1.getName());
xml.printArg("to", P2.getName());
if (Is3D) {
xml.printArg("is3D", "true");
}
if (Fixed && E != null) {
xml.printArg("fixed", E.toString());
}
// if (Arrow) {
// xml.printArg("arrow", "true");
// } //plus nécessaire
if (code_symbol > 0) {
xml.printArg("code_symbol", "" + code_symbol);
}
super.printArgs(xml);
}
@Override
public double getLength() {
return R;
}
@Override
public double getLength3D() {
return R3D;
}
public boolean is3D() {
return Is3D;
}
@Override
public boolean fixed() {
return Fixed;
}
@Override
public boolean fixed3D() {
return Fixed3D;
}
@Override
public void setFixed(final boolean flag, final String s)
throws ConstructionException {
if (!flag || s.equals("")) {
Fixed = false;
E = null;
} else {
E = new Expression(s, getConstruction(), this);
if (!E.isValid()) {
throw new ConstructionException(E.getErrorText());
}
Fixed = true;
}
updateText();
}
@Override
public void setFixed3D(final boolean flag, final String s)
throws ConstructionException {
if (!flag || s.equals("")) {
Fixed3D = false;
E3D = null;
} else {
E3D = new Expression(s, getConstruction(), this);
if (!E3D.isValid()) {
throw new ConstructionException(E.getErrorText());
}
Fixed3D = true;
}
updateText();
}
@Override
public void round() {
try {
setFixed(true, getDisplayValue());
validate();
} catch (final Exception e) {
}
}
/**
* @return Segment can be fixed in length.
*/
@Override
public boolean canFix() {
return P1.moveableBy(this) || P2.moveableBy(this);
}
@Override
public boolean contains(final double x, final double y) {
final double a = (x - X1) * DX + (y - Y1) * DY;
if (a < -1e-9 || a > R + 1e-9) {
return false;
}
return true;
}
@Override
public double project(final double x, final double y) {
final double h = super.project(x, y);
if (h < 0) {
return 0;
}
if (h > R) {
return R;
}
return h;
}
/**
* @return true, if equal.
*/
@Override
public boolean equals(final ConstructionObject o) {
if (!(o instanceof SegmentObject) || !o.valid()) {
return false;
}
final SegmentObject l = (SegmentObject) o;
return (equals(X1, l.X1) && equals(X2, l.X2) && equals(Y1, l.Y1) && equals(
Y2, l.Y2))
|| (equals(X1, l.X2) && equals(Y1, l.Y2) && equals(X2, l.X1) && equals(
Y2, l.Y1));
}
public boolean isValidFix() {
return E != null && E.isValid();
}
@Override
public String getStringLength() {
if (E != null) {
return E.toString();
} else {
return "" + round(R);
}
}
public String getStringLength3D() {
if (E3D != null) {
return E3D.toString();
} else {
return "" + round(R3D);
}
}
public int getSegmentCode() {
return code_symbol;
}
public void setSegmentCode(final int i) {
code_symbol = i;
}
@Override
public double getValue() throws ConstructionException {
if (!Valid) {
throw new InvalidException("exception.invalid");
} else {
if (!P1.is3D()||!P2.is3D()) return R;
else return R3D;
}
}
public double getValue3D() throws ConstructionException {
if (!Valid) {
throw new InvalidException("exception.invalid");
} else {
return R3D;
}
}
@Override
public void translate() {
super.translate();
try {
setFixed(Fixed, E.toString());
E.translate();
} catch (final Exception e) {
Fixed = false;
}
}
@Override
public Enumeration depending() {
if (!Fixed &&!Fixed3D) {
return super.depending();
} else {
if (E!= null) {
super.depending();
final Enumeration e = E.getDepList().elements();
while (e.hasMoreElements()) {
DL.add((ConstructionObject) e.nextElement());
}
}
if (E3D!=null) {
final Enumeration f = E3D.getDepList().elements();
while (f.hasMoreElements()) {
DL.add((ConstructionObject) f.nextElement());
}
}
return DL.elements();
}
}
public void setArrow(final boolean arrow) {
Arrow = arrow;
}
public boolean isArrow() {
return Arrow;
}
@Override
public void project(final PointObject P) {
final double h = project(P.getX(), P.getY());
P.setXY(getX() + h * getDX(), getY() + h * getDY());
P.setA(h / getLength());
}
@Override
public void project(final PointObject P, final double alpha) {
final double d = alpha * getLength();
P.setXY(getX() + d * getDX(), getY() + d * getDY());
}
@Override
public boolean moveable() {
if (!Fixed && P1.moveable() && P2.moveable()) {
return true;
}
return false;
}
@Override
public void setFixed(final boolean bool) {
if (bool) {
E = new Expression(this.getStringLength(), getConstruction(), this);
}
Fixed=bool;
}
}

View file

@ -0,0 +1,28 @@
/*
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;
public interface SimulationObject {
public void setSimulationValue(double x);
public void resetSimulationValue();
}

View file

@ -0,0 +1,386 @@
/*
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: PointObject.java
import java.awt.FontMetrics;
import java.io.BufferedReader;
import java.io.StringReader;
import java.util.Enumeration;
import java.util.Vector;
import rene.util.xml.XmlWriter;
import rene.gui.Global;
import rene.zirkel.ZirkelCanvas;
import rene.zirkel.construction.Construction;
import rene.zirkel.construction.Count;
import rene.zirkel.expression.Expression;
import rene.zirkel.expression.ExpressionColor;
import rene.zirkel.expression.ExpressionString;
import rene.zirkel.graphics.MyGraphics;
import rene.zirkel.graphics.MainGraphics;
public class TextObject extends ConstructionObject implements MoveableObject {
protected double X, Y;
Vector T;
static Count N=new Count();
double C, R, W, H;
protected Expression EX, EY;
protected boolean Fixed;
protected boolean DoShow; // for replays
public TextObject(final Construction c, final double x, final double y) {
super(c);
X=x;
Y=y;
T=new Vector();
setColor(ColorIndex, SpecialColor);
Valid=true;
setLines("<txt>");
}
@Override
public void setDefaults() {
// setShowName(Global.getParameter("options.text.shownames",false));
// setShowValue(Global.getParameter("options.text.showvalues",false));
setShowName(true);
setShowValue(true);
setColor(Global.getParameter("options.text.color", 0), Global.getParameter("options.text.pcolor", (ExpressionColor) null, this));
setColorType(Global.getParameter("options.text.colortype", 0));
setHidden(Cn.Hidden);
setObtuse(Cn.Obtuse);
setSolid(Cn.Solid);
setLarge(Cn.LargeFont);
setBold(Cn.BoldFont);
setPartial(Cn.Partial);
}
@Override
public void setTargetDefaults() {
setShowName(true);
setShowValue(true);
setColor(Global.getParameter("options.text.color", 0), Global.getParameter("options.text.pcolor", (ExpressionColor) null, this));
setColorType(Global.getParameter("options.text.colortype", 0));
}
@Override
public boolean nearto(final int x, final int y, final ZirkelCanvas zc) {
if (!displays(zc)) {
return false;
}
return C<=x&&R<=y&&x<=C+W&&y<=R+H;
}
@Override
public String getTag() {
return "Text";
}
@Override
public int getN() {
return N.next();
}
@Override
public void updateText() {
setText(getLines(), true);
}
@Override
public void move(final double x, final double y) {
X=x;
Y=y;
}
@Override
public void paint(final MyGraphics g, final ZirkelCanvas zc) {
C=zc.col(X);
R=zc.row(Y);
// if (true) {
// Enumeration e=T.elements();
// String txt="";
// while (e.hasMoreElements()) {
// String s = ((ExpressionString) e.nextElement()).evaluate();
// txt=txt+s+"coucou\n";
// }
// g.drawLaTeXString(txt,C,R);
// return;
// }
if (mustHide(zc)) {
return;
}
final boolean hidden=Hidden;
if (DoShow) {
Hidden=false;
}
g.setColor(this);
setFont(g);
if (DoShow) {
Hidden=hidden;
}
FontMetrics fm=g.getFontMetrics();
W=H=fm.getHeight();
final Enumeration e=T.elements();
double r=R;
while (e.hasMoreElements()) {
String s=((ExpressionString) e.nextElement()).evaluate();
boolean bold=false, large=false;
if (s.startsWith("***")) {
s=s.substring(3);
bold=large=true;
} else if (s.startsWith("**")) {
s=s.substring(2);
large=true;
} else if (s.startsWith("*")) {
s=s.substring(1);
bold=true;
}
if (isStrongSelected()) {
((MainGraphics) g).drawMarkerRect(C, r, 10, 10);
g.setColor(this);
}
g.setFont(large, bold);
// r+=g.drawLaTeXString(s, C, r);
r += g.drawStringExtended(s, C, r);
W=Math.max(W, ((MainGraphics) g).getW());
// W=Math.max(W, fm.stringWidth(s));
}
H=r-R;
}
@Override
public boolean mustHide(final ZirkelCanvas zc) {
return super.mustHide(zc)&&!(Valid&&DoShow);
}
@Override
public void validate() {
Valid=true;
if (Fixed&&EX!=null&&EX.isValid()) {
try {
X=EX.getValue();
} catch (final Exception e) {
Valid=false;
return;
}
}
if (Fixed&&EY!=null&&EY.isValid()) {
try {
Y=EY.getValue();
} catch (final Exception e) {
Valid=false;
return;
}
}
}
@Override
public String getLines() {
String S="";
final Enumeration e=T.elements();
while (e.hasMoreElements()) {
final String s=((ExpressionString) e.nextElement()).toString();
S=S+s;
if (e.hasMoreElements()) {
S=S+"\n";
}
}
return S;
}
@Override
public void setLines(String o) {
if (o.equals("")) {
o="<txt>";
}
final Vector w=new Vector();
try {
final BufferedReader in=new BufferedReader(new StringReader(o));
while (true) {
final String s=in.readLine();
if (s==null) {
break;
}
w.addElement(new ExpressionString(s, this));
}
in.close();
} catch (final Exception e) {
}
T=w;
updateText();
}
@Override
public String getDisplayValue() {
return "("+roundDisplay(X)+","+roundDisplay(Y)+")";
}
@Override
public double getX() {
return X;
}
@Override
public double getY() {
return Y;
}
@Override
public void printArgs(final XmlWriter xml) {
if (Fixed&&EX!=null&&EX.isValid()) {
xml.printArg("x", EX.toString());
} else {
xml.printArg("x", ""+X);
}
if (Fixed&&EY!=null&&EY.isValid()) {
xml.printArg("y", EY.toString());
} else {
xml.printArg("y", ""+Y);
}
if (Fixed) {
xml.printArg("fixed", "true");
}
}
public boolean moveable() {
return !Fixed;
}
@Override
public boolean fixed() {
return Fixed;
}
@Override
public void setFixed(final boolean flag) {
Fixed=flag;
if (!Fixed) {
EX=EY=null;
}
updateText();
}
@Override
public void setFixed(final String x, final String y) {
Fixed=true;
EX=new Expression(x, getConstruction(), this);
EY=new Expression(y, getConstruction(), this);
updateText();
}
@Override
public String getEX() {
if (EX!=null) {
return EX.toString();
} else {
return ""+round(X);
}
}
@Override
public String getEY() {
if (EY!=null) {
return EY.toString();
} else {
return ""+round(Y);
}
}
public void setDoShow(final boolean flag) {
DoShow=flag;
}
@Override
public void snap(final ZirkelCanvas zc) {
final double d=zc.getGridSize()/2;
X=Math.round(X/d)*d;
Y=Math.round(Y/d)*d;
}
@Override
public void translate() {
if (Fixed) {
try {
setFixed(EX.toString(), EY.toString());
EX.translate();
EY.translate();
} catch (final Exception e) {
}
}
}
@Override
public Enumeration depending() {
super.depending();
final Enumeration e=T.elements();
while (e.hasMoreElements()) {
((ExpressionString) e.nextElement()).addDep(this);
}
if (Fixed) {
if (EX!=null) {
EX.addDep(this);
}
if (EY!=null) {
EY.addDep(this);
}
}
return DL.elements();
}
@Override
public boolean canDisplayName() {
return false;
}
double oldx, oldy, startx, starty;
public void startDrag(final double x, final double y) {
oldx=X;
oldy=Y;
startx=x;
starty=y;
}
public void dragTo(final double x, final double y) {
move(oldx+(x-startx), oldy+(y-starty));
}
public double getOldX() {
return oldx;
}
public double getOldY() {
return oldy;
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,132 @@
/*
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: SegmentObject.java
import java.util.Enumeration;
import rene.zirkel.ZirkelCanvas;
import rene.zirkel.construction.Construction;
public class TwoPointLineObject extends PrimitiveLineObject implements
MoveableObject {
protected PointObject P2, P1;
double X2, Y2, R, R3D;
public TwoPointLineObject(final Construction c, final PointObject p1,
final PointObject p2) {
super(c);
P1 = p1;
P2 = p2;
}
public void setP1P2(final PointObject p1, final PointObject p2) {
P1 = p1;
P2 = p2;
}
public PointObject getP2() {
return P2;
}
public PointObject getP1() {
return P1;
}
@Override
public Enumeration secondaryParams() {
DL.reset();
return depset(P1, P2);
}
@Override
public Enumeration depending() {
super.depending();
return depset(P1, P2);
}
public double getLength() {
return R;
}
public double getLength3D() {
return R3D;
}
@Override
public void translate() {
P1 = (PointObject) P1.getTranslation();
P2 = (PointObject) P2.getTranslation();
}
@Override
public boolean contains(final PointObject p) {
return P1 == p || P2 == p;
}
public void dragTo(final double x, final double y) {
// System.out.println(getName()+" : dragTo !");
P1.move(x1 + (x - x3), y1 + (y - y3));
P2.move(x2 + (x - x3), y2 + (y - y3));
}
@Override
public void move(final double x, final double y) {
}
public boolean moveable() {
if (P1.moveable() && P2.moveable())
return true;
return false;
}
double x1, y1, x2, y2, x3, y3;
public void startDrag(final double x, final double y) {
x1 = P1.getX();
y1 = P1.getY();
x2 = P2.getX();
y2 = P2.getY();
x3 = x;
y3 = y;
}
@Override
public void snap(final ZirkelCanvas zc) {
if (moveable()) {
P1.snap(zc);
P2.snap(zc);
}
}
public double getOldX() {
return 0;
}
public double getOldY() {
return 0;
}
}

View file

@ -0,0 +1,483 @@
/*
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: Functionbject.java
import java.awt.Checkbox;
import java.awt.Color;
import java.awt.FontMetrics;
import java.awt.Frame;
import java.awt.TextField;
import java.awt.event.FocusEvent;
import java.util.Enumeration;
import java.util.StringTokenizer;
import eric.JEricPanel;
import rene.dialogs.Warning;
import rene.gui.Global;
import rene.gui.IconBar;
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.InvalidException;
import rene.zirkel.graphics.MyGraphics;
import eric.bar.JProperties;
import eric.bar.JPropertiesBar;
import rene.zirkel.expression.ExpressionColor;
/**
* @author Rene
*
* This class is for function of several variables. Those functions
* cannot be drawn at all.
*/
public class UserFunctionObject extends ConstructionObject implements
MoveableObject, DriverObject, Evaluator {
static Count N = new Count();
Expression EY = null;
double X[] = { 0 };
String Var[] = { "x" };
protected double Xpos, Ypos;
protected boolean Fixed;
protected Expression EXpos, EYpos;
String LASTE = "";
public UserFunctionObject(final Construction c) {
super(c);
validate();
updateText();
N.reset();
}
@Override
public void setDefaults() {
setShowName(Global.getParameter("options.text.shownames", false));
setShowValue(Global.getParameter("options.text.showvalues", false));
setColor(Global.getParameter("options.text.color", 0), Global
.getParameter("options.text.pcolor", (ExpressionColor) null, this));
setColorType(Global.getParameter("options.text.colortype", 0));
setHidden(Cn.Hidden);
setObtuse(Cn.Obtuse);
setSolid(Cn.Solid);
setLarge(Cn.LargeFont);
setBold(Cn.BoldFont);
setPartial(Cn.Partial);
}
@Override
public void setTargetDefaults() {
setShowName(Global.getParameter("options.text.shownames", false));
setShowValue(Global.getParameter("options.text.showvalues", false));
setColor(Global.getParameter("options.text.color", 0), Global
.getParameter("options.text.pcolor", (ExpressionColor) null, this));
setColorType(Global.getParameter("options.text.colortype", 0));
}
@Override
public String getTag() {
return "Function";
}
@Override
public int getN() {
return N.next();
}
@Override
public void updateText() {
setText(getDisplayValue());
}
public boolean isValid() {
return Valid;
}
@Override
public void validate() {
if (EY != null) {
Valid = EY.isValid();
} else {
Valid = false;
}
if (Fixed && EXpos != null && EXpos.isValid()) {
try {
Xpos = EXpos.getValue();
} catch (final Exception e) {
Valid = false;
return;
}
}
if (Fixed && EYpos != null && EYpos.isValid()) {
try {
Ypos = EYpos.getValue();
} catch (final Exception e) {
Valid = false;
return;
}
}
}
public void setExpressions(final String t, final String ey) {
final StringTokenizer tok = new StringTokenizer(t);
Var = new String[tok.countTokens()];
X = new double[tok.countTokens()];
int i = 0;
while (tok.hasMoreTokens()) {
Var[i++] = tok.nextToken();
}
EY = new Expression(ey, getConstruction(), this, Var);
validate();
}
@Override
public String getEY() {
if (EY != null) {
return EY.toString();
} else {
return "0";
}
}
double C, R, W, H;
@Override
public void paint(final MyGraphics g, final ZirkelCanvas zc) {
if (!Valid || mustHide(zc)) {
return;
}
final FontMetrics fm = g.getFontMetrics();
H = fm.getHeight();
C = zc.col(Xpos);
R = zc.row(Ypos);
g.setColor(this);
setFont(g);
final String s = AngleObject.translateToUnicode(getDisplayValue());
g.drawString(s, C, R);
R -= H;
W = fm.stringWidth(s);
}
@Override
public double getValue() throws ConstructionException {
if (!Valid) {
throw new InvalidException("exception.invalid");
}
return X[0];
}
public double getValue(final String var) throws ConstructionException {
if (!Valid) {
throw new InvalidException("exception.invalid");
}
for (int i = 0; i < Var.length; i++) {
if (var.equals(Var[i])) {
return X[i];
}
}
return X[0];
}
@Override
public String getDisplayValue() {
String s = "";
if (showName()) {
if (getAlias() != null) {
s = getAlias() + " : ";
}
s = s + getName() + "(" + Var[0];
for (int i = 1; i < Var.length; i++) {
s = s + "," + Var[i];
}
s = s + ")";
if (showValue()) {
s = s + "=";
}
}
if (showValue()) {
s = s
+ ((EY == null) ? "" : JProperties.Point_To_Comma(EY
.toString(), Cn, true));
}
return s;
}
@Override
public boolean nearto(final int cc, final int rr, final ZirkelCanvas zc) {
if (!displays(zc)) {
return false;
}
return C <= cc && R <= rr && cc <= C + W && rr <= R + H;
}
public boolean EditAborted;
@Override
public void printArgs(final XmlWriter xml) {
xml.printArg("f", EY.toString());
if (Fixed && EXpos != null && EXpos.isValid()) {
xml.printArg("x", EXpos.toString());
} else {
xml.printArg("x", "" + Xpos);
}
if (Fixed && EYpos != null && EYpos.isValid()) {
xml.printArg("y", EYpos.toString());
} else {
xml.printArg("y", "" + Ypos);
}
if (Fixed) {
xml.printArg("fixed", "true");
}
xml.printArg("var", getVar());
}
@Override
public void translate() {
try {
EY = new Expression(EY.toString(), getConstruction(), this, Var);
final ConstructionObject O = getTranslation();
setTranslation(this);
if (Fixed) {
try {
setFixed(EXpos.toString(), EYpos.toString());
EXpos.translate();
EYpos.translate();
} catch (final Exception e) {
}
}
validate();
setTranslation(O);
} catch (final Exception e) {
System.out.println();
System.out.println(getName());
System.out.println(e);
e.printStackTrace();
}
}
@Override
public void setFixed(final boolean flag) {
Fixed = flag;
if (!Fixed) {
EXpos = EYpos = null;
}
updateText();
}
@Override
public void setFixed(final String x, final String y) {
Fixed = true;
EXpos = new Expression(x, getConstruction(), this);
EYpos = new Expression(y, getConstruction(), this);
updateText();
}
@Override
public boolean fixed() {
return Fixed;
}
@Override
public String getEXpos() {
if (EXpos != null) {
return EXpos.toString();
} else {
return "" + round(Xpos);
}
}
@Override
public String getEYpos() {
if (EYpos != null) {
return EYpos.toString();
} else {
return "" + round(Ypos);
}
}
@Override
public boolean onlynearto(final int x, final int y, final ZirkelCanvas zc) {
return false;
// return nearto(x,y,zc);
}
@Override
public boolean equals(final ConstructionObject o) {
return false;
}
@Override
public Enumeration depending() {
DL.reset();
addDepending(EY);
if (Fixed) {
addDepending(EXpos);
addDepending(EYpos);
}
return DL.elements();
}
public void addDepending(final Expression E) {
if (E != null) {
final Enumeration e = E.getDepList().elements();
while (e.hasMoreElements()) {
DL.add((ConstructionObject) e.nextElement());
}
}
}
@Override
public boolean hasUnit() {
return false;
}
public double evaluateF(final double x[]) throws ConstructionException {
int n = x.length;
if (n > X.length) {
n = X.length;
}
for (int i = 0; i < n; i++) {
X[i] = x[i];
}
for (int i = n; i < X.length; i++) {
X[i] = 0;
}
try {
return EY.getValue();
} catch (final Exception e) {
throw new ConstructionException("");
}
}
public double evaluateF(final double x) throws ConstructionException {
X[0] = x;
for (int i = 1; i < X.length; i++) {
X[i] = 0;
}
try {
return EY.getValue();
} catch (final Exception e) {
throw new ConstructionException("");
}
}
public double evaluateF(final double x, final double y)
throws ConstructionException {
X[0] = x;
X[1] = y;
for (int i = 2; i < X.length; i++) {
X[i] = 0;
}
try {
return EY.getValue();
} catch (final Exception e) {
throw new ConstructionException("");
}
}
@Override
public boolean maybeTransparent() {
return true;
}
@Override
public boolean canDisplayName() {
return true;
}
@Override
public boolean isFilledForSelect() {
return false;
}
public String getVar() {
String vars = Var[0];
for (int i = 1; i < Var.length; i++) {
vars = vars + " " + Var[i];
}
return vars;
}
public void dragTo(final double x, final double y) {
move(oldx + (x - startx), oldy + (y - starty));
}
@Override
public void move(final double x, final double y) {
Xpos = x;
Ypos = y;
}
double oldx, oldy, startx, starty;
public boolean moveable() {
return !Fixed;
}
public void startDrag(final double x, final double y) {
oldx = Xpos;
oldy = Ypos;
startx = x;
starty = y;
}
public double getOldX() {
return oldx;
}
public double getOldY() {
return oldy;
}
@Override
public double getX() {
return Xpos;
}
@Override
public double getY() {
return Ypos;
}
@Override
public boolean isDriverObject() {
return true;
}
public boolean somethingChanged() {
return (!EY.toString().equals(LASTE));
}
public void clearChanges() {
LASTE = EY.toString();
}
}

View file

@ -0,0 +1,328 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package rene.zirkel.objects;
import eric.JZirkelCanvas;
import rene.gui.Global;
import rene.util.xml.XmlWriter;
import rene.zirkel.construction.Construction;
import rene.zirkel.construction.Count;
import rene.zirkel.expression.Expression;
/**
*
* @author PM
*/
public class VectorObject extends SegmentObject {
private Expression EX = null;
private Expression EY = null;
private Expression EX3D = null;
private Expression EY3D = null;
private Expression EZ3D = null;
//private double X3D = 0;
//private double Y3D = 0;
//private double Z3D = 0;
static Count N = new Count();
public VectorObject(final Construction c, final PointObject p1, final PointObject p2) {
super(c, p1, p2);
Arrow = true;
// int n = Global.name("name.short.Vector").length();
// String name = Name.substring(0, n)+"_"+Name.substring(n);
// this.setAlias("$\\overrightarrow{"+name+"}");
}
@Override
public Boolean is2DObject(){
return !Is3D;
}
@Override
public Boolean isTellsSon(){
return true;
//the vector object, like William Tell's son, has an arrow over it
}
@Override
public void setName() {
Name=Global.name("name.short.Vector")+getN();
}
@Override
public int getN() {
return N.next();
}
public double getDeltaX(){
return P2.getX()-P1.getX();
}
public double getDeltaY(){
return P2.getY()-P1.getY();
}
public double getDeltaX3D(){
return P2.getX3D()-P1.getX3D();
}
public double getDeltaY3D(){
return P2.getY3D()-P1.getY3D();
}
public double getDeltaZ3D(){
return P2.getZ3D()-P1.getZ3D();
}
@Override
public boolean fixedCoord(){
boolean b = P2.getEX().equals("x("+P1.getName()+")"+"+"+getEX());
b &= P2.getEY().equals("y("+P1.getName()+")"+"+"+getEY());
return b;
}
@Override
public boolean fixedCoord3D(){
boolean b = P2.getEX3D().equals("x3D("+P1.getName()+")"+"+"+getEX3D());
b &= P2.getEY3D().equals("y3D("+P1.getName()+")"+"+"+getEY3D());
b &= P2.getEZ3D().equals("z3D("+P1.getName()+")"+"+"+getEZ3D());
return b;
}
@Override
public void move(double x, double y){
P2.setColorType(THIN);
//P2.setHidden(true);
P2.move(P1.getX()+x, P1.getY()+y);
}
@Override
public void move3D(double x, double y, double z){
P2.setColorType(THIN);
//P2.setHidden(true);
P2.move3D(P1.getX3D()+x, P1.getY3D()+y, P1.getZ3D()+z);
}
@Override
public String getCDPDisplayValue(){
return "("+Global.getCDPLocaleNumber(this.getDeltaX(), 2)+" "+(Global.getParameter("options.germanpoints", false)?"|":";")+Global.getCDPLocaleNumber(this.getDeltaY(), 2)+")";
}
@Override
public String getDisplayValue() {
/*
String rep = "";
if(!this.showName()) {
rep += "$";
}*/
if (P1.is3D()&&P2.is3D()) return "\\left(\\begin{array}{r}"+Global.getLocaleNumber(getDeltaX3D(), "lengths")+"\\\\"+Global.getLocaleNumber(getDeltaY3D(), "lengths")+"\\\\"+Global.getLocaleNumber(getDeltaZ3D(), "lengths")+"\\end{array}\\right)";
else return "\\left(\\begin{array}{r}"+Global.getLocaleNumber(getDeltaX(), "lengths")+"\\\\"+Global.getLocaleNumber(getDeltaY(), "lengths")+"\\end{array}\\right)";
//return rep+"\\left(\\begin{array}{r}"+Global.getLocaleNumber(getDeltaX(), "lengths")+"\\\\"+Global.getLocaleNumber(getDeltaY(), "lengths")+"\\end{array}\\right)$";
//return "("+Global.getLocaleNumber(getDeltaX(), "lengths")+(Global.getParameter("options.germanpoints", false)?"|":";")+Global.getLocaleNumber(getDeltaY(), "lengths")+")";
}
@Override
public void updateText() {
if (!Fixed && !this.fixedCoord()) {
setText(text2(Global.name("text.vector"), P1.getName(), P2.getName()));
} else if (Fixed) {
if (E == null) {
setText(text3(Global.name("text.vector.fixed.length"), P1.getName(), P2.getName(), "" + round(R)));
} else {
setText(text3(Global.name("text.vector.fixed.length"), P1.getName(), P2.getName(), "\"" + E.toString() + "\""));
}
} else {
setText(text3(Global.name("text.vector.fixed.coord"), P1.getName(), P2.getName(), "(" + round(this.getDeltaX())+" ; " + round(this.getDeltaY()) + ")"));
}
}
@Override
public void setFixed(final String x, final String y) {
setEXY(x, y);
P2.setFixed("x("+P1.getName()+")"+"+"+EX.toString(), "y("+P1.getName()+")"+"+"+EY.toString());
P2.setColorType(THIN);
P2.setBack(true);//modif proposée par Alain le 29/12/12 parce que je sais pas comment mettre un numéro de calque :-X
updateText();
JZirkelCanvas.getCurrentZC().repaint();
}
@Override
public void setFixed(boolean b){
P2.setFixed(b);
P2.setColorType(b?THIN:NORMAL);
//P2.setHidden(b);
updateText();
JZirkelCanvas.getCurrentZC().repaint();
}
@Override
public void setFixed3D(boolean b){
P2.setFixed3D(b);
P2.setColorType(b?THIN:NORMAL);
//P2.setHidden(b);
updateText();
JZirkelCanvas.getCurrentZC().repaint();
}
@Override
public void setFixed(final String x, final String y, final String z) {
setEXYZ(x, y, z);
P2.setFixed("x3D("+P1.getName()+")"+"+"+EX3D.toString(), "y3D("+P1.getName()+")"+"+"+EY3D.toString(), "z3D("+P1.getName()+")"+"+"+EZ3D.toString());
P2.setColorType(THIN);
P2.setBack(true);//modif proposée par Alain le 29/12/12 parce que je sais pas comment mettre un numéro de calque :-X
updateText();
JZirkelCanvas.getCurrentZC().repaint();
}
public void setEXY(String x, String y){
EX = new Expression(x, getConstruction(), this);
EY = new Expression(y, getConstruction(), this);
}
public void setEXYZ(String x3D, String y3D, String z3D){
EX3D = new Expression(x3D, getConstruction(), this);
EY3D = new Expression(y3D, getConstruction(), this);
EZ3D = new Expression(z3D, getConstruction(), this);
}
@Override
public String getEX() {
if (EX!=null) {
return EX.toString();
} else {
return ""+round(this.getDeltaX());
}
}
@Override
public String getEY() {
if (EY!=null) {
return EY.toString();
} else {
return ""+round(this.getDeltaY());
}
}
@Override
public String getEX3D() {
if (EX3D!=null) {
return EX3D.toString();
} else {
return ""+round(this.getDeltaX3D());
}
}
@Override
public String getEY3D() {
if (EY3D!=null) {
return EY3D.toString();
} else {
return ""+round(this.getDeltaY3D());
}
}
@Override
public String getEZ3D() {
if (EZ3D!=null) {
return EZ3D.toString();
} else {
return ""+round(this.getDeltaZ3D());
}
}
@Override
public void printArgs(final XmlWriter xml) {
xml.printArg("from", P1.getName());
xml.printArg("to", P2.getName());
if (Fixed && E != null) {
xml.printArg("fixed", E.toString());
}
if(fixedCoord()){
xml.printArg("x", EX.toString());
xml.printArg("y", EY.toString());
}
if (Is3D) {
xml.printArg("is3D", "true");
if (Fixed3D && E3D != null) {
xml.printArg("fixed3D", E3D.toString());
}
if(fixedCoord3D()){
xml.printArg("x3D", EX3D.toString());
xml.printArg("y3D", EY3D.toString());
xml.printArg("z3D", EZ3D.toString());
}
}
if (Fixed3D) {
xml.printArg("fixed3D", "true");
}
xml.printArg("arrow", "true");
if (code_symbol > 0) {
xml.printArg("code_symbol", "" + code_symbol);
}
if (Partial) {
xml.printArg("partial", "true");
}
}
@Override
public boolean moveable() {
if(P1.moveable()&&!is3D()){
return true;
} else {
return false;
}
}
@Override
public ConstructionObject copy(final double x, final double y) {
VectorObject o=null;
try {
o=(VectorObject) clone();
setTranslation(o);
o.translateConditionals();
o.translate();
o.setName();
o.updateText();
o.setBreak(false);
//o.setTarget(false);
} catch (final Exception e) {}
return o;
}
@Override
public void translate() {
super.translate();
if (Is3D) {
try {
setEXYZ(EX3D.toString(), EY3D.toString(), EZ3D.toString());
EX3D.translate();
EY3D.translate();
EZ3D.translate();
}
catch (final Exception e) {}
}
else {
try {
setEXY(EX.toString(), EY.toString());
EX.translate();
EY.translate();
} catch (final Exception e) {
//setFixed(false);
}
}
}
public void setIs3D(boolean b) {
Is3D=b;
}
}