306 lines
8.1 KiB
Java
306 lines
8.1 KiB
Java
/*
|
|
|
|
Copyright 2006 Rene Grothmann, modified by Eric Hakenholz
|
|
|
|
This file is part of C.a.R. software.
|
|
|
|
C.a.R. is a free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, version 3 of the License.
|
|
|
|
C.a.R. is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
package rene.zirkel.objects;
|
|
|
|
// file: 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);
|
|
}
|
|
|
|
}
|