Class InteriorPointLine

  1  
  2 /*
  3  * Copyright (c) 2016 Vivid Solutions.
  4  *
  5  * All rights reserved. This program and the accompanying materials
  6  * are made available under the terms of the Eclipse Public License 2.0
  7  * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
  8  * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v20.html
  9  * and the Eclipse Distribution License is available at
 10  *
 11  * http://www.eclipse.org/org/documents/edl-v10.php.
 12  */
 13 package org.locationtech.jts.algorithm;
 14  
 15 import org.locationtech.jts.geom.Coordinate;
 16 import org.locationtech.jts.geom.Geometry;
 17 import org.locationtech.jts.geom.GeometryCollection;
 18 import org.locationtech.jts.geom.LineString;
 19  
 20 /**
 21  * Computes a point in the interior of an linear geometry.
 22  * <h2>Algorithm</h2>
 23  * <ul>
 24  * <li>Find an interior vertex which is closest to
 25  * the centroid of the linestring.
 26  * <li>If there is no interior vertex, find the endpoint which is
 27  * closest to the centroid.
 28  * </ul>
 29  *
 30  * @version 1.7
 31  */
 32 public class InteriorPointLine {
 33   
 34   /**
 35    * Computes an interior point for the
 36    * linear components of a Geometry.
 37    * 
 38    * @param geom the geometry to compute
 39    * @return the computed interior point,
 40    * or <code>null</code> if the geometry has no linear components
 41    */
 42   public static Coordinate getInteriorPoint(Geometry geom) {
 43     InteriorPointLine intPt = new InteriorPointLine(geom);
 44     return intPt.getInteriorPoint();
 45   }
 46   
 47   private Coordinate centroid;
 48   private double minDistance = Double.MAX_VALUE;
 49  
 50   private Coordinate interiorPoint = null;
 51  
 52   public InteriorPointLine(Geometry g)
 53   {
 54     centroid = g.getCentroid().getCoordinate();
 55     addInterior(g);
 56     if (interiorPoint == null)
 57       addEndpoints(g);
 58   }
 59  
 60   public Coordinate getInteriorPoint()
 61   {
 62     return interiorPoint;
 63   }
 64  
 65   /**
 66    * Tests the interior vertices (if any)
 67    * defined by a linear Geometry for the best inside point.
 68    * If a Geometry is not of dimension 1 it is not tested.
 69    * @param geom the geometry to add
 70    */
 71   private void addInterior(Geometry geom)
 72   {
 73     if (geom instanceof LineString) {
 74       addInterior(geom.getCoordinates());
 75     }
 76     else if (geom instanceof GeometryCollection) {
 77       GeometryCollection gc = (GeometryCollection) geom;
 78       for (int i = 0; i < gc.getNumGeometries(); i++) {
 79         addInterior(gc.getGeometryN(i));
 80       }
 81     }
 82   }
 83   private void addInterior(Coordinate[] pts)
 84   {
 85     for (int i = 1; i < pts.length - 1; i++) {
 86       add(pts[i]);
 87     }
 88   }
 89   /**
 90    * Tests the endpoint vertices
 91    * defined by a linear Geometry for the best inside point.
 92    * If a Geometry is not of dimension 1 it is not tested.
 93    * @param geom the geometry to add
 94    */
 95   private void addEndpoints(Geometry geom)
 96   {
 97     if (geom instanceof LineString) {
 98       addEndpoints(geom.getCoordinates());
 99     }
100     else if (geom instanceof GeometryCollection) {
101       GeometryCollection gc = (GeometryCollection) geom;
102       for (int i = 0; i < gc.getNumGeometries(); i++) {
103         addEndpoints(gc.getGeometryN(i));
104       }
105     }
106   }
107   private void addEndpoints(Coordinate[] pts)
108   {
109     add(pts[0]);
110     add(pts[pts.length - 1]);
111   }
112  
113   private void add(Coordinate point)
114   {
115     double dist = point.distance(centroid);
116     if (dist < minDistance) {
117       interiorPoint = new Coordinate(point);
118       minDistance = dist;
119     }
120   }
121  
122 }
123