Regnerate geos wrapper with correct version for this branch
[geos.git] / src / linearref / LengthLocationMap.cpp
blobe41f6ebd600d1172ec895a846601809ddb4bb7ea
1 /**********************************************************************
3 * GEOS - Geometry Engine Open Source
4 * http://geos.osgeo.org
6 * Copyright (C) 2011 Sandro Santilli <strk@keybit.net>
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>
27 using namespace std;
29 using namespace geos::geom;
31 namespace geos
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) {}
47 LinearLocation
48 LengthLocationMap::getLocation(double length) const
50 double forwardLength = length;
51 if (length < 0.0)
53 double lineLen = linearGeom->getLength();
54 forwardLength = lineLen + length;
56 return getLocationForward(forwardLength);
59 LinearLocation
60 LengthLocationMap::getLocation(double length, bool resolveLower) const
62 double forwardLength = length;
64 // negative values are measured from end of geometry
65 if (length < 0.0)
67 double lineLen = linearGeom->getLength();
68 forwardLength = lineLen + length;
71 LinearLocation loc = getLocationForward(forwardLength);
72 if (resolveLower) {
73 return loc;
75 return resolveHigher(loc);
78 /* private */
79 LinearLocation
80 LengthLocationMap::getLocationForward(double length) const
82 if (length <= 0.0)
83 return LinearLocation();
85 double totalLength = 0.0;
87 LinearIterator it (linearGeom);
88 while (it.hasNext())
90 /**
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
94 * is returned,
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);
105 else {
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;
120 it.next();
122 // length is longer than line - return end location
123 return LinearLocation::getEndLocation(linearGeom);
126 /* private */
127 LinearLocation
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;
136 do {
137 compIndex++;
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);
151 while (it.hasNext())
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;
166 it.next();
168 return totalLength;