/* File SimplePolygon2D.java 
 *
 * Project : Java Geometry Library
 *
 * ===========================================
 * 
 * This library is free software; you can redistribute it and/or modify it 
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 2.1 of the License, or (at
 * your option) any later version.
 *
 * This library is distributed in the hope that it will be useful, but 
 * WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.
 *
 * See the GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library. if not, write to :
 * The Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 * Boston, MA 02111-1307, USA.
 */

// package

package math.geom2d.polygon;

// Imports
import java.awt.Graphics2D;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import math.geom2d.AffineTransform2D;
import math.geom2d.Box2D;
import math.geom2d.GeometricObject2D;
import math.geom2d.Point2D;
import math.geom2d.circulinear.*;
import math.geom2d.line.LineSegment2D;
import math.geom2d.point.PointSets2D;
import math.geom2d.transform.CircleInversion2D;

/**
 * Represent a polygonal domain whose boundary is a single closed polyline.
 */
public class SimplePolygon2D implements Polygon2D {

    // ===================================================================
    // Static constructors
    
    /**
     * Static factory for creating a new SimplePolygon2D from a collection of
     * points.
     * @since 0.8.1
     */
    public static SimplePolygon2D create(Collection points) {
    	return new SimplePolygon2D(points);
    }
    
    /**
     * Static factory for creating a new SimplePolygon2D from an array of
     * points.
     * @since 0.8.1
     */
    public static SimplePolygon2D create(Point2D... points) {
    	return new SimplePolygon2D(points);
    }
    

    // ===================================================================
    // class variables

    /**
     * The inner ordered list of vertices. The last point is connected to the
     * first one.
     */
    protected ArrayList vertices;

    // ===================================================================
    // constructors

    /**
     * Empty constructor: no vertex.
     */
    public SimplePolygon2D() {
    	vertices = new ArrayList();
    }

    /**
     * Constructor from an array of points
     * 
     * @param vertices the vertices stored in an array of Point2D
     */
    public SimplePolygon2D(Point2D... vertices) {
        this.vertices = new ArrayList(vertices.length);
        for (Point2D vertex : vertices)
            this.vertices.add(vertex);
    }

	/**
	 * Constructor from two arrays, one for each coordinate.
	 * 
	 * @param xcoords
	 *            the x coordinate of each vertex
	 * @param ycoords
	 *            the y coordinate of each vertex
	 */
	public SimplePolygon2D(double[] xcoords, double[] ycoords) {
		vertices = new ArrayList(xcoords.length);
		for (int i = 0; i < xcoords.length; i++)
			vertices.add(new Point2D(xcoords[i], ycoords[i]));
	}

	public SimplePolygon2D(Collection points) {
		this.vertices = new ArrayList(points.size());
		this.vertices.addAll(points);
	}

	/**
	 * Ensure the polygon has enough memory for storing the required number of
	 * vertices.
	 */
	public SimplePolygon2D(int nVertices) {
    	vertices = new ArrayList(nVertices);
    }
	
    /**
     * Creates a simple polygon with the given linear ring representing its
     * boundary.
     * @param ring the boundary of the polygon
     */
    public SimplePolygon2D(LinearRing2D ring) {
        this.vertices = new ArrayList(ring.vertexNumber());
        this.vertices.addAll(ring.vertices());
    }

    public SimplePolygon2D(SimplePolygon2D poly) {
    	this.vertices = new ArrayList(poly.vertexNumber());
    	this.vertices.addAll(poly.vertices);
    }
    
    // ===================================================================
    // methods specific to SimplePolygon2D

    /**
     * Computes the winding number of the polygon. Algorithm adapted from
     * http://www.geometryalgorithms.com/Archive/algorithm_0103/algorithm_0103.htm
     * 
     * @param x the x-coordinate of the point
     * @param y the y-coordinate of the point
     * @return the number of windings of the curve around the point
     */
    public int getWindingNumber(double x, double y) {
        return Polygons2D.windingNumber(vertices, new Point2D(x, y));
    }
        
    /**
     * Returns a simplified version of this polygon, by using Douglas-Peucker
     * algorithm.
     */
	public SimplePolygon2D simplify(double distMax) {
		return new SimplePolygon2D(Polylines2D.simplifyClosedPolyline(this.vertices, distMax));
	}
	
	/**
     * Returns the linear ring that composes the boundary of this polygon.
     * @since 0.9.3
     */
    public LinearRing2D getRing() {
    	return new LinearRing2D(this.vertices);
    }
    
    // ===================================================================
    // management of vertex list

    /**
     * Adds a point as the last vertex.
     */
    public void addVertex(Point2D point) {
        this.vertices.add(point);
    }

    /**
     * Adds a point as the last vertex.
     * @since 0.9.3
     */
    public void insertVertex(int index, Point2D point) {
        this.vertices.add(index, point);
    }

    /**
	 * Changes the position of the i-th vertex.
	 */
	public void setVertex(int index, Point2D position) {
	    this.vertices.set(index, position);
	}

	/**
     * Removes a vertex of the polygon.
     * 
     * @param point the vertex to be removed.
     */
    public boolean removeVertex(Point2D point) {
        return this.vertices.remove(point);
    }

    /**
     * Removes a vertex of the polygon specified by its index.
     * @since 0.9.3
     */
    public void removeVertex(int index) {
        this.vertices.remove(index);
    }

    /**
     * Removes all the vertices of the polygon.
     */
    public void clearVertices() {
        this.vertices.clear();
    }
    
    /**
     * Computes the index of the closest vertex to the input point.
     */
    public int closestVertexIndex(Point2D point) {
    	double minDist = Double.POSITIVE_INFINITY;
    	int index = -1;
    	
    	for (int i = 0; i < vertices.size(); i++) {
    		double dist = vertices.get(i).distance(point);
    		if (dist < minDist) {
    			index = i;
    			minDist = dist;
    		}
    	}
    	
    	return index;
    }
    
    /**
     * Computes the signed area of the polygon. Algorithm is taken from page: 
     * http://local.wasp.uwa.edu.au/~pbourke/geometry/polyarea/. Signed are
     * is positive if polygon is oriented counter-clockwise, and negative
     * otherwise. Result is wrong if polygon is self-intersecting.
     * 
     * @return the signed area of the polygon.
     */
    public double area() {
    	return Polygons2D.computeArea(this);
    }

    /**
     * Computes the centroid (center of mass) of the polygon. Algorithm is taken
     * from page: 
     * http://local.wasp.uwa.edu.au/~pbourke/geometry/polyarea/.
     * 
     * @return the centroid of the polygon
     */
    public Point2D centroid() {
    	return Polygons2D.computeCentroid(this);
    }

    /**
     * Returns the points of the polygon. The result is a pointer to the inner
     * collection of vertices.
     */
    public Collection vertices() {
        return vertices;
    }

    /**
     * Returns the i-th vertex of the polygon.
     * 
     * @param i index of the vertex, between 0 and the number of vertices
     */
    public Point2D vertex(int i) {
        return vertices.get(i);
    }

    /**
     * Returns the number of vertices of the polygon.
     * 
     * @since 0.6.3
     */
    public int vertexNumber() {
        return vertices.size();
    }

    /**
     * Returns the set of edges, as a collection of LineSegment2D.
     */
    public Collection edges() {

        int nPoints = this.vertices.size();
        ArrayList edges = new ArrayList(nPoints);

        if (nPoints==0)
            return edges;

        for (int i = 0; i pts2 = 
				PointSets2D.filterMultipleVertices(this.vertices, true);
			SimplePolygon2D poly2 = new SimplePolygon2D(pts2);
	    	return CirculinearDomains2D.computeBuffer(poly2, dist);
		}
		
		// 
		return CirculinearDomains2D.computeBuffer(this, dist);
	}

	// ===================================================================
    // methods inherited from Domain2D interface

	/* (non-Javadoc)
	 * @see math.geom2d.domain.Domain2D#asPolygon(int)
	 */
	public Polygon2D asPolygon(int n) {
		return this;
	}

    /**
     * Returns a set of one LinearRing2D, which encloses the polygon.
     */
    public CirculinearContourArray2D boundary() {
        Point2D[] array = new Point2D[this.vertices.size()];
        for (int i = 0; i(
        		new LinearRing2D(array));
    }

	/* (non-Javadoc)
	 * @see math.geom2d.domain.Domain2D#contours()
	 */
	public Collection contours() {
        ArrayList rings = new ArrayList(1);
        rings.add(new LinearRing2D(vertices));
        return rings;
	}

    /**
     * Returns the polygon created by reversing the order of the vertices.
     */
    public SimplePolygon2D complement() {
        int nPoints = this.vertices.size();

        Point2D[] res = new Point2D[nPoints];

        if (nPoints>0)
            res[0] = this.vertices.get(0);

        for (int i = 1; i0;
    }

    public boolean isEmpty() {
        return vertices.size() == 0;
    }

    /**
     * Returns the new Polygon created by an affine transform of this polygon.
     * If the transform is not direct, the order of vertices is reversed.
     */
    public SimplePolygon2D transform(AffineTransform2D trans) {
        int nPoints = this.vertices.size();

        Point2D[] array = new Point2D[nPoints];
        Point2D[] res = new Point2D[nPoints];

		for (int i = 0; i < nPoints; i++) {
			array[i] = this.vertices.get(i);
            res[i] = new Point2D();
        }
        trans.transform(array, res);

        SimplePolygon2D poly = new SimplePolygon2D(res);
        if (!trans.isDirect())
            poly = poly.complement();

        return poly;
    }

    // ===================================================================
    // methods inherited from Shape interface

    /**
     * Returns true if the point p lies inside the polygon, with precision
     * given by Shape2D.ACCURACY.
     */
    public boolean contains(Point2D p) {
        return contains(p.x(), p.y());
    }

    /**
     * Returns true if the point (x, y) lies inside the polygon, with precision
     * given by Shape2D.ACCURACY.
     */
    public boolean contains(double x, double y) {
    	if (this.boundary().contains(x, y))
    		return true;
    	
    	double area = this.area();
    	int winding = this.getWindingNumber(x, y);
    	if (area > 0) {
    		return winding == 1;
    	} else {
    		return winding == 0;
    	}
    }

    /**
     * Returns a general path iterator.
     */
    public java.awt.geom.GeneralPath getGeneralPath() {
        java.awt.geom.GeneralPath path = new java.awt.geom.GeneralPath();
		if (vertices.size() < 2)
			return path;

        // move to first point
        Point2D point = vertices.get(0);
        path.moveTo((float) (point.x()), (float) (point.y()));

        // line to each point
        for (int i = 0; i array = new ArrayList(vertices.size());
        for(Point2D point : vertices)
            array.add(point);
        return new SimplePolygon2D(array);
    }

}
 

Ads help maintain this website.