1 /**********************************************************************
2  *
3  * GEOS - Geometry Engine Open Source
4  * http://geos.osgeo.org
5  *
6  * Copyright (C) 2011 Sandro Santilli <strk@kbt.io>
7  * Copyright (C) 2005-2006 Refractions Research Inc.
8  * Copyright (C) 2001-2002 Vivid Solutions Inc.
9  *
10  * This is free software; you can redistribute and/or modify it under
11  * the terms of the GNU Lesser General Public Licence as published
12  * by the Free Software Foundation.
13  * See the COPYING file for more information.
14  *
15  **********************************************************************
16  *
17  * Last port: linearref/LengthIndexedLine.java r463
18  *
19  **********************************************************************/
20 
21 #ifndef GEOS_LINEARREF_LENGTHINDEXEDLINE_H
22 #define GEOS_LINEARREF_LENGTHINDEXEDLINE_H
23 
24 #include <geos/export.h>
25 #include <geos/geom/Coordinate.h>
26 #include <geos/geom/Geometry.h>
27 #include <geos/linearref/LinearLocation.h>
28 
29 namespace geos {
30 namespace linearref { // geos::linearref
31 
32 /** \brief
33  * Supports linear referencing along a linear geom::Geometry
34  * using the length along the line as the index.
35  *
36  * Negative length values are taken as measured in the reverse direction
37  * from the end of the geometry.
38  * Out-of-range index values are handled by clamping
39  * them to the valid range of values.
40  * Non-simple lines (i.e. which loop back to cross or touch
41  * themselves) are supported.
42  */
43 
44 class GEOS_DLL LengthIndexedLine {
45 private:
46     const geom::Geometry* linearGeom;
47     LinearLocation locationOf(double index) const;
48     LinearLocation locationOf(double index, bool resolveLower) const;
49     double positiveIndex(double index) const;
50 
51 public:
52 
53     /** \brief
54      * Constructs an object which allows a linear [Geometry](@ref geom::Geometry)
55      * to be linearly referenced using length as an index.
56      *
57      * @param linearGeom the linear geometry to reference along
58      */
59 
60     LengthIndexedLine(const geom::Geometry* linearGeom);
61 
62     /** \brief
63      * Computes the [Coordinate](@ref geom::Coordinate) for the point
64      * on the line at the given index.
65      *
66      * If the index is out of range the first or last point on the
67      * line will be returned.
68      * The Z-ordinate of the computed point will be interpolated from
69      * the Z-ordinates of the line segment containing it, if they exist.
70      *
71      * @param index the index of the desired point
72      * @return the Coordinate at the given index
73      */
74     geom::Coordinate extractPoint(double index) const;
75 
76 
77     /**
78      * \brief
79      * Computes the [Coordinate](@ref geom::Coordinate) for the point
80      * on the line at the given index, offset by the given distance.
81      *
82      * If the index is out of range the first or last point on the
83      * line will be returned.
84      * The computed point is offset to the left of the line if the
85      * offset distance is positive, to the right if negative.
86      *
87      * The Z-ordinate of the computed point will be interpolated from
88      * the Z-ordinates of the line segment containing it, if they exist.
89      *
90      * @param index the index of the desired point
91      * @param offsetDistance the distance the point is offset from the segment
92      *                       (positive is to the left, negative is to the right)
93      * @return the Coordinate at the given index
94      */
95     geom::Coordinate extractPoint(double index, double offsetDistance) const;
96 
97     /** \brief
98      * Computes the [LineString](@ref geom::LineString) for the interval
99      * on the line between the given indices.
100      *
101      * If the endIndex lies before the startIndex,
102      * the computed geometry is reversed.
103      *
104      * @param startIndex the index of the start of the interval
105      * @param endIndex the index of the end of the interval
106      * @return the linear interval between the indices
107      */
108     std::unique_ptr<geom::Geometry> extractLine(double startIndex, double endIndex) const;
109 
110 
111     /** \brief
112      * Computes the minimum index for a point on the line.
113      *
114      * If the line is not simple (i.e. loops back on itself)
115      * a single point may have more than one possible index.
116      * In this case, the smallest index is returned.
117      *
118      * The supplied point does not *necessarily* have to lie precisely
119      * on the line, but if it is far from the line the accuracy and
120      * performance of this function is not guaranteed.
121      * Use {@link #project} to compute a guaranteed result for points
122      * which may be far from the line.
123      *
124      * @param pt a point on the line
125      * @return the minimum index of the point
126      *
127      * @see project
128      */
129     double indexOf(const geom::Coordinate& pt) const;
130 
131     /** \brief
132      * Finds the index for a point on the line which is
133      * greater than the given index.
134      *
135      * If no such index exists, returns `minIndex`.
136      * This method can be used to determine all indexes for
137      * a point which occurs more than once on a non-simple line.
138      * It can also be used to disambiguate cases where the given point lies
139      * slightly off the line and is equidistant from two different
140      * points on the line.
141      *
142      * The supplied point does not `*necessarily* have to lie precisely
143      * on the line, but if it is far from the line the accuracy and
144      * performance of this function is not guaranteed.
145      * Use {@link #project} to compute a guaranteed result for points
146      * which may be far from the line.
147      *
148      * @param pt a point on the line
149      * @param minIndex the value the returned index must be greater than
150      * @return the index of the point greater than the given minimum index
151      *
152      * @see project
153      */
154     double indexOfAfter(const geom::Coordinate& pt, double minIndex) const;
155 
156     /** \brief
157      * Computes the indices for a subline of the line.
158      *
159      * (The subline must **conform** to the line; that is,
160      * all vertices in the subline (except possibly the first and last)
161      * must be vertices of the line and occcur in the same order).
162      *
163      * @param subLine a subLine of the line
164      * @return a pair of indices for the start and end of the subline.
165      */
166     double* indicesOf(const geom::Geometry* subLine) const;
167 
168 
169     /** \brief
170      * Computes the index for the closest point on the line to the given point.
171      *
172      * If more than one point has the closest distance the first one along the line
173      * is returned.
174      * (The point does not necessarily have to lie precisely on the line.)
175      *
176      * @param pt a point on the line
177      * @return the index of the point
178      */
179     double project(const geom::Coordinate& pt) const;
180 
181     /** \brief
182      * Returns the index of the start of the line
183      * @return the start index
184      */
185     double getStartIndex() const;
186 
187     /** \brief
188      * Returns the index of the end of the line
189      * @return the end index
190      */
191     double getEndIndex() const;
192 
193     /** \brief
194      * Tests whether an index is in the valid index range for the line.
195      *
196      * @param index the index to test
197      * @return `true` if the index is in the valid range
198      */
199     bool isValidIndex(double index) const;
200 
201 
202     /** \brief
203      * Computes a valid index for this line by clamping the given index
204      * to the valid range of index values.
205      *
206      * @return a valid index value
207      */
208     double clampIndex(double index) const;
209 };
210 }
211 }
212 #endif
213