| 1 |
|
| 2 |
|
| 3 |
|
| 4 |
|
| 5 |
|
| 6 |
|
| 7 |
|
| 8 |
|
| 9 |
|
| 10 |
|
| 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 |
|