package org.geogebra.common.kernel.discrete.delaunay; import java.util.Comparator; import org.geogebra.common.kernel.Kernel; import org.geogebra.common.util.MyMath; import org.geogebra.common.util.debug.Log; /** * This class represents a 3D point, with some simple geometric methods * (pointLineTest). */ public class Point_dt { double x, y, z; @Override public int hashCode() { double tempArray[] = { x, y, z }; return java.util.Arrays.hashCode(tempArray); } /** * Default Constructor. <br /> * constructs a 3D point at (0,0,0). */ public Point_dt() { this(0, 0); } /** * constructs a 3D point */ public Point_dt(double x, double y, double z) { this.x = x; this.y = y; this.z = z; } /** constructs a 3D point with a z value of 0. */ public Point_dt(double x, double y) { this(x, y, 0); } /** simple copy constructor */ public Point_dt(Point_dt p) { x = p.x; y = p.y; z = p.z; } /** returns the x-coordinate of this point. */ public double x() { return x; } /** * Sets the x coordinate. * * @param x * The new x coordinate. */ public void setX(double x) { this.x = x; } /** returns the y-coordinate of this point. */ public double y() { return y; } /** * Sets the y coordinate. * * @param y * The new y coordinate. */ public void setY(double y) { this.y = y; } /** returns the z-coordinate of this point. */ public double z() { return z; } /** * Sets the z coordinate. * * @param z * The new z coordinate. */ public void setZ(double Z) { this.z = Z; } double distance2(Point_dt p) { return (p.x - x) * (p.x - x) + (p.y - y) * (p.y - y); } double distance2(double px, double py) { return (px - x) * (px - x) + (py - y) * (py - y); } boolean isLess(Point_dt p) { return Compare.lessThan(x, p.x) || (Compare.equals(x, p.x) && Compare.lessThan(y, p.y)); } boolean isGreater(Point_dt p) { return Compare.greaterThan(x, p.x) || (Compare.equals(x, p.x) && Compare.greaterThan(y, p.y)); } /** * return true iff this point [x,y] coordinates are the same as p [x,y] * coordinates. (the z value is ignored). */ @Override public boolean equals(Object p) { if (!(p instanceof Point_dt)) { return false; } return Compare.equals(x, ((Point_dt) p).x) && Compare.equals(y, ((Point_dt) p).y); } /** return a String in the [x,y,z] format */ @Override public String toString() { return " Pt[" + x + "," + y + "," + z + "]"; } /** @return the L2 distance NOTE: 2D only!!! */ public double distance(Point_dt p) { return MyMath.length(p.x() - x, p.y() - y); //double temp = Math.pow(p.x() - x, 2) + Math.pow(p.y() - y, 2); //return Math.sqrt(temp); } /** @return the L2 distance NOTE: 3D only!!! */ public double distance3D(Point_dt p) { return MyMath.length(p.x() - x, p.y() - y, p.z() - z); // double temp = Math.pow(p.x() - x, 2) + Math.pow(p.y() - y, 2) // + Math.pow(p.z() - z, 2); // return Math.sqrt(temp); } /** * return a String: x y z (used by the save to file - write_tsin method). */ public String toFile() { return ("" + x + " " + y + " " + z); } String toFileXY() { return ("" + x + " " + y); } // pointLineTest // =============== // simple geometry to make things easy! public final static int ONSEGMENT = 0; /** * + <br> */ public final static int LEFT = 1; /** * + */ public final static int RIGHT = 2; public final static int INFRONTOFA = 3; public final static int BEHINDB = 4; public final static int ERROR = 5; /** * tests the relation between this point (as a 2D [x,y] point) and a 2D * segment a,b (the Z values are ignored), returns one of the following: * LEFT, RIGHT, INFRONTOFA, BEHINDB, ONSEGMENT * * @param a * the first point of the segment. * @param b * the second point of the segment. * @return the value (flag) of the relation between this point and the a,b * line-segment. */ public int pointLineTest(Point_dt a, Point_dt b) { double dx = b.x - a.x; double dy = b.y - a.y; double res = dy * (x - a.x) - dx * (y - a.y); if (res < 0) { return LEFT; } if (res > 0) { return RIGHT; } if (dx > 0) { if (x < a.x) { return INFRONTOFA; } if (b.x < x) { return BEHINDB; } return ONSEGMENT; } if (dx < 0) { if (x > a.x) { return INFRONTOFA; } if (b.x > x) { return BEHINDB; } return ONSEGMENT; } if (dy > 0) { if (y < a.y) { return INFRONTOFA; } if (b.y < y) { return BEHINDB; } return ONSEGMENT; } if (dy < 0) { if (y > a.y) { return INFRONTOFA; } if (b.y > y) { return BEHINDB; } return ONSEGMENT; } Log.error("Error, pointLineTest with a=b"); return ERROR; } boolean areCollinear(Point_dt a, Point_dt b) { double dx = b.x - a.x; double dy = b.y - a.y; double res = dy * (x - a.x) - dx * (y - a.y); return res == 0; } /* * public ajSegment Bisector( ajPoint b) { double sx = (x+b.x)/2; double sy * = (y+b.y)/2; double dx = b.x-x; double dy = b.y-y; ajPoint p1 = new * ajPoint(sx-dy,sy+dx); ajPoint p2 = new ajPoint(sx+dy,sy-dx); return new * ajSegment( p1,p2 ); } */ Point_dt circumcenter(Point_dt a, Point_dt b) { double u = ((a.x - b.x) * (a.x + b.x) + (a.y - b.y) * (a.y + b.y)) / 2.0f; double v = ((b.x - x) * (b.x + x) + (b.y - y) * (b.y + y)) / 2.0f; double den = (a.x - b.x) * (b.y - y) - (b.x - x) * (a.y - b.y); if (den == 0) { Log.debug("circumcenter, degenerate case"); } return new Point_dt((u * (b.y - y) - v * (a.y - b.y)) / den, (v * (a.x - b.x) - u * (b.x - x)) / den); } public static Comparator<Point_dt> getComparator(int flag) { return new Compare(flag); } public static Comparator<Point_dt> getComparator() { return new Compare(0); } } class Compare implements Comparator<Point_dt> { private int _flag; public Compare(int i) { _flag = i; } /** compare between two points. */ @Override public int compare(Point_dt d1, Point_dt d2) { int ans = 0; if (d1 != null && d2 != null) { if (_flag == 0) { if (greaterThan(d1.x, d2.x)) { return 1; } if (lessThan(d1.x, d2.x)) { return -1; } // x1 == x2 if (greaterThan(d1.y, d2.y)) { return 1; } if (lessThan(d1.y, d2.y)) { return -1; } } else if (_flag == 1) { if (greaterThan(d1.x, d2.x)) { return -1; } if (lessThan(d1.x, d2.x)) { return 1; } // x1 == x2 if (greaterThan(d1.y, d2.y)) { return -1; } if (lessThan(d1.y, d2.y)) { return 1; } } else if (_flag == 2) { if (greaterThan(d1.y, d2.y)) { return 1; } if (lessThan(d1.y, d2.y)) { return -1; } // y1 == y2 if (greaterThan(d1.x, d2.x)) { return 1; } if (d1.x < d2.x) { return -1; } } else if (_flag == 3) { if (greaterThan(d1.y, d2.y)) { return -1; } if (d1.y < d2.y) { return 1; } // y1 == y2 if (greaterThan(d1.x, d2.x)) { return -1; } if (lessThan(d1.x, d2.x)) { return 1; } } } else { if (d1 == null && d2 == null) { return 0; } if (d1 == null && d2 != null) { return 1; } if (d1 != null && d2 == null) { return -1; } } return ans; } public static boolean greaterThan(double x, double y) { return Kernel.isGreater(x, y); } public static boolean lessThan(double x, double y) { return Kernel.isGreater(y, x); } public static boolean equals(double x, double y) { return Kernel.isEqual(x, y); } }