Class RandomPointsBuilder

  1 /*
  2  * Copyright (c) 2016 Martin Davis.
  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  
 13 package org.locationtech.jts.shape.random;
 14  
 15 import org.locationtech.jts.algorithm.locate.IndexedPointInAreaLocator;
 16 import org.locationtech.jts.algorithm.locate.PointOnGeometryLocator;
 17 import org.locationtech.jts.geom.Coordinate;
 18 import org.locationtech.jts.geom.Envelope;
 19 import org.locationtech.jts.geom.Geometry;
 20 import org.locationtech.jts.geom.GeometryFactory;
 21 import org.locationtech.jts.geom.Location;
 22 import org.locationtech.jts.geom.Polygonal;
 23 import org.locationtech.jts.shape.GeometricShapeBuilder;
 24  
 25 /**
 26  * Creates random point sets contained in a 
 27  * region defined by either a rectangular or a polygonal extent. 
 28  * 
 29  * @author mbdavis
 30  *
 31  */
 32 public class RandomPointsBuilder 
 33 extends GeometricShapeBuilder
 34 {
 35   protected Geometry maskPoly = null;
 36   private PointOnGeometryLocator extentLocator;
 37  
 38   /**
 39    * Create a shape factory which will create shapes using the default
 40    * {@link GeometryFactory}.
 41    */
 42   public RandomPointsBuilder()
 43   {
 44     super(new GeometryFactory());
 45   }
 46  
 47   /**
 48    * Create a shape factory which will create shapes using the given
 49    * {@link GeometryFactory}.
 50    *
 51    * @param geomFact the factory to use
 52    */
 53   public RandomPointsBuilder(GeometryFactory geomFact)
 54   {
 55       super(geomFact);
 56   }
 57  
 58   /**
 59    * Sets a polygonal mask.
 60    * 
 61    * @param mask
 62    * @throws IllegalArgumentException if the mask is not polygonal
 63    */
 64   public void setExtent(Geometry mask)
 65   {
 66       if (! (mask instanceof Polygonal))
 67           throw new IllegalArgumentException("Only polygonal extents are supported");
 68       this.maskPoly = mask;
 69       setExtent(mask.getEnvelopeInternal());
 70       extentLocator = new IndexedPointInAreaLocator(mask);
 71   }
 72   
 73   public Geometry getGeometry()
 74   {
 75       Coordinate[] pts = new Coordinate[numPts];
 76       int i = 0;
 77       while (i < numPts) {
 78           Coordinate p = createRandomCoord(getExtent());
 79           if (extentLocator != null && ! isInExtent(p))
 80               continue;
 81           pts[i++] = p;
 82       }
 83       return geomFactory.createMultiPointFromCoords(pts);
 84   }
 85   
 86   protected boolean isInExtent(Coordinate p)
 87   {
 88       if (extentLocator != null
 89           return extentLocator.locate(p) != Location.EXTERIOR;
 90       return getExtent().contains(p);
 91   }
 92   
 93   protected Coordinate createCoord(double x, double y)
 94   {
 95       Coordinate pt = new Coordinate(x, y);
 96       geomFactory.getPrecisionModel().makePrecise(pt);
 97     return pt;
 98   }
 99   
100   protected Coordinate createRandomCoord(Envelope env)
101   {
102     double x = env.getMinX() + env.getWidth() * Math.random();
103     double y = env.getMinY() + env.getHeight() * Math.random();
104     return createCoord(x, y);
105   }
106  
107 }
108