Class LocationIndexedLine

  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  
 13 package org.locationtech.jts.linearref;
 14  
 15 import org.locationtech.jts.geom.Coordinate;
 16 import org.locationtech.jts.geom.Geometry;
 17 import org.locationtech.jts.geom.LineString;
 18 import org.locationtech.jts.geom.MultiLineString;
 19  
 20 /**
 21  * Supports linear referencing
 22  * along a linear {@link Geometry}
 23  * using {@link LinearLocation}s as the index.
 24  */
 25 public class LocationIndexedLine
 26 {
 27   private Geometry linearGeom;
 28  
 29   /**
 30    * Constructs an object which allows linear referencing along
 31    * a given linear {@link Geometry}.
 32    *
 33    * @param linearGeom the linear geometry to reference along
 34    */
 35   public LocationIndexedLine(Geometry linearGeom)
 36   {
 37     this.linearGeom = linearGeom;
 38     checkGeometryType();
 39   }
 40  
 41   private void checkGeometryType()
 42   {
 43     if (! (linearGeom instanceof LineString || linearGeom instanceof MultiLineString))
 44       throw new IllegalArgumentException("Input geometry must be linear");
 45   }
 46   /**
 47    * Computes the {@link Coordinate} for the point
 48    * on the line at the given index.
 49    * If the index is out of range the first or last point on the
 50    * line will be returned.
 51    * The Z-ordinate of the computed point will be interpolated from
 52    * the Z-ordinates of the line segment containing it, if they exist.
 53    *
 54    * @param index the index of the desired point
 55    * @return the Coordinate at the given index
 56    */
 57   public Coordinate extractPoint(LinearLocation index)
 58   {
 59     return index.getCoordinate(linearGeom);
 60   }
 61  
 62   /**
 63    * Computes the {@link Coordinate} for the point
 64    * on the line at the given index, offset by the given distance.
 65    * If the index is out of range the first or last point on the
 66    * line will be returned.
 67    * The computed point is offset to the left of the line if the offset distance is
 68    * positive, to the right if negative.
 69    * 
 70    * The Z-ordinate of the computed point will be interpolated from
 71    * the Z-ordinates of the line segment containing it, if they exist.
 72    *
 73    * @param index the index of the desired point
 74    * @param offsetDistance the distance the point is offset from the segment
 75    *    (positive is to the left, negative is to the right)
 76    * @return the Coordinate at the given index
 77    */
 78   public Coordinate extractPoint(LinearLocation index, double offsetDistance)
 79   {
 80     LinearLocation indexLow = index.toLowest(linearGeom);
 81     return indexLow.getSegment(linearGeom).pointAlongOffset(indexLow.getSegmentFraction(), offsetDistance);
 82   }
 83  
 84   /**
 85    * Computes the {@link LineString} for the interval
 86    * on the line between the given indices.
 87    * If the start location is after the end location,
 88    * the computed linear geometry has reverse orientation to the input line.
 89    *
 90    * @param startIndex the index of the start of the interval
 91    * @param endIndex the index of the end of the interval
 92    * @return the linear geometry between the indices
 93    */
 94   public Geometry extractLine(LinearLocation startIndex, LinearLocation endIndex)
 95   {
 96     return ExtractLineByLocation.extract(linearGeom, startIndex, endIndex);
 97   }
 98  
 99   /**
100    * Computes the index for a given point on the line.
101    * <p>
102    * The supplied point does not <i>necessarily</i> have to lie precisely
103    * on the line, but if it is far from the line the accuracy and
104    * performance of this function is not guaranteed.
105    * Use {@link #project} to compute a guaranteed result for points
106    * which may be far from the line.
107    *
108    * @param pt a point on the line
109    * @return the index of the point
110    * @see #project(Coordinate)
111    */
112   public LinearLocation indexOf(Coordinate pt)
113   {
114     return LocationIndexOfPoint.indexOf(linearGeom, pt);
115   }
116   
117   /**
118    * Finds the index for a point on the line
119    * which is greater than the given index.
120    * If no such index exists, returns <tt>minIndex</tt>.
121    * This method can be used to determine all indexes for
122    * a point which occurs more than once on a non-simple line.
123    * It can also be used to disambiguate cases where the given point lies
124    * slightly off the line and is equidistant from two different
125    * points on the line.
126    *
127    * The supplied point does not <i>necessarily</i> have to lie precisely
128    * on the line, but if it is far from the line the accuracy and
129    * performance of this function is not guaranteed.
130    * Use {@link #project} to compute a guaranteed result for points
131    * which may be far from the line.
132    *
133    * @param pt a point on the line
134    * @param minIndex the value the returned index must be greater than
135    * @return the index of the point greater than the given minimum index
136    *
137    * @see #project(Coordinate)
138    */
139   public LinearLocation indexOfAfter(Coordinate pt, LinearLocation minIndex)
140   {
141     return LocationIndexOfPoint.indexOfAfter(linearGeom, pt, minIndex);
142   }
143  
144  
145   /**
146    * Computes the indices for a subline of the line.
147    * (The subline must <i>conform</i> to the line; that is,
148    * all vertices in the subline (except possibly the first and last)
149    * must be vertices of the line and occur in the same order).
150    *
151    * @param subLine a subLine of the line
152    * @return a pair of indices for the start and end of the subline.
153    */
154   public LinearLocation[] indicesOf(Geometry subLine)
155   {
156     return LocationIndexOfLine.indicesOf(linearGeom, subLine);
157   }
158  
159   /**
160    * Computes the index for the closest point on the line to the given point.
161    * If more than one point has the closest distance the first one along the line
162    * is returned.
163    * (The point does not necessarily have to lie precisely on the line.)
164    *
165    * @param pt a point on the line
166    * @return the index of the point
167    */
168   public LinearLocation project(Coordinate pt)
169   {
170     return LocationIndexOfPoint.indexOf(linearGeom, pt);
171   }
172  
173   /**
174    * Returns the index of the start of the line
175    * @return the location index
176    */
177   public LinearLocation getStartIndex()
178   {
179     return new LinearLocation();
180   }
181  
182   /**
183    * Returns the index of the end of the line
184    * @return the location index
185    */
186   public LinearLocation getEndIndex()
187   {
188     return LinearLocation.getEndLocation(linearGeom);
189   }
190  
191   /**
192    * Tests whether an index is in the valid index range for the line.
193    *
194    * @param index the index to test
195    * @return <code>true</code> if the index is in the valid range
196    */
197   public boolean isValidIndex(LinearLocation index)
198   {
199     return index.isValid(linearGeom);
200   }
201  
202   /**
203    * Computes a valid index for this line
204    * by clamping the given index to the valid range of index values
205    *
206    * @return a valid index value
207    */
208   public LinearLocation clampIndex(LinearLocation index)
209   {
210     LinearLocation loc = index.copy();
211     loc.clamp(linearGeom);
212     return loc;
213   }
214 }
215