Class PolygonShape

  1 /*
  2  * Copyright (c) 2016 Vivid Solutions.
  3  *
  4  * All rights reserved. This program and the accompanying materials
  5  * are made available under the terms of the Eclipse Public License 2.0
  6  * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
  7  * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v20.html
  8  * and the Eclipse Distribution License is available at
  9  *
 10  * http://www.eclipse.org/org/documents/edl-v10.php.
 11  */
 12 package org.locationtech.jts.awt;
 13  
 14 import java.awt.Rectangle;
 15 import java.awt.Shape;
 16 import java.awt.geom.AffineTransform;
 17 import java.awt.geom.GeneralPath;
 18 import java.awt.geom.PathIterator;
 19 import java.awt.geom.Point2D;
 20 import java.awt.geom.Rectangle2D;
 21 import java.util.Collection;
 22 import java.util.Iterator;
 23  
 24 import org.locationtech.jts.geom.Coordinate;
 25  
 26  
 27 /**
 28  * A {@link Shape} which represents a polygon which may contain holes.
 29  * Provided because the standard AWT Polygon class does not support holes.
 30  * 
 31  * @author Martin Davis
 32  *
 33  */
 34 public class PolygonShape implements Shape 
 35 {
 36   // use a GeneralPath with a winding rule, since it supports floating point coordinates
 37     private GeneralPath polygonPath;
 38     private GeneralPath ringPath;
 39     
 40     /**
 41      * Creates a new polygon {@link Shape}.
 42      * 
 43      * @param shellVertices the vertices of the shell 
 44      * @param holeVerticesCollection a collection of Coordinate[] for each hole
 45      */
 46     public PolygonShape(Coordinate[] shellVertices,
 47         Collection holeVerticesCollection) 
 48     {
 49         polygonPath = toPath(shellVertices);
 50  
 51         for (Iterator i = holeVerticesCollection.iterator(); i.hasNext();) {
 52             Coordinate[] holeVertices = (Coordinate[]) i.next();
 53             polygonPath.append(toPath(holeVertices), false);
 54         }
 55     }
 56  
 57     public PolygonShape() 
 58     {
 59     }
 60  
 61     void addToRing(Point2D p)
 62     {
 63         if (ringPath == null) {
 64             ringPath = new GeneralPath(GeneralPath.WIND_EVEN_ODD);
 65             ringPath.moveTo((float) p.getX(), (float) p.getY());
 66         }
 67         else {
 68             ringPath.lineTo((float) p.getX(), (float) p.getY());
 69         }
 70     }
 71     
 72     void endRing()
 73     {
 74       ringPath.closePath();
 75         if (polygonPath == null) {
 76             polygonPath = ringPath;
 77         }
 78         else {
 79             polygonPath.append(ringPath, false);
 80         }
 81         ringPath = null;
 82     }
 83     
 84     /**
 85      * Creates a GeneralPath representing a polygon ring 
 86      * having the given coordinate sequence.
 87      * Uses the GeneralPath.WIND_EVEN_ODD winding rule.
 88      * 
 89      * @param coordinates a coordinate sequence
 90      * @return the path for the coordinate sequence
 91      */
 92     private GeneralPath toPath(Coordinate[] coordinates) {
 93       GeneralPath path = new GeneralPath(GeneralPath.WIND_EVEN_ODD, coordinates.length);
 94  
 95       if (coordinates.length > 0) {
 96         path.moveTo((float) coordinates[0].x, (float) coordinates[0].y);
 97         for (int i = 0; i < coordinates.length; i++) {
 98           path.lineTo((float) coordinates[i].x, (float) coordinates[i].y);
 99         }
100       }
101       return path;
102   }
103  
104     public Rectangle getBounds() {
105       return polygonPath.getBounds();
106     }
107  
108     public Rectangle2D getBounds2D() {
109         return polygonPath.getBounds2D();
110     }
111  
112     public boolean contains(double x, double y) {
113       return polygonPath.contains(x, y);
114     }
115  
116     public boolean contains(Point2D p) {
117       return polygonPath.contains(p);
118     }
119  
120     public boolean intersects(double x, double y, double w, double h) {
121       return polygonPath.intersects(x, y, w, h);
122     }
123  
124     public boolean intersects(Rectangle2D r) {
125       return polygonPath.intersects(r);
126     }
127  
128     public boolean contains(double x, double y, double w, double h) {
129       return polygonPath.contains(x, y, w, h);
130     }
131  
132     public boolean contains(Rectangle2D r) {
133       return polygonPath.contains(r);
134     }
135  
136     public PathIterator getPathIterator(AffineTransform at) {
137         return polygonPath.getPathIterator(at);
138     }
139  
140     public PathIterator getPathIterator(AffineTransform at, double flatness) {
141         return polygonPath.getPathIterator(at, flatness);
142     }
143 }
144