CaRMtl/rene/zirkel/tools/Tracker.java

316 lines
7.7 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.tools;
// file: Tracker.java
import java.awt.event.MouseEvent;
import java.util.Enumeration;
import java.util.Vector;
import rene.util.xml.XmlWriter;
import rene.gui.Global;
import rene.zirkel.ZirkelCanvas;
import rene.zirkel.constructors.ObjectConstructor;
import rene.zirkel.graphics.MyGraphics;
import rene.zirkel.graphics.TrackPainter;
import rene.zirkel.objects.ConstructionObject;
import rene.zirkel.objects.MoveableObject;
import rene.zirkel.objects.PointObject;
import rene.zirkel.objects.PrimitiveLineObject;
import rene.zirkel.structures.Coordinates;
public class Tracker extends ObjectConstructor implements TrackPainter {
ConstructionObject PM;
int PMax = 8, PN;
ConstructionObject P;
ConstructionObject PO[] = new ConstructionObject[PMax];
Vector V = new Vector();
Vector VO[] = new Vector[PMax];
double X, Y, DX, DY;
double XO[] = new double[PMax], YO[] = new double[PMax],
DXO[] = new double[PMax], DYO[] = new double[PMax];
boolean Started;
boolean StartedO[] = new boolean[PMax];
boolean Other;
public Tracker(final ConstructionObject p, final ConstructionObject po[]) {
super();
P = p;
PN = 0;
for (int i = 0; i < po.length; i++) {
if (i >= PMax || po[i] == null)
break;
PO[PN] = po[i];
VO[i] = new Vector();
PN++;
}
}
public Tracker() {
super();
}
@Override
public void mousePressed(final MouseEvent e, final ZirkelCanvas zc) {
final double x = zc.x(e.getX()), y = zc.y(e.getY());
if (P == null) {
P = zc.selectPoint(e.getX(), e.getY());
if (P == null)
P = zc.selectLine(e.getX(), e.getY());
if (P == null)
return;
P.setSelected(true);
zc.repaint();
if (e.isShiftDown())
Other = true;
else
Other = false;
showStatus(zc);
} else if (Other) {
ConstructionObject P = zc.selectPoint(e.getX(), e.getY());
if (P == null)
P = zc.selectLine(e.getX(), e.getY());
if (P != null) {
P.setSelected(true);
zc.repaint();
PO[PN] = P;
VO[PN] = new Vector();
PN++;
}
if (!e.isShiftDown() || PN >= PMax)
Other = false;
showStatus(zc);
} else {
final ConstructionObject pm = zc.selectMoveableObject(e.getX(), e
.getY());
PM = pm;
if (PM != null) {
zc.clearSelected();
PM.setSelected(true);
((MoveableObject) PM).startDrag(x, y);
zc.repaint();
showStatus(zc);
}
Started = false;
}
}
@Override
public void mouseMoved(final MouseEvent e, final ZirkelCanvas zc,
final boolean simple) {
if (P == null || Other)
zc.indicatePointsOrLines(e.getX(), e.getY());
else if (PM == null)
zc.indicateMoveableObjects(e.getX(), e.getY());
else
zc.clearIndicated();
}
@Override
public void mouseDragged(final MouseEvent e, final ZirkelCanvas zc) {
if (PM == null)
return;
((MoveableObject) PM).dragTo(zc.x(e.getX()), zc.y(e.getY()));
zc.validate();
track(zc);
zc.repaint();
}
@Override
public void mouseReleased(final MouseEvent e, final ZirkelCanvas zc) {
if (PM == null)
return;
PM.setSelected(false);
PM = null;
zc.repaint();
showStatus(zc);
}
@Override
public void reset(final ZirkelCanvas zc) {
zc.clearSelected();
P = PM = null;
PN = 0;
V = new Vector();
showStatus(zc);
zc.repaint();
}
@Override
public void showStatus(final ZirkelCanvas zc) {
if (P == null || Other)
zc.showStatus(Global.name("message.tracker.select"));
else if (PM == null)
zc.showStatus(Global.name("message.tracker.selectpoint"));
else
zc.showStatus(Global.name("message.tracker.move"));
}
public void track(final ZirkelCanvas zc) {
if (P == null)
return;
if (P instanceof PointObject) {
final PointObject p = (PointObject) P;
if (p.valid())
V.addElement(new Coordinates(p.getX(), p.getY()));
} else if (P instanceof PrimitiveLineObject) {
final PrimitiveLineObject L = (PrimitiveLineObject) P;
if (L.valid()) {
if (!Started) {
X = L.getX();
Y = L.getY();
DX = L.getDX();
DY = L.getDY();
Started = true;
} else {
double x, y, dx, dy;
x = L.getX();
y = L.getY();
dx = L.getDX();
dy = L.getDY();
final double det = dx * DY - dy * DX;
if (Math.sqrt(Math.abs(det)) > 1e-9) {
final double a = (-(X - x) * DY + DX * (Y - y))
/ (-det);
V.addElement(new Coordinates(x + a * dx, y + a * dy));
}
X = x;
Y = y;
DX = dx;
DY = dy;
}
}
}
for (int i = 0; i < PN; i++) {
if (PO[i] == null || !PO[i].valid())
continue;
if (PO[i] instanceof PointObject) {
final PointObject p = (PointObject) PO[i];
VO[i].addElement(new Coordinates(p.getX(), p.getY()));
} else if (PO[i] instanceof PrimitiveLineObject) {
final PrimitiveLineObject L = (PrimitiveLineObject) PO[i];
if (!StartedO[i]) {
XO[i] = L.getX();
YO[i] = L.getY();
DXO[i] = L.getDX();
DYO[i] = L.getDY();
StartedO[i] = true;
} else {
double x, y, dx, dy;
x = L.getX();
y = L.getY();
dx = L.getDX();
dy = L.getDY();
final double det = dx * DYO[i] - dy * DXO[i];
if (Math.sqrt(Math.abs(det)) > 1e-9) {
final double a = (-(XO[i] - x) * DYO[i] + DXO[i]
* (YO[i] - y))
/ (-det);
VO[i]
.addElement(new Coordinates(x + a * dx, y + a
* dy));
}
XO[i] = x;
YO[i] = y;
DXO[i] = dx;
DYO[i] = dy;
}
}
}
}
public Enumeration elements() {
return V.elements();
}
public void paint(final MyGraphics g, final ZirkelCanvas zc) {
if (P == null)
return;
Coordinates C;
Enumeration e = V.elements();
g.setColor(P);
double c0, r0, c, r;
final int maxd = zc.width() / 20;
if (e.hasMoreElements()) {
C = (Coordinates) e.nextElement();
c0 = zc.col(C.X);
r0 = zc.row(C.Y);
while (e.hasMoreElements()) {
C = (Coordinates) e.nextElement();
c = zc.col(C.X);
r = zc.row(C.Y);
if (Math.abs(c0 - c) < maxd && Math.abs(r0 - r) < maxd)
g.drawLine(c0, r0, c, r, P);
else
g.drawLine(c0, r0, c0, r0, P);
c0 = c;
r0 = r;
}
}
for (int i = 0; i < PN; i++) {
if (PO[i] == null)
continue;
g.setColor(PO[i]);
e = VO[i].elements();
if (e.hasMoreElements()) {
C = (Coordinates) e.nextElement();
c0 = zc.col(C.X);
r0 = zc.row(C.Y);
while (e.hasMoreElements()) {
C = (Coordinates) e.nextElement();
c = zc.col(C.X);
r = zc.row(C.Y);
if (Math.abs(c0 - c) < maxd && Math.abs(r0 - r) < maxd)
g.drawLine(c0, r0, c, r, PO[i]);
else
g.drawLine(c0, r0, c0, r0, PO[i]);
c0 = c;
r0 = r;
}
}
}
}
public void validate(final ZirkelCanvas zc) {
}
public void save(final XmlWriter xml) {
if (P == null)
return;
xml.startTagStart("Track");
xml.printArg("track", P.getName());
for (int i = 0; i < PN; i++) {
xml.printArg("track" + i, PO[i].getName());
}
if (PM != null)
xml.printArg("move", PM.getName());
xml.finishTagNewLine();
}
@Override
public boolean useSmartBoard() {
return false;
}
}