1 /********************************************************************** 2 * 3 * GEOS - Geometry Engine Open Source 4 * http://geos.osgeo.org 5 * 6 * Copyright (C) 2011 Sandro Santilli <strk@kbt.io> 7 * 8 * This is free software; you can redistribute and/or modify it under 9 * the terms of the GNU Lesser General Public Licence as published 10 * by the Free Software Foundation. 11 * See the COPYING file for more information. 12 * 13 ********************************************************************** 14 * 15 * Last port: linearref/LocationIndexedLine.java r466 16 * 17 **********************************************************************/ 18 19 #ifndef GEOS_LINEARREF_LOCATIONINDEXEDLINE_H 20 #define GEOS_LINEARREF_LOCATIONINDEXEDLINE_H 21 22 #include <geos/export.h> 23 #include <geos/geom/Coordinate.h> 24 #include <geos/geom/Geometry.h> 25 #include <geos/linearref/LinearLocation.h> 26 #include <geos/linearref/LocationIndexOfPoint.h> 27 #include <geos/linearref/LocationIndexOfLine.h> 28 #include <geos/util/IllegalArgumentException.h> 29 30 namespace geos { 31 namespace linearref { // geos::linearref 32 33 /** 34 * \brief 35 * Supports linear referencing along a linear 36 * [Geometry](@ref geom::Geometry) using 37 * [LinearLocations](@ref LinearLocation) as the index. 38 */ 39 class GEOS_DLL LocationIndexedLine { 40 private: 41 const geom::Geometry* linearGeom; 42 43 void checkGeometryType()44 checkGeometryType() 45 { 46 if(!linearGeom->isLineal()) { 47 throw util::IllegalArgumentException("Input geometry must be linear"); 48 } 49 } 50 51 public: 52 53 /** 54 * \brief 55 * Constructs an object which allows linear referencing along 56 * a given linear [Geometry](@ref geom::Geometry). 57 * 58 * @param p_linearGeom the linear geometry to reference along 59 */ LocationIndexedLine(const geom::Geometry * p_linearGeom)60 LocationIndexedLine(const geom::Geometry* p_linearGeom) 61 : linearGeom(p_linearGeom) 62 { 63 checkGeometryType(); 64 } 65 66 /** 67 * \brief 68 * Computes the [Coordinate](@ref geom::Coordinate) for the point 69 * on the line at the given index. 70 * 71 * If the index is out of range the first or last point on the 72 * line will be returned. 73 * The Z-ordinate of the computed point will be interpolated from 74 * the Z-ordinates of the line segment containing it, if they exist. 75 * 76 * @param index the index of the desired point 77 * @return the Coordinate at the given index 78 */ 79 geom::Coordinate extractPoint(const LinearLocation & index)80 extractPoint(const LinearLocation& index) const 81 { 82 return index.getCoordinate(linearGeom); 83 } 84 85 86 /** 87 * \brief 88 * Computes the [Coordinate](@ref geom::Coordinate) for the point 89 * on the line at the given index, offset by the given distance. 90 * 91 * If the index is out of range the first or last point on the 92 * line will be returned. 93 * The computed point is offset to the left of the line if the offset 94 * distance is positive, to the right if negative. 95 * 96 * The Z-ordinate of the computed point will be interpolated from 97 * the Z-ordinates of the line segment containing it, if they exist. 98 * 99 * @param index the index of the desired point 100 * @param offsetDistance the distance the point is offset from the segment 101 * (positive is to the left, negative is to the right) 102 * @return the Coordinate at the given index 103 */ 104 geom::Coordinate extractPoint(const LinearLocation & index,double offsetDistance)105 extractPoint(const LinearLocation& index, 106 double offsetDistance) const 107 { 108 geom::Coordinate ret; 109 index.getSegment(linearGeom)->pointAlongOffset( 110 index.getSegmentFraction(), offsetDistance, ret 111 ); 112 return ret; 113 } 114 115 /** 116 * \brief 117 * Computes the [LineString](@ref geom::LineString) for the interval 118 * on the line between the given indices. 119 * 120 * If the endIndex lies before the startIndex, 121 * the computed geometry is reversed. 122 * 123 * @param startIndex the index of the start of the interval 124 * @param endIndex the index of the end of the interval 125 * @return the linear interval between the indices 126 */ 127 std::unique_ptr<geom::Geometry> extractLine(const LinearLocation & startIndex,const LinearLocation & endIndex)128 extractLine(const LinearLocation& startIndex, 129 const LinearLocation& endIndex) const 130 { 131 return ExtractLineByLocation::extract(linearGeom, startIndex, endIndex); 132 } 133 134 135 /** 136 * \brief 137 * Computes the index for a given point on the line. 138 * 139 * The supplied point does not <i>necessarily</i> have to lie precisely 140 * on the line, but if it is far from the line the accuracy and 141 * performance of this function is not guaranteed. 142 * Use {@link #project} to compute a guaranteed result for points 143 * which may be far from the line. 144 * 145 * @param pt a point on the line 146 * @return the index of the point 147 * 148 * @see project 149 */ 150 LinearLocation indexOf(const geom::Coordinate & pt)151 indexOf(const geom::Coordinate& pt) const 152 { 153 return LocationIndexOfPoint::indexOf(linearGeom, pt); 154 } 155 156 /** 157 * \brief 158 * Finds the index for a point on the line 159 * which is greater than the given index. 160 * 161 * If no such index exists, returns <tt>minIndex</tt>. 162 * This method can be used to determine all indexes for 163 * a point which occurs more than once on a non-simple line. 164 * It can also be used to disambiguate cases where the given point lies 165 * slightly off the line and is equidistant from two different 166 * points on the line. 167 * 168 * The supplied point does not <i>necessarily</i> have to lie precisely 169 * on the line, but if it is far from the line the accuracy and 170 * performance of this function is not guaranteed. 171 * Use {@link #project} to compute a guaranteed result for points 172 * which may be far from the line. 173 * 174 * @param pt a point on the line 175 * @param minIndex the value the returned index must be greater than 176 * @return the index of the point greater than the given minimum index 177 * 178 * @see project 179 */ 180 LinearLocation indexOfAfter(const geom::Coordinate & pt,const LinearLocation & minIndex)181 indexOfAfter(const geom::Coordinate& pt, 182 const LinearLocation& minIndex) const 183 { 184 return LocationIndexOfPoint::indexOfAfter(linearGeom, pt, &minIndex); 185 } 186 187 /** 188 * \brief 189 * Computes the indices for a subline of the line. 190 * 191 * (The subline must <b>conform</b> to the line; that is, 192 * all vertices in the subline (except possibly the first and last) 193 * must be vertices of the line and occur in the same order). 194 * 195 * @param subLine a subLine of the line 196 * @return a pair of indices for the start and end of the subline. 197 */ 198 LinearLocation* indicesOf(const geom::Geometry * subLine)199 indicesOf(const geom::Geometry* subLine) const 200 { 201 return LocationIndexOfLine::indicesOf(linearGeom, subLine); 202 } 203 204 205 /** 206 * \brief 207 * Computes the index for the closest point on the line to the given point. 208 * 209 * If more than one point has the closest distance the first one along 210 * the line is returned. 211 * (The point does not necessarily have to lie precisely on the line.) 212 * 213 * @param pt a point on the line 214 * @return the index of the point 215 */ 216 LinearLocation project(const geom::Coordinate & pt)217 project(const geom::Coordinate& pt) const 218 { 219 return LocationIndexOfPoint::indexOf(linearGeom, pt); 220 } 221 222 /** 223 * \brief 224 * Returns the index of the start of the line 225 * 226 * @return the start index 227 */ 228 LinearLocation getStartIndex()229 getStartIndex() const 230 { 231 return LinearLocation(); 232 } 233 234 /** 235 * \brief 236 * Returns the index of the end of the line 237 * 238 * @return the end index 239 */ 240 LinearLocation getEndIndex()241 getEndIndex() const 242 { 243 return LinearLocation::getEndLocation(linearGeom); 244 } 245 246 /** 247 * \brief 248 * Tests whether an index is in the valid index range for the line. 249 * 250 * @param index the index to test 251 * @return `true` if the index is in the valid range 252 */ 253 bool isValidIndex(const LinearLocation & index)254 isValidIndex(const LinearLocation& index) const 255 { 256 return index.isValid(linearGeom); 257 } 258 259 260 /** 261 * \brief 262 * Computes a valid index for this line 263 * by clamping the given index to the valid range of index values 264 * 265 * @return a valid index value 266 */ 267 LinearLocation clampIndex(const LinearLocation & index)268 clampIndex(const LinearLocation& index) const 269 { 270 LinearLocation loc = index; 271 loc.clamp(linearGeom); 272 return loc; 273 } 274 }; 275 276 } // geos::linearref 277 } // geos 278 #endif 279