package org.geogebra.common.kernel.discrete;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;
import org.geogebra.common.awt.GPoint2D;
import org.geogebra.common.kernel.Construction;
import org.geogebra.common.kernel.Kernel;
import org.geogebra.common.kernel.MyPoint;
import org.geogebra.common.kernel.SegmentType;
import org.geogebra.common.kernel.commands.Commands;
import org.geogebra.common.kernel.discrete.delaunay.Delaunay_Triangulation;
import org.geogebra.common.kernel.discrete.delaunay.Point_dt;
import org.geogebra.common.kernel.discrete.delaunay.Triangle_dt;
import org.geogebra.common.kernel.geos.GeoElement;
import org.geogebra.common.kernel.geos.GeoList;
import org.geogebra.common.kernel.kernelND.GeoPointND;
import org.geogebra.common.util.debug.Log;
public class AlgoDelauneyTriangulation extends AlgoDiscrete {
public AlgoDelauneyTriangulation(Construction cons, String label,
GeoList inputList) {
super(cons, label, inputList, null);
}
@Override
public Commands getClassName() {
return Commands.DelauneyTriangulation;
}
@Override
public final void compute() {
try {
size = inputList.size();
if (!inputList.isDefined() || size == 0) {
locus.setUndefined();
return;
}
double inhom[] = new double[2];
Point_dt[] points = new Point_dt[size];
for (int i = 0; i < size; i++) {
GeoElement geo = inputList.get(i);
if (geo.isDefined() && geo.isGeoPoint()) {
GeoPointND p = (GeoPointND) geo;
p.getInhomCoords(inhom);
points[i] = new Point_dt(inhom[0], inhom[1]);
}
}
Delaunay_Triangulation dt = new Delaunay_Triangulation(points);
if (dt.allCollinear) {
locus.setUndefined();
return;
}
Iterator<Triangle_dt> it = dt.trianglesIterator();
if (al == null) {
al = new ArrayList<MyPoint>();
} else {
al.clear();
}
// add to TreeSet to remove duplicates (from touching triangles)
TreeSet<MyLine> tree = new TreeSet<MyLine>(getComparator());
while (it.hasNext()) {
Triangle_dt triangle = it.next();
tree.add(new MyLine(
new GPoint2D.Double(triangle.p1().x(),
triangle.p1().y()),
new GPoint2D.Double(triangle.p2().x(),
triangle.p2().y())));
if (triangle.p3() != null) {
tree.add(new MyLine(
new GPoint2D.Double(triangle.p2().x(),
triangle.p2().y()),
new GPoint2D.Double(triangle.p3().x(),
triangle.p3().y())));
tree.add(new MyLine(
new GPoint2D.Double(triangle.p3().x(),
triangle.p3().y()),
new GPoint2D.Double(triangle.p1().x(),
triangle.p1().y())));
}
}
Iterator<MyLine> it2 = tree.iterator();
while (it2.hasNext()) {
MyLine line = it2.next();
al.add(new MyPoint(line.p1.getX(), line.p1.getY(),
SegmentType.MOVE_TO));
al.add(new MyPoint(line.p2.getX(), line.p2.getY(),
SegmentType.LINE_TO));
}
locus.setPoints(al);
locus.setDefined(true);
} catch (Exception e) {
Log.error(e.getMessage());
locus.setUndefined();
}
}
/*
* comparator used to eliminate duplicate objects (TreeSet deletes
* duplicates ie those that return 0)
*/
public static Comparator<MyLine> getComparator() {
if (lineComparator == null) {
lineComparator = new Comparator<MyLine>() {
@Override
public int compare(MyLine itemA, MyLine itemB) {
GPoint2D p1A = itemA.p1;
GPoint2D p2A = itemA.p2;
GPoint2D p1B = itemB.p1;
GPoint2D p2B = itemB.p2;
// return 0 if endpoints the same
// so no duplicates in the TreeMap
if (Kernel.isEqual(p1A.getX(), p2B.getX())
&& Kernel.isEqual(p1A.getY(), p2B.getY())
&& Kernel.isEqual(p2A.getX(), p1B.getX())
&& Kernel.isEqual(p2A.getY(), p1B.getY())) {
// Application.debug("equal2");
return 0;
}
// check this one second (doesn't occur in practice)
if (Kernel.isEqual(p1A.getX(), p1B.getX())
&& Kernel.isEqual(p1A.getY(), p1B.getY())
&& Kernel.isEqual(p2A.getX(), p2B.getX())
&& Kernel.isEqual(p2A.getY(), p2B.getY())) {
// Application.debug("equal1");
return 0;
}
// need to return something sensible, otherwise tree doesn't
// work
return itemA.lengthSquared() > itemB.lengthSquared() ? -1
: 1;
}
};
}
return lineComparator;
}
private static Comparator<MyLine> lineComparator;
}