/** * */ package maps.util; import rescuecore2.misc.geometry.GeometryTools2D; import rescuecore2.misc.geometry.Line2D; import rescuecore2.misc.geometry.Point2D; /** * from http://www.ewjordan.com/ * */ public class Polygon { public double[] x; public double[] y; public int nVertices; public Polygon(double[] _x, double[] _y) { nVertices = _x.length; // println("length "+nVertices); x = new double[nVertices]; y = new double[nVertices]; for (int i = 0; i < nVertices; ++i) { x[i] = _x[i]; y[i] = _y[i]; } } public Polygon(Triangle t) { this(t.x, t.y); } public void set(Polygon p) { nVertices = p.nVertices; x = new double[nVertices]; y = new double[nVertices]; for (int i = 0; i < nVertices; ++i) { x[i] = p.x[i]; y[i] = p.y[i]; } } /* * Assuming the polygon is simple, checks if it is convex. */ public boolean isConvex() { boolean isPositive = false; for (int i = 0; i < nVertices; ++i) { int lower = (i == 0) ? (nVertices - 1) : (i - 1); int middle = i; int upper = (i == nVertices - 1) ? (0) : (i + 1); double dx0 = x[middle] - x[lower]; double dy0 = y[middle] - y[lower]; double dx1 = x[upper] - x[middle]; double dy1 = y[upper] - y[middle]; double cross = dx0 * dy1 - dx1 * dy0; // Cross product should have same sign // for each vertex if poly is convex. boolean newIsP = (cross > 0) ? true : false; if (i == 0) { isPositive = newIsP; } else if (isPositive != newIsP) { return false; } } return true; } public boolean isRoughlyConvex(double degreeTolerance) { if (isConvex()) { return true; } for (int i = 0; i < nVertices; ++i) { int lower = (i == 0) ? (nVertices - 1) : (i - 1); int middle = i; int upper = (i == nVertices - 1) ? (0) : (i + 1); Line2D line1 = new Line2D(new Point2D(x[lower], y[lower]), new Point2D(x[middle], y[middle])); Line2D line2 = new Line2D(new Point2D(x[middle], y[middle]), new Point2D(x[upper], y[upper])); double angle = GeometryTools2D.getLeftAngleBetweenLines(line1, line2); if (!(angle <= 180 || (360 - angle) <= degreeTolerance)) { System.out.println(angle); return false; } } return true; } /* * Tries to add a triangle to the polygon. Returns null if it can't connect * properly. Assumes bitwise equality of join vertices. */ public Polygon add(Triangle t) { // First, find vertices that connect int firstP = -1; int firstT = -1; int secondP = -1; int secondT = -1; // println("nVertices: "+this.nVertices); for (int i = 0; i < nVertices; i++) { if (t.x[0] == x[i] && t.y[0] == y[i]) { // println("found p0"); if (firstP == -1) { firstP = i; firstT = 0; } else { secondP = i; secondT = 0; } } else if (t.x[1] == x[i] && t.y[1] == y[i]) { // println("found p1"); if (firstP == -1) { firstP = i; firstT = 1; } else { secondP = i; secondT = 1; } } else if (t.x[2] == x[i] && t.y[2] == y[i]) { // println("found p2"); if (firstP == -1) { firstP = i; firstT = 2; } else { secondP = i; secondT = 2; } } else { // println(t.x[0]+" "+t.y[0]+" "+t.x[1]+" "+t.y[1]+" "+t.x[2]+" "+t.y[2]); // println(x[0]+" "+y[0]+" "+x[1]+" "+y[1]); } } // Fix ordering if first should be last vertex of poly if (firstP == 0 && secondP == nVertices - 1) { firstP = nVertices - 1; secondP = 0; } // Didn't find it if (secondP == -1) return null; // Find tip index on triangle int tipT = 0; if (tipT == firstT || tipT == secondT) tipT = 1; if (tipT == firstT || tipT == secondT) tipT = 2; double[] newx = new double[nVertices + 1]; double[] newy = new double[nVertices + 1]; int currOut = 0; for (int i = 0; i < nVertices; i++) { newx[currOut] = x[i]; newy[currOut] = y[i]; if (i == firstP) { ++currOut; newx[currOut] = t.x[tipT]; newy[currOut] = t.y[tipT]; } ++currOut; } return new Polygon(newx, newy); } public double getCircumference() { double lastX = x[x.length - 1]; double lastY = y[x.length - 1]; double distance = 0; for (int i = 0; i < x.length; i++) { double thisX = x[i]; double thisY = y[i]; double diffX = lastX - thisX; double diffY = lastY - thisY; distance += Math.sqrt(diffX * diffX + diffY * diffY); lastX = thisX; lastY = thisY; } return distance; } /* * (non-Javadoc) * * @see java.lang.Object#toString() */ @Override public String toString() { String str = "Polygon"; for (int i = 0; i < x.length; i++) { str += "(" + x[i] + "," + y[i] + ")"; } str += ", c: " + getCircumference(); return str; } public int getNumVertices() { return x.length; } }