1 /**********************************************************************
3 * GEOS - Geometry Engine Open Source
4 * http://geos.osgeo.org
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.
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.
15 **********************************************************************
17 * Last port: algorithm/LengthLocationMap.java r463
19 **********************************************************************/
22 #include <geos/linearref/LengthIndexedLine.h>
23 #include <geos/linearref/LinearIterator.h>
24 #include <geos/linearref/LinearLocation.h>
25 #include <geos/linearref/LengthLocationMap.h>
29 using namespace geos::geom
;
33 namespace linearref
// geos.linearref
37 double LengthLocationMap::getLength(const Geometry
* linearGeom
, const LinearLocation
& loc
)
39 LengthLocationMap
locater(linearGeom
);
40 return locater
.getLength(loc
);
44 LengthLocationMap::LengthLocationMap(const Geometry
* linearGeom
) :
45 linearGeom(linearGeom
) {}
48 LengthLocationMap::getLocation(double length
) const
50 double forwardLength
= length
;
53 double lineLen
= linearGeom
->getLength();
54 forwardLength
= lineLen
+ length
;
56 return getLocationForward(forwardLength
);
60 LengthLocationMap::getLocation(double length
, bool resolveLower
) const
62 double forwardLength
= length
;
64 // negative values are measured from end of geometry
67 double lineLen
= linearGeom
->getLength();
68 forwardLength
= lineLen
+ length
;
71 LinearLocation loc
= getLocationForward(forwardLength
);
75 return resolveHigher(loc
);
80 LengthLocationMap::getLocationForward(double length
) const
83 return LinearLocation();
85 double totalLength
= 0.0;
87 LinearIterator
it (linearGeom
);
91 * Special handling is required for the situation when the
92 * length references exactly to a component endpoint.
93 * In this case, the endpoint location of the current component
95 * rather than the startpoint location of the next component.
96 * This produces consistent behaviour with the project method.
98 if (it
.isEndOfLine()) {
99 if (totalLength
== length
) {
100 unsigned int compIndex
= it
.getComponentIndex();
101 unsigned int segIndex
= it
.getVertexIndex();
102 return LinearLocation(compIndex
, segIndex
, 0.0);
106 Coordinate p0
= it
.getSegmentStart();
107 Coordinate p1
= it
.getSegmentEnd();
108 double segLen
= p1
.distance(p0
);
109 // length falls in this segment
110 if (totalLength
+ segLen
> length
)
112 double frac
= (length
- totalLength
) / segLen
;
113 unsigned int compIndex
= it
.getComponentIndex();
114 unsigned int segIndex
= it
.getVertexIndex();
115 return LinearLocation(compIndex
, segIndex
, frac
);
117 totalLength
+= segLen
;
122 // length is longer than line - return end location
123 return LinearLocation::getEndLocation(linearGeom
);
128 LengthLocationMap::resolveHigher(const LinearLocation
& loc
) const
130 if (! loc
.isEndpoint(*linearGeom
)) return loc
;
132 unsigned int compIndex
= loc
.getComponentIndex();
133 // if last component can't resolve any higher
134 if (compIndex
>= linearGeom
->getNumGeometries() - 1) return loc
;
138 } while (compIndex
< linearGeom
->getNumGeometries() - 1
139 && linearGeom
->getGeometryN(compIndex
)->getLength() == 0);
141 // resolve to next higher location
142 return LinearLocation(compIndex
, 0, 0.0);
146 double LengthLocationMap::getLength(const LinearLocation
& loc
) const
148 double totalLength
= 0.0;
150 LinearIterator
it(linearGeom
);
153 if (! it
.isEndOfLine())
155 Coordinate p0
= it
.getSegmentStart();
156 Coordinate p1
= it
.getSegmentEnd();
157 double segLen
= p1
.distance(p0
);
158 // length falls in this segment
159 if (loc
.getComponentIndex() == it
.getComponentIndex()
160 && loc
.getSegmentIndex() == it
.getVertexIndex())
162 return totalLength
+ segLen
* loc
.getSegmentFraction();
164 totalLength
+= segLen
;