sascha@1794: package de.intevation.flys.geom; sascha@1794: sascha@1794: import gnu.trove.TDoubleArrayList; sascha@1794: sascha@1794: import java.io.Serializable; sascha@1794: sascha@1794: import java.awt.Shape; sascha@1794: sascha@1794: import java.awt.geom.Path2D; sascha@1794: import java.awt.geom.Point2D; sascha@1794: sascha@1794: import java.util.ArrayList; sascha@1794: import java.util.List; sascha@1794: import java.util.Arrays; sascha@1794: import java.util.Comparator; sascha@1794: import java.util.Collections; sascha@1794: sascha@1794: public class Polygon2D sascha@1794: implements Serializable sascha@1794: { sascha@1794: public static final Comparator POINT_X_CMP = sascha@1794: new Comparator() { sascha@1794: public int compare(Point2D a, Point2D b) { sascha@1794: double d = a.getX() - b.getX(); sascha@1794: if (d < 0d) return -1; sascha@1794: return d > 0d ? + 1 : 0; sascha@1794: } sascha@1794: }; sascha@1794: sascha@1794: public static final Comparator FIRST_POINT_X = sascha@1794: new Comparator() { sascha@1794: public int compare(Point2D [] a, Point2D [] b) { sascha@1794: if (a.length == 0) return -1; // should not happen. sascha@1794: if (b.length == 0) return +1; // should not happen. sascha@1794: double d = a[0].getX() - b[0].getX(); sascha@1794: if (d < 0d) return -1; sascha@1794: return d > 0d ? + 1 : 0; sascha@1794: } sascha@1794: }; sascha@1794: sascha@1794: protected TDoubleArrayList xs; sascha@1794: protected TDoubleArrayList ys; sascha@1794: sascha@1794: public Polygon2D() { sascha@1794: xs = new TDoubleArrayList(); sascha@1794: ys = new TDoubleArrayList(); sascha@1794: } sascha@1794: sascha@1794: public void add(double x, double y) { sascha@1794: xs.add(x); sascha@1794: ys.add(y); sascha@1794: } sascha@1794: sascha@1794: public double area() { sascha@1794: double area = 0d; sascha@1794: sascha@1794: for (int i = 0, N = xs.size(); i < N; ++i) { sascha@1794: int j = (i + 1) % N; sascha@1794: area += xs.getQuick(i)*ys.getQuick(j); sascha@1794: area -= xs.getQuick(j)*ys.getQuick(i); sascha@1794: } sascha@1794: sascha@1794: return 0.5d*area; sascha@1794: } sascha@1794: sascha@1794: public Shape toShape() { sascha@1794: Path2D.Double path = new Path2D.Double(); sascha@1794: sascha@1794: int N = xs.size(); sascha@1794: sascha@1794: if (N > 0) { sascha@1794: path.moveTo(xs.getQuick(0), ys.getQuick(0)); sascha@1794: for (int i = 1; i < N; ++i) { sascha@1794: path.lineTo(xs.getQuick(i), ys.getQuick(i)); sascha@1794: } sascha@1794: path.closePath(); sascha@1794: } sascha@1794: sascha@1794: return path; sascha@1794: } sascha@1794: sascha@1794: protected static List splitByNaNs( sascha@1794: double [] xs, sascha@1794: double [] ys sascha@1794: ) { sascha@1794: List parts = new ArrayList(); sascha@1794: sascha@1794: List tmp = new ArrayList(xs.length); sascha@1794: sascha@1794: for (int i = 0; i < xs.length; ++i) { sascha@1794: double x = xs[i]; sascha@1794: double y = ys[i]; sascha@1794: sascha@1794: if (Double.isNaN(x) || Double.isNaN(y)) { sascha@1794: if (!tmp.isEmpty()) { sascha@1794: Point2D [] part = new Point2D[tmp.size()]; sascha@1794: parts.add(tmp.toArray(part)); sascha@1794: tmp.clear(); sascha@1794: } sascha@1794: } sascha@1794: else { sascha@1794: tmp.add(new Point2D.Double(x, y)); sascha@1794: } sascha@1794: } sascha@1794: sascha@1794: if (!tmp.isEmpty()) { sascha@1794: Point2D [] part = new Point2D[tmp.size()]; sascha@1794: parts.add(tmp.toArray(part)); sascha@1794: } sascha@1794: sascha@1794: return parts; sascha@1794: } sascha@1794: sascha@1794: public static void createPolygons( sascha@1794: double [] xAs, double [] yAs, sascha@1794: double [] xBs, double [] yBs, sascha@1794: List positives, sascha@1794: List negatives sascha@1794: ) { sascha@1794: if (xAs.length == 0 || xBs.length == 0) { sascha@1794: return; sascha@1794: } sascha@1794: sascha@1794: List splAs = splitByNaNs(xAs, yAs); sascha@1794: List splBs = splitByNaNs(xBs, yBs); sascha@1794: sascha@1794: // They feeded us with NaNs only. sascha@1794: if (splAs.isEmpty() || splBs.isEmpty()) { sascha@1794: return; sascha@1794: } sascha@1794: sascha@1794: // Sort each part by x to ensure that the first sascha@1794: // is the smallest. sascha@1794: for (Point2D [] splA: splAs) { sascha@1794: Arrays.sort(splA, POINT_X_CMP); sascha@1794: } sascha@1794: sascha@1794: for (Point2D [] splB: splBs) { sascha@1794: Arrays.sort(splB, POINT_X_CMP); sascha@1794: } sascha@1794: sascha@1794: // Now sort all parts by there first elements. sascha@1794: // Should be good enough to find overlapping regions. sascha@1794: Collections.sort(splAs, FIRST_POINT_X); sascha@1794: Collections.sort(splBs, FIRST_POINT_X); sascha@1794: sascha@1794: // Check if the two series intersect at all. sascha@1794: // If no then there will be no area between them. sascha@1794: sascha@1794: Point2D [] p1 = splAs.get(0); sascha@1794: Point2D [] p2 = splBs.get(splBs.size()-1); sascha@1794: sascha@1794: // First of As greater than last of Bs. sascha@1794: if (POINT_X_CMP.compare(p1[0], p2[p2.length-1]) > 0) { sascha@1794: return; sascha@1794: } sascha@1794: sascha@1794: p2 = splAs.get(splAs.size()-1); sascha@1794: p1 = splBs.get(0); sascha@1794: sascha@1794: // First of Bs greater than last of As. sascha@1794: if (POINT_X_CMP.compare(p1[0], p2[p2.length-1]) > 0) { sascha@1794: return; sascha@1794: } sascha@1794: sascha@1794: // TODO: Intersect/split the two series parts. sascha@1794: sascha@1794: } sascha@1794: } sascha@1794: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :