view flys-artifacts/src/main/java/de/intevation/flys/artifacts/geom/Polygon2D.java @ 1794:2ad7ba85a2b3

Work in progress: Added polygon to help creating 'Raum/Flaeche' renderers. flys-artifacts/trunk@3117 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Fri, 28 Oct 2011 16:59:03 +0000
parents
children fe7f9264a2ed
line wrap: on
line source
package de.intevation.flys.geom;

import gnu.trove.TDoubleArrayList;

import java.io.Serializable;

import java.awt.Shape;

import java.awt.geom.Path2D;
import java.awt.geom.Point2D;

import java.util.ArrayList;
import java.util.List;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Collections;

public class Polygon2D
implements   Serializable
{
    public static final Comparator<Point2D> POINT_X_CMP =
        new Comparator<Point2D>() {
            public int compare(Point2D a, Point2D b) {
                double d = a.getX() - b.getX();
                if (d < 0d) return -1;
                return d > 0d ? + 1 : 0;
            }
        };

    public static final Comparator<Point2D []> FIRST_POINT_X =
        new Comparator<Point2D []>() {
            public int compare(Point2D [] a, Point2D [] b) {
                if (a.length == 0) return -1; // should not happen.
                if (b.length == 0) return +1; // should not happen.
                double d = a[0].getX() - b[0].getX();
                if (d < 0d) return -1;
                return d > 0d ? + 1 : 0;
            }
        };

    protected TDoubleArrayList xs;
    protected TDoubleArrayList ys;

    public Polygon2D() {
        xs = new TDoubleArrayList();
        ys = new TDoubleArrayList();
    }

    public void add(double x, double y) {
        xs.add(x);
        ys.add(y);
    }

    public double area() {
        double area = 0d;

		for (int i = 0, N = xs.size(); i < N; ++i) {
			int j = (i + 1) % N;
			area += xs.getQuick(i)*ys.getQuick(j);
			area -= xs.getQuick(j)*ys.getQuick(i);
		}

        return 0.5d*area;
    }

    public Shape toShape() {
        Path2D.Double path = new Path2D.Double();

        int N = xs.size();

        if (N > 0) {
            path.moveTo(xs.getQuick(0), ys.getQuick(0));
            for (int i = 1; i < N; ++i) {
                path.lineTo(xs.getQuick(i), ys.getQuick(i));
            }
            path.closePath();
        }

        return path;
    }

    protected static List<Point2D []> splitByNaNs(
        double [] xs,
        double [] ys
    ) {
        List<Point2D []> parts = new ArrayList<Point2D []>();

        List<Point2D> tmp = new ArrayList<Point2D>(xs.length);

        for (int i = 0; i < xs.length; ++i) {
            double x = xs[i];
            double y = ys[i];

            if (Double.isNaN(x) || Double.isNaN(y)) {
                if (!tmp.isEmpty()) {
                    Point2D [] part = new Point2D[tmp.size()];
                    parts.add(tmp.toArray(part));
                    tmp.clear();
                }
            }
            else {
                tmp.add(new Point2D.Double(x, y));
            }
        }

        if (!tmp.isEmpty()) {
            Point2D [] part = new Point2D[tmp.size()];
            parts.add(tmp.toArray(part));
        }

        return parts;
    }

    public static void createPolygons(
        double [] xAs, double [] yAs,
        double [] xBs, double [] yBs,
        List<Polygon2D> positives,
        List<Polygon2D> negatives
    ) {
        if (xAs.length == 0 || xBs.length == 0) {
            return;
        }

        List<Point2D []> splAs = splitByNaNs(xAs, yAs);
        List<Point2D []> splBs = splitByNaNs(xBs, yBs);

        // They feeded us with NaNs only.
        if (splAs.isEmpty() || splBs.isEmpty()) {
            return;
        }

        // Sort each part by x to ensure that the first
        // is the smallest.
        for (Point2D [] splA: splAs) {
            Arrays.sort(splA, POINT_X_CMP);
        }

        for (Point2D [] splB: splBs) {
            Arrays.sort(splB, POINT_X_CMP);
        }

        // Now sort all parts by there first elements.
        // Should be good enough to find overlapping regions.
        Collections.sort(splAs, FIRST_POINT_X);
        Collections.sort(splBs, FIRST_POINT_X);

        // Check if the two series intersect at all.
        // If no then there will be no area between them.

        Point2D [] p1 = splAs.get(0);
        Point2D [] p2 = splBs.get(splBs.size()-1);

        // First of As greater than last of Bs.
        if (POINT_X_CMP.compare(p1[0], p2[p2.length-1]) > 0) {
            return;
        }

        p2 = splAs.get(splAs.size()-1);
        p1 = splBs.get(0);

        //  First of Bs greater than last of As.
        if (POINT_X_CMP.compare(p1[0], p2[p2.length-1]) > 0) {
            return;
        }

        // TODO: Intersect/split the two series parts.

    }
}
// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org