/** * */ package maps.util; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import rescuecore2.misc.geometry.GeometryTools2D; import rescuecore2.misc.geometry.Line2D; import rescuecore2.misc.geometry.Point2D; /** * @author Sebastian * */ public class PolygonSplitter { public static Polygon[] splitPolygon(Polygon polygon, double maxNodes, double maxCircumference) { List<Polygon> unfinishedPolygons = new LinkedList<Polygon>(); List<Polygon> finishedPolygons = new LinkedList<Polygon>(); unfinishedPolygons.add(polygon); while (unfinishedPolygons.size() > 0) { Polygon next = unfinishedPolygons.remove(0); if (next.getNumVertices() > maxNodes && next.getCircumference() > maxCircumference) { List<Polygon> split = splitPolygonEvenly(next); if (split != null) { unfinishedPolygons.addAll(split); } else { finishedPolygons.add(next); } } else { finishedPolygons.add(next); } } return finishedPolygons.toArray(new Polygon[0]); } /** * @param apexList */ public static Polygon reduceEdges(Polygon polygon, double minDegree) { List<Point2D> points = new ArrayList<Point2D>(polygon.x.length); Point2D lastPoint = new Point2D(polygon.x[0], polygon.y[0]); points.add(lastPoint); for (int i = 1; i < polygon.x.length; i++) { Point2D nextPoint = new Point2D(polygon.x[i], polygon.y[i]); Point2D nextPointAfter; if (i == polygon.x.length - 1) { nextPointAfter = points.get(0); } else { nextPointAfter = new Point2D(polygon.x[i + 1], polygon.y[i + 1]); } Line2D line1 = new Line2D(lastPoint, nextPoint); Line2D line2 = new Line2D(nextPoint, nextPointAfter); if (GeometryTools2D.getRightAngleBetweenLines(line1, line2) > minDegree) { points.add(nextPoint); lastPoint = nextPoint; } } double[] x = new double[points.size()]; double[] y = new double[points.size()]; for (int i = 0; i < points.size(); i++) { x[i] = points.get(i).getX(); y[i] = points.get(i).getY(); } return new Polygon(x, y); } public static List<Polygon> splitPolygonEvenly(Polygon next) { List<Line2D> edges = new ArrayList<Line2D>(); double[] x = next.x; double[] y = next.y; for (int i = 0; i < x.length; i++) { edges.add(new Line2D(new Point2D(x[i], y[i]), new Point2D(x[(i + 1) % x.length], y[(i + 1) % x.length]))); } double bestCircumference = Double.MAX_VALUE; List<Polygon> bestPolygons = null; for (int i = 0; i < x.length; i++) { for (int j = i + 2; j < x.length; j++) { if (i == 0 && j == x.length - 1) { continue; } Line2D newLine = new Line2D(new Point2D(x[i], y[i]), new Point2D(x[j], y[j])); // First check this edge does not intersect other edges than // those immediately around the points boolean valid = true; int intersections = 0; for (int k = 0; k < edges.size(); k++) { if (k == i || ((i - 1 + x.length) % x.length) == k) { continue; } if (k == j || ((j - 1 + x.length) % x.length) == k) { continue; } double intersectionE2HWL = edges.get(k).getIntersection( newLine); double intersectionHWL2E = newLine.getIntersection(edges .get(k)); // Avoid parallel lines if (intersectionE2HWL == Double.NaN) { valid = false; break; } // Exactly hits a vertex - ignore this one. if (intersectionHWL2E == 0 || intersectionHWL2E == 1) { valid = false; break; } if (intersectionE2HWL > 0) { if (intersectionHWL2E > 0 && intersectionHWL2E < 1) { if (intersectionE2HWL < 1) { valid = false; break; } else { intersections++; } } } // Check for intersection /* * if () { if (intersectionHWL2E >= 0) { if * (intersectionHWL2E < 1) { //valid = false; //break; } * else { // intersections++; } } } */ } if (valid && (intersections % 2 == 0)) { // Try to construct polygons List<Polygon> polygons = new ArrayList<Polygon>(2); List<Point2D> firstPolygon = new ArrayList<Point2D>(); List<Point2D> secondPolygon = new ArrayList<Point2D>(); for (int a = i; a != (j + 1) % x.length; a = (a + 1) % x.length) { firstPolygon.add(new Point2D(x[a], y[a])); } for (int a = j; a != (i + 1) % x.length; a = (a + 1) % x.length) { secondPolygon.add(new Point2D(x[a], y[a])); } double[] firstXs = new double[firstPolygon.size()]; double[] firstYs = new double[firstPolygon.size()]; double[] secondXs = new double[secondPolygon.size()]; double[] secondYs = new double[secondPolygon.size()]; for (int a = 0; a < firstXs.length; a++) { firstXs[a] = firstPolygon.get(a).getX(); firstYs[a] = firstPolygon.get(a).getY(); } for (int a = 0; a < secondXs.length; a++) { secondXs[a] = secondPolygon.get(a).getX(); secondYs[a] = secondPolygon.get(a).getY(); } polygons.add(new Polygon(firstXs, firstYs)); polygons.add(new Polygon(secondXs, secondYs)); double firstC = polygons.get(0).getCircumference(); double secondC = polygons.get(1).getCircumference(); double max = (firstC > secondC) ? firstC : secondC; if (max < bestCircumference) { bestCircumference = max; bestPolygons = polygons; } } } } return bestPolygons; } }