Class PreparedPolygon

  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.geom.prep;
 13  
 14  
 15 import org.locationtech.jts.algorithm.locate.IndexedPointInAreaLocator;
 16 import org.locationtech.jts.algorithm.locate.PointOnGeometryLocator;
 17 import org.locationtech.jts.geom.Geometry;
 18 import org.locationtech.jts.geom.MultiPolygon;
 19 import org.locationtech.jts.geom.Polygon;
 20 import org.locationtech.jts.geom.Polygonal;
 21 import org.locationtech.jts.noding.FastSegmentSetIntersectionFinder;
 22 import org.locationtech.jts.noding.SegmentStringUtil;
 23 import org.locationtech.jts.operation.predicate.RectangleContains;
 24 import org.locationtech.jts.operation.predicate.RectangleIntersects;
 25  
 26 /**
 27  * A prepared version for {@link Polygonal} geometries.
 28  * This class supports both {@link Polygon}s and {@link MultiPolygon}s.
 29  * <p>
 30  * This class does <b>not</b> support MultiPolygons which are non-valid 
 31  * (e.g. with overlapping elements). 
 32  * <p>
 33  * Instances of this class are thread-safe and immutable.
 34  * 
 35  * @author mbdavis
 36  *
 37  */
 38 public class PreparedPolygon
 39   extends BasicPreparedGeometry
 40 {
 41     private final boolean isRectangle;
 42     // create these lazily, since they are expensive
 43     private FastSegmentSetIntersectionFinder segIntFinder = null;
 44     private PointOnGeometryLocator pia = null;
 45  
 46   public PreparedPolygon(Polygonal poly) {
 47     super((Geometry) poly);
 48     isRectangle = getGeometry().isRectangle();
 49   }
 50  
 51   /**
 52    * Gets the indexed intersection finder for this geometry.
 53    * 
 54    * @return the intersection finder
 55    */
 56   public synchronized FastSegmentSetIntersectionFinder getIntersectionFinder()
 57   {
 58       /**
 59        * MD - Another option would be to use a simple scan for 
 60        * segment testing for small geometries.  
 61        * However, testing indicates that there is no particular advantage 
 62        * to this approach.
 63        */
 64       if (segIntFinder == null)
 65           segIntFinder = new FastSegmentSetIntersectionFinder(SegmentStringUtil.extractSegmentStrings(getGeometry()));
 66       return segIntFinder;
 67   }
 68   
 69   public synchronized PointOnGeometryLocator getPointLocator()
 70   {
 71       if (pia == null)
 72       pia = new IndexedPointInAreaLocator(getGeometry());
 73          
 74     return pia;
 75   }
 76   
 77   public boolean intersects(Geometry g)
 78   {
 79       // envelope test
 80       if (! envelopesIntersect(g)) return false;
 81       
 82     // optimization for rectangles
 83     if (isRectangle) {
 84       return RectangleIntersects.intersects((Polygon) getGeometry(), g);
 85     }
 86     
 87     return PreparedPolygonIntersects.intersects(this, g);
 88   }
 89   
 90   public boolean contains(Geometry g)
 91   {
 92     // short-circuit test
 93     if (! envelopeCovers(g)) 
 94         return false;
 95       
 96     // optimization for rectangles
 97     if (isRectangle) {
 98       return RectangleContains.contains((Polygon) getGeometry(), g);
 99     }
100  
101     return PreparedPolygonContains.contains(this, g);
102   }
103   
104   public boolean containsProperly(Geometry g)
105   {
106     // short-circuit test
107     if (! envelopeCovers(g)) 
108         return false;
109     return PreparedPolygonContainsProperly.containsProperly(this, g);
110   }
111   
112   public boolean covers(Geometry g)
113   {
114     // short-circuit test
115     if (! envelopeCovers(g)) 
116         return false;
117     // optimization for rectangle arguments
118     if (isRectangle) {
119       return true;
120     }
121     return PreparedPolygonCovers.covers(this, g);
122   }
123 }
124