[geos-commits] r3484 - in trunk: . include/geos/linearref
src/linearref
svn_geos at osgeo.org
svn_geos at osgeo.org
Fri Sep 23 08:14:53 EDT 2011
Author: strk
Date: 2011-09-23 05:14:53 -0700 (Fri, 23 Sep 2011)
New Revision: 3484
Added:
trunk/include/geos/linearref/LocationIndexedLine.h
Modified:
trunk/NEWS
trunk/include/geos/linearref/LengthIndexedLine.h
trunk/include/geos/linearref/LengthLocationMap.h
trunk/include/geos/linearref/LinearIterator.h
trunk/include/geos/linearref/LinearLocation.h
trunk/include/geos/linearref/LocationIndexOfPoint.h
trunk/include/geos/linearref/Makefile.am
trunk/src/linearref/LengthIndexedLine.cpp
trunk/src/linearref/LengthLocationMap.cpp
trunk/src/linearref/LinearIterator.cpp
trunk/src/linearref/LinearLocation.cpp
trunk/src/linearref/LocationIndexOfPoint.cpp
Log:
Fixed handling of Linear Referencing over MultiLineStrings to always return lowest index, and to trim zero-length result components (#323)
Includes test. This is a port of JTS changesets 463, 464 and 465
Modified: trunk/NEWS
===================================================================
--- trunk/NEWS 2011-09-23 12:14:39 UTC (rev 3483)
+++ trunk/NEWS 2011-09-23 12:14:53 UTC (rev 3484)
@@ -9,6 +9,10 @@
to take it by reference rather than pointer.
- GraphComponent::label is now a Label value (from a pointer)
- NodedSegmentString takes ownership of CoordinateSequence now
+- Bug fixes / improvements
+ - Fixed Linear Referencing API to handle MultiLineStrings consistently
+ by always using the lowest possible index value, and by trimming
+ zero-length components from results (#323)
Changes in 3.3.0
2011-05-30
Modified: trunk/include/geos/linearref/LengthIndexedLine.h
===================================================================
--- trunk/include/geos/linearref/LengthIndexedLine.h 2011-09-23 12:14:39 UTC (rev 3483)
+++ trunk/include/geos/linearref/LengthIndexedLine.h 2011-09-23 12:14:53 UTC (rev 3484)
@@ -3,6 +3,7 @@
* GEOS - Geometry Engine Open Source
* http://geos.refractions.net
*
+ * Copyright (C) 2011 Sandro Santilli <strk at keybit.net>
* Copyright (C) 2005-2006 Refractions Research Inc.
* Copyright (C) 2001-2002 Vivid Solutions Inc.
*
@@ -13,7 +14,7 @@
*
**********************************************************************
*
- * Last port: linearref/LengthIndexedLine.java rev. 1.10
+ * Last port: linearref/LengthIndexedLine.java r463
*
**********************************************************************/
@@ -46,6 +47,8 @@
private:
const geom::Geometry *linearGeom;
LinearLocation locationOf(double index) const;
+ LinearLocation locationOf(double index, bool resolveLower) const;
+ double positiveIndex(double index) const;
public:
@@ -73,12 +76,14 @@
/**
+ * \brief
* Computes the {@link Coordinate} for the point
* on the line at the given index, offset by the given distance.
+ *
* If the index is out of range the first or last point on the
* line will be returned.
- * The computed point is offset to the left of the line if the offset distance is
- * positive, to the right if negative.
+ * The computed point is offset to the left of the line if the
+ * offset distance is positive, to the right if negative.
*
* The Z-ordinate of the computed point will be interpolated from
* the Z-ordinates of the line segment containing it, if they exist.
Modified: trunk/include/geos/linearref/LengthLocationMap.h
===================================================================
--- trunk/include/geos/linearref/LengthLocationMap.h 2011-09-23 12:14:39 UTC (rev 3483)
+++ trunk/include/geos/linearref/LengthLocationMap.h 2011-09-23 12:14:53 UTC (rev 3484)
@@ -3,6 +3,7 @@
* GEOS - Geometry Engine Open Source
* http://geos.refractions.net
*
+ * Copyright (C) 2011 Sandro Santilli <strk at keybit.net>
* Copyright (C) 2005-2006 Refractions Research Inc.
* Copyright (C) 2001-2002 Vivid Solutions Inc.
*
@@ -13,7 +14,7 @@
*
**********************************************************************
*
- * Last port: linearref/LengthLocationMap.java rev. 1.10
+ * Last port: linearref/LengthLocationMap.java r463
*
**********************************************************************/
@@ -24,10 +25,8 @@
#include <geos/geom/Geometry.h>
#include <geos/linearref/LinearLocation.h>
-namespace geos
-{
-namespace linearref // geos::linearref
-{
+namespace geos {
+namespace linearref { // geos::linearref
/**
* Computes the {@link LinearLocation} for a given length
@@ -44,6 +43,8 @@
LinearLocation getLocationForward(double length) const;
+ LinearLocation resolveHigher(const LinearLocation& loc) const;
+
public:
// TODO: cache computed cumulative length for each vertex
@@ -51,6 +52,7 @@
// TODO: support measure index for fast mapping to a location
/**
+ * \brief
* Computes the {@link LinearLocation} for a
* given length along a linear {@link Geometry}.
*
@@ -58,9 +60,30 @@
* @param length the length index of the location
* @return the {@link LinearLocation} for the length
*/
- static LinearLocation getLocation(const geom::Geometry *linearGeom, double length);
+ static LinearLocation getLocation(const geom::Geometry *linearGeom, double length)
+ {
+ LengthLocationMap locater(linearGeom);
+ return locater.getLocation(length);
+ }
/**
+ * \brief
+ * Computes the {@link LinearLocation} for a
+ * given length along a linear {@link Geometry}.
+ *
+ * @param line the linear geometry to use
+ * @param length the length index of the location
+ * @param resolveLower if true lengths are resolved to the
+ * lowest possible index
+ * @return the {@link LinearLocation} for the length
+ */
+ static LinearLocation getLocation(const geom::Geometry *linearGeom, double length, bool resolveLower)
+ {
+ LengthLocationMap locater(linearGeom);
+ return locater.getLocation(length, resolveLower);
+ }
+
+ /**
* Computes the length for a given {@link LinearLocation}
* on a linear {@link Geometry}.
*
@@ -73,18 +96,37 @@
LengthLocationMap(const geom::Geometry *linearGeom);
/**
+ * \brief
* Compute the {@link LinearLocation} corresponding to a length.
+ *
* Negative lengths are measured in reverse from end of the linear geometry.
* Out-of-range values are clamped.
+ * Ambiguous indexes are resolved to the lowest possible location value,
+ * depending on the value of <tt>resolveLower</tt>.
*
* @param length the length index
* @return the corresponding LinearLocation
*/
+ LinearLocation getLocation(double length, bool resolveLower) const;
+
+ /**
+ * \brief
+ * Compute the {@link LinearLocation} corresponding to a length.
+ *
+ * Negative lengths are measured in reverse from end of the linear geometry.
+ * Out-of-range values are clamped.
+ * Ambiguous indexes are resolved to the lowest possible location value.
+ *
+ * @param length the length index
+ * @return the corresponding LinearLocation
+ */
LinearLocation getLocation(double length) const;
double getLength(const LinearLocation& loc) const;
};
-}
-}
+
+} // geos.linearref
+} // geos
+
#endif
Modified: trunk/include/geos/linearref/LinearIterator.h
===================================================================
--- trunk/include/geos/linearref/LinearIterator.h 2011-09-23 12:14:39 UTC (rev 3483)
+++ trunk/include/geos/linearref/LinearIterator.h 2011-09-23 12:14:53 UTC (rev 3484)
@@ -13,7 +13,7 @@
*
**********************************************************************
*
- * Last port: linearref/LinearIterator.java rev. 1.10
+ * Last port: linearref/LinearIterator.java r463
*
**********************************************************************/
@@ -90,7 +90,7 @@
/**
* Checks whether the iterator cursor is pointing to the
- * endpoint of a linestring.
+ * endpoint of a component {@link LineString}.
*
* @return <code>true</true> if the iterator is at an endpoint
*/
@@ -143,6 +143,8 @@
/**
* Invariant: currentLine <> null if the iterator is pointing
* at a valid coordinate
+ *
+ * @throws IllegalArgumentException if linearGeom is not {@link Lineal}
*/
void loadCurrentLine();
Modified: trunk/include/geos/linearref/LinearLocation.h
===================================================================
--- trunk/include/geos/linearref/LinearLocation.h 2011-09-23 12:14:39 UTC (rev 3483)
+++ trunk/include/geos/linearref/LinearLocation.h 2011-09-23 12:14:53 UTC (rev 3484)
@@ -3,6 +3,7 @@
* GEOS - Geometry Engine Open Source
* http://geos.refractions.net
*
+ * Copyright (C) 2011 Sandro Santilli <strk at keybit.net>
* Copyright (C) 2005-2006 Refractions Research Inc.
* Copyright (C) 2001-2002 Vivid Solutions Inc.
*
@@ -13,7 +14,7 @@
*
**********************************************************************
*
- * Last port: linearref/LinearLocation.java rev. 1.10
+ * Last port: linearref/LinearLocation.java r463
*
**********************************************************************/
@@ -155,7 +156,7 @@
* given linear {@link Geometry} which is
* referenced by this location.
*
- * @param linearGeom a linear geometry
+ * @param linearGeom the linear geometry referenced by this location
* @return the <tt>Coordinate</tt> at the location
*/
geom::Coordinate getCoordinate(const geom::Geometry* linearGeom) const;
@@ -225,6 +226,15 @@
*/
bool isOnSameSegment(const LinearLocation& loc) const;
+ /**
+ * \brief
+ * Tests whether this location is an endpoint of
+ * the linear component it refers to.
+ *
+ * @param linearGeom the linear geometry referenced by this location
+ * @return true if the location is a component endpoint
+ */
+ bool isEndpoint(const geom::Geometry& linearGeom) const;
friend std::ostream& operator<< (std::ostream& out, const LinearLocation& obj );
Modified: trunk/include/geos/linearref/LocationIndexOfPoint.h
===================================================================
--- trunk/include/geos/linearref/LocationIndexOfPoint.h 2011-09-23 12:14:39 UTC (rev 3483)
+++ trunk/include/geos/linearref/LocationIndexOfPoint.h 2011-09-23 12:14:53 UTC (rev 3484)
@@ -3,6 +3,7 @@
* GEOS - Geometry Engine Open Source
* http://geos.refractions.net
*
+ * Copyright (C) 2011 Sandro Santilli <strk at keybit.net>
* Copyright (C) 2005-2006 Refractions Research Inc.
* Copyright (C) 2001-2002 Vivid Solutions Inc.
*
@@ -13,7 +14,7 @@
*
**********************************************************************
*
- * Last port: linearref/LinearGeometryBuilder.java rev. 1.10
+ * Last port: linearref/LinearGeometryBuilder.java r466
*
**********************************************************************/
@@ -42,12 +43,12 @@
private:
const geom::Geometry *linearGeom;
- LinearLocation indexOfFromStart(const geom::Coordinate& inputPt, LinearLocation* minIndex) const;
+ LinearLocation indexOfFromStart(const geom::Coordinate& inputPt, const LinearLocation* minIndex) const;
public:
static LinearLocation indexOf(const geom::Geometry *linearGeom, const geom::Coordinate& inputPt);
- static LinearLocation indexOfAfter(const geom::Geometry *linearGeom, const geom::Coordinate& inputPt, LinearLocation* minIndex);
+ static LinearLocation indexOfAfter(const geom::Geometry *linearGeom, const geom::Coordinate& inputPt, const LinearLocation* minIndex);
LocationIndexOfPoint(const geom::Geometry *linearGeom);
@@ -73,7 +74,7 @@
* @param minLocation the minimum location for the point location
* @return the location of the nearest point
*/
- LinearLocation indexOfAfter(const geom::Coordinate& inputPt, LinearLocation* minIndex) const;
+ LinearLocation indexOfAfter(const geom::Coordinate& inputPt, const LinearLocation* minIndex) const;
};
}
}
Added: trunk/include/geos/linearref/LocationIndexedLine.h
===================================================================
--- trunk/include/geos/linearref/LocationIndexedLine.h (rev 0)
+++ trunk/include/geos/linearref/LocationIndexedLine.h 2011-09-23 12:14:53 UTC (rev 3484)
@@ -0,0 +1,267 @@
+/**********************************************************************
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.refractions.net
+ *
+ * Copyright (C) 2011 Sandro Santilli <strk at keybit.net>
+ *
+ * This is free software; you can redistribute and/or modify it under
+ * the terms of the GNU Lesser General Public Licence as published
+ * by the Free Software Foundation.
+ * See the COPYING file for more information.
+ *
+ **********************************************************************
+ *
+ * Last port: linearref/LocationIndexedLine.java r466
+ *
+ **********************************************************************/
+
+#ifndef GEOS_LINEARREF_LOCATIONINDEXEDLINE_H
+#define GEOS_LINEARREF_LOCATIONINDEXEDLINE_H
+
+#include <geos/export.h>
+#include <geos/geom/Coordinate.h>
+#include <geos/geom/Geometry.h>
+#include <geos/geom/Lineal.h>
+#include <geos/linearref/LinearLocation.h>
+#include <geos/linearref/LocationIndexOfPoint.h>
+#include <geos/linearref/LocationIndexOfLine.h>
+#include <geos/util/IllegalArgumentException.h>
+
+namespace geos {
+namespace linearref { // geos::linearref
+
+/**
+ * \brief
+ * Supports linear referencing
+ * along a linear {@link Geometry}
+ * using {@link LinearLocation}s as the index.
+ */
+class GEOS_DLL LocationIndexedLine
+{
+private:
+ const geom::Geometry *linearGeom;
+
+ void checkGeometryType()
+ {
+ if ( ! dynamic_cast<const geom::Lineal*>(linearGeom) )
+ throw util::IllegalArgumentException("Input geometry must be linear");
+ }
+
+public:
+
+ /**
+ * \brief
+ * Constructs an object which allows linear referencing along
+ * a given linear {@link Geometry}.
+ *
+ * @param linearGeom the linear geometry to reference along
+ */
+ LocationIndexedLine(const geom::Geometry *linearGeom)
+ : linearGeom(linearGeom)
+ {
+ checkGeometryType();
+ }
+
+ /**
+ * \brief
+ * Computes the {@link Coordinate} for the point
+ * on the line at the given index.
+ *
+ * If the index is out of range the first or last point on the
+ * line will be returned.
+ * The Z-ordinate of the computed point will be interpolated from
+ * the Z-ordinates of the line segment containing it, if they exist.
+ *
+ * @param index the index of the desired point
+ * @return the Coordinate at the given index
+ */
+ geom::Coordinate extractPoint(const LinearLocation& index) const
+ {
+ return index.getCoordinate(linearGeom);
+ }
+
+
+ /**
+ * \brief
+ * Computes the {@link Coordinate} for the point
+ * on the line at the given index, offset by the given distance.
+ *
+ * If the index is out of range the first or last point on the
+ * line will be returned.
+ * The computed point is offset to the left of the line if the offset
+ * distance is positive, to the right if negative.
+ *
+ * The Z-ordinate of the computed point will be interpolated from
+ * the Z-ordinates of the line segment containing it, if they exist.
+ *
+ * @param index the index of the desired point
+ * @param offsetDistance the distance the point is offset from the segment
+ * (positive is to the left, negative is to the right)
+ * @return the Coordinate at the given index
+ */
+ geom::Coordinate extractPoint(const LinearLocation& index,
+ double offsetDistance) const
+ {
+ geom::Coordinate ret;
+ index.getSegment(linearGeom)->pointAlongOffset(
+ index.getSegmentFraction(), offsetDistance, ret
+ );
+ return ret;
+ }
+
+ /**
+ * \brief
+ * Computes the {@link LineString} for the interval
+ * on the line between the given indices.
+ *
+ * If the endIndex lies before the startIndex,
+ * the computed geometry is reversed.
+ *
+ * @param startIndex the index of the start of the interval
+ * @param endIndex the index of the end of the interval
+ * @return the linear interval between the indices
+ */
+ geom::Geometry *extractLine(const LinearLocation& startIndex,
+ const LinearLocation& endIndex) const
+ {
+ return ExtractLineByLocation::extract(linearGeom, startIndex, endIndex);
+ }
+
+
+ /**
+ * \brief
+ * Computes the index for a given point on the line.
+ *
+ * The supplied point does not <i>necessarily</i> have to lie precisely
+ * on the line, but if it is far from the line the accuracy and
+ * performance of this function is not guaranteed.
+ * Use {@link #project} to compute a guaranteed result for points
+ * which may be far from the line.
+ *
+ * @param pt a point on the line
+ * @return the index of the point
+ *
+ * @see project
+ */
+ LinearLocation indexOf(const geom::Coordinate& pt) const
+ {
+ return LocationIndexOfPoint::indexOf(linearGeom, pt);
+ }
+
+ /**
+ * \brief
+ * Finds the index for a point on the line
+ * which is greater than the given index.
+ *
+ * If no such index exists, returns <tt>minIndex</tt>.
+ * This method can be used to determine all indexes for
+ * a point which occurs more than once on a non-simple line.
+ * It can also be used to disambiguate cases where the given point lies
+ * slightly off the line and is equidistant from two different
+ * points on the line.
+ *
+ * The supplied point does not <i>necessarily</i> have to lie precisely
+ * on the line, but if it is far from the line the accuracy and
+ * performance of this function is not guaranteed.
+ * Use {@link #project} to compute a guaranteed result for points
+ * which may be far from the line.
+ *
+ * @param pt a point on the line
+ * @param minIndex the value the returned index must be greater than
+ * @return the index of the point greater than the given minimum index
+ *
+ * @see project
+ */
+ LinearLocation indexOfAfter(const geom::Coordinate& pt,
+ const LinearLocation& minIndex) const
+ {
+ return LocationIndexOfPoint::indexOfAfter(linearGeom, pt, &minIndex);
+ }
+
+ /**
+ * \brief
+ * Computes the indices for a subline of the line.
+ *
+ * (The subline must <b>conform</b> to the line; that is,
+ * all vertices in the subline (except possibly the first and last)
+ * must be vertices of the line and occur in the same order).
+ *
+ * @param subLine a subLine of the line
+ * @return a pair of indices for the start and end of the subline.
+ */
+ LinearLocation* indicesOf(const geom::Geometry *subLine) const
+ {
+ return LocationIndexOfLine::indicesOf(linearGeom, subLine);
+ }
+
+
+ /**
+ * \brief
+ * Computes the index for the closest point on the line to the given point.
+ *
+ * If more than one point has the closest distance the first one along
+ * the line is returned.
+ * (The point does not necessarily have to lie precisely on the line.)
+ *
+ * @param pt a point on the line
+ * @return the index of the point
+ */
+ LinearLocation project(const geom::Coordinate& pt) const
+ {
+ return LocationIndexOfPoint::indexOf(linearGeom, pt);
+ }
+
+ /**
+ * \brief
+ * Returns the index of the start of the line
+ *
+ * @return the start index
+ */
+ LinearLocation getStartIndex() const
+ {
+ return LinearLocation();
+ }
+
+ /**
+ * \brief
+ * Returns the index of the end of the line
+ *
+ * @return the end index
+ */
+ LinearLocation getEndIndex() const
+ {
+ return LinearLocation::getEndLocation(linearGeom);
+ }
+
+ /**
+ * \brief
+ * Tests whether an index is in the valid index range for the line.
+ *
+ * @param length the index to test
+ * @return <code>true</code> if the index is in the valid range
+ */
+ bool isValidIndex(const LinearLocation& index) const
+ {
+ return index.isValid(linearGeom);
+ }
+
+
+ /**
+ * \brief
+ * Computes a valid index for this line
+ * by clamping the given index to the valid range of index values
+ *
+ * @return a valid index value
+ */
+ LinearLocation clampIndex(const LinearLocation& index) const
+ {
+ LinearLocation loc = index;
+ loc.clamp(linearGeom);
+ return loc;
+ }
+};
+
+} // geos::linearref
+} // geos
+#endif
Modified: trunk/include/geos/linearref/Makefile.am
===================================================================
--- trunk/include/geos/linearref/Makefile.am 2011-09-23 12:14:39 UTC (rev 3483)
+++ trunk/include/geos/linearref/Makefile.am 2011-09-23 12:14:53 UTC (rev 3484)
@@ -13,5 +13,6 @@
LinearIterator.h \
LinearGeometryBuilder.h \
LinearLocation.h \
+ LocationIndexedLine.h \
LocationIndexOfLine.h \
LocationIndexOfPoint.h
Modified: trunk/src/linearref/LengthIndexedLine.cpp
===================================================================
--- trunk/src/linearref/LengthIndexedLine.cpp 2011-09-23 12:14:39 UTC (rev 3483)
+++ trunk/src/linearref/LengthIndexedLine.cpp 2011-09-23 12:14:53 UTC (rev 3484)
@@ -3,6 +3,7 @@
* GEOS - Geometry Engine Open Source
* http://geos.refractions.net
*
+ * Copyright (C) 2011 Sandro Santilli <strk at keybit.net>
* Copyright (C) 2005-2006 Refractions Research Inc.
* Copyright (C) 2001-2002 Vivid Solutions Inc.
*
@@ -13,12 +14,13 @@
*
**********************************************************************
*
- * Last port: linearref/LengthIndexedLine.java rev. 1.35
+ * Last port: linearref/LengthIndexedLine.java r463
*
**********************************************************************/
#include <geos/linearref/ExtractLineByLocation.h>
#include <geos/linearref/LengthIndexedLine.h>
+#include <geos/linearref/LocationIndexedLine.h>
#include <geos/linearref/LinearLocation.h>
#include <geos/linearref/LengthLocationMap.h>
#include <geos/linearref/LengthIndexOfPoint.h>
@@ -52,13 +54,20 @@
}
-Geometry *LengthIndexedLine::extractLine(double startIndex, double endIndex) const
+Geometry *
+LengthIndexedLine::extractLine(double startIndex, double endIndex) const
{
-
- const LinearLocation startLoc = locationOf(startIndex);
- const LinearLocation endLoc = locationOf(endIndex);
- Geometry* g = ExtractLineByLocation::extract(linearGeom, startLoc, endLoc);
- return g;
+ const LocationIndexedLine lil(linearGeom);
+ const double startIndex2 = clampIndex(startIndex);
+ const double endIndex2 = clampIndex(endIndex);
+ // if extracted line is zero-length, resolve start lower as well to
+ // ensure they are equal
+ const bool resolveStartLower = ( startIndex2 == endIndex2 );
+ const LinearLocation startLoc = locationOf(startIndex2, resolveStartLower);
+ const LinearLocation endLoc = locationOf(endIndex2);
+// LinearLocation endLoc = locationOf(endIndex2, true);
+// LinearLocation startLoc = locationOf(startIndex2);
+ return ExtractLineByLocation::extract(linearGeom, startLoc, endLoc);
}
LinearLocation LengthIndexedLine::locationOf(double index) const
@@ -66,7 +75,13 @@
return LengthLocationMap::getLocation(linearGeom, index);
}
+LinearLocation
+LengthIndexedLine::locationOf(double index, bool resolveLower) const
+{
+ return LengthLocationMap::getLocation(linearGeom, index, resolveLower);
+}
+
double LengthIndexedLine::indexOf(const Coordinate& pt) const
{
return LengthIndexOfPoint::indexOf(linearGeom, pt);
@@ -111,15 +126,27 @@
&& index <= getEndIndex());
}
-double LengthIndexedLine::clampIndex(double index) const
+/* public */
+double
+LengthIndexedLine::clampIndex(double index) const
{
+ double posIndex = positiveIndex(index);
double startIndex = getStartIndex();
- if (index < startIndex) return startIndex;
+ if (posIndex < startIndex) return startIndex;
double endIndex = getEndIndex();
- if (index > endIndex) return endIndex;
+ if (posIndex > endIndex) return endIndex;
- return index;
+ return posIndex;
}
+
+/* private */
+double
+LengthIndexedLine::positiveIndex(double index) const
+{
+ if (index >= 0.0) return index;
+ return linearGeom->getLength() + index;
}
-}
+
+} // geos.linearref
+} // geos
Modified: trunk/src/linearref/LengthLocationMap.cpp
===================================================================
--- trunk/src/linearref/LengthLocationMap.cpp 2011-09-23 12:14:39 UTC (rev 3483)
+++ trunk/src/linearref/LengthLocationMap.cpp 2011-09-23 12:14:53 UTC (rev 3484)
@@ -3,6 +3,7 @@
* GEOS - Geometry Engine Open Source
* http://geos.refractions.net
*
+ * Copyright (C) 2011 Sandro Santilli <strk at keybit.net>
* Copyright (C) 2005-2006 Refractions Research Inc.
* Copyright (C) 2001-2002 Vivid Solutions Inc.
*
@@ -13,7 +14,7 @@
*
**********************************************************************
*
- * Last port: algorithm/LengthLocationMap.java rev. 1.35
+ * Last port: algorithm/LengthLocationMap.java r463
*
**********************************************************************/
@@ -33,12 +34,6 @@
{
-LinearLocation LengthLocationMap::getLocation(const Geometry* linearGeom, double length)
-{
- LengthLocationMap locater(linearGeom);
- return locater.getLocation(length);
-}
-
double LengthLocationMap::getLength(const Geometry* linearGeom, const LinearLocation& loc)
{
LengthLocationMap locater(linearGeom);
@@ -49,7 +44,8 @@
LengthLocationMap::LengthLocationMap(const Geometry* linearGeom) :
linearGeom(linearGeom) {}
-LinearLocation LengthLocationMap::getLocation(double length) const
+LinearLocation
+LengthLocationMap::getLocation(double length) const
{
double forwardLength = length;
if (length < 0.0)
@@ -60,8 +56,29 @@
return getLocationForward(forwardLength);
}
-LinearLocation LengthLocationMap::getLocationForward(double length) const
+LinearLocation
+LengthLocationMap::getLocation(double length, bool resolveLower) const
{
+ double forwardLength = length;
+
+ // negative values are measured from end of geometry
+ if (length < 0.0)
+ {
+ double lineLen = linearGeom->getLength();
+ forwardLength = lineLen + length;
+ }
+
+ LinearLocation loc = getLocationForward(forwardLength);
+ if (resolveLower) {
+ return loc;
+ }
+ return resolveHigher(loc);
+}
+
+/* private */
+LinearLocation
+LengthLocationMap::getLocationForward(double length) const
+{
if (length <= 0.0)
return LinearLocation();
@@ -70,8 +87,22 @@
LinearIterator it (linearGeom);
while (it.hasNext())
{
- if (! it.isEndOfLine())
- {
+ /**
+ * Special handling is required for the situation when the
+ * length references exactly to a component endpoint.
+ * In this case, the endpoint location of the current component
+ * is returned,
+ * rather than the startpoint location of the next component.
+ * This produces consistent behaviour with the project method.
+ */
+ if (it.isEndOfLine()) {
+ if (totalLength == length) {
+ unsigned int compIndex = it.getComponentIndex();
+ unsigned int segIndex = it.getVertexIndex();
+ return LinearLocation(compIndex, segIndex, 0.0);
+ }
+ }
+ else {
Coordinate p0 = it.getSegmentStart();
Coordinate p1 = it.getSegmentEnd();
double segLen = p1.distance(p0);
@@ -85,13 +116,33 @@
}
totalLength += segLen;
}
+
it.next();
}
// length is longer than line - return end location
return LinearLocation::getEndLocation(linearGeom);
}
+/* private */
+LinearLocation
+LengthLocationMap::resolveHigher(const LinearLocation& loc) const
+{
+ if (! loc.isEndpoint(*linearGeom)) return loc;
+ unsigned int compIndex = loc.getComponentIndex();
+ // if last component can't resolve any higher
+ if (compIndex >= linearGeom->getNumGeometries() - 1) return loc;
+
+ do {
+ compIndex++;
+ } while (compIndex < linearGeom->getNumGeometries() - 1
+ && linearGeom->getGeometryN(compIndex)->getLength() == 0);
+
+ // resolve to next higher location
+ return LinearLocation(compIndex, 0, 0.0);
+}
+
+
double LengthLocationMap::getLength(const LinearLocation& loc) const
{
double totalLength = 0.0;
Modified: trunk/src/linearref/LinearIterator.cpp
===================================================================
--- trunk/src/linearref/LinearIterator.cpp 2011-09-23 12:14:39 UTC (rev 3483)
+++ trunk/src/linearref/LinearIterator.cpp 2011-09-23 12:14:53 UTC (rev 3484)
@@ -13,7 +13,7 @@
*
**********************************************************************
*
- * Last port: linearref/LinearIterator.java rev. 1.35
+ * Last port: linearref/LinearIterator.java r463
*
**********************************************************************/
Modified: trunk/src/linearref/LinearLocation.cpp
===================================================================
--- trunk/src/linearref/LinearLocation.cpp 2011-09-23 12:14:39 UTC (rev 3483)
+++ trunk/src/linearref/LinearLocation.cpp 2011-09-23 12:14:53 UTC (rev 3484)
@@ -3,6 +3,7 @@
* GEOS - Geometry Engine Open Source
* http://geos.refractions.net
*
+ * Copyright (C) 2011 Sandro Santilli <strk at keybit.net>
* Copyright (C) 2005-2006 Refractions Research Inc.
* Copyright (C) 2001-2002 Vivid Solutions Inc.
*
@@ -13,7 +14,7 @@
*
**********************************************************************
*
- * Last port: linearref/LinearLocation.java rev. 1.10
+ * Last port: linearref/LinearLocation.java r463
*
**********************************************************************/
@@ -318,11 +319,24 @@
return false;
}
+/* public */
+bool
+LinearLocation::isEndpoint(const Geometry& linearGeom) const
+{
+ const LineString& lineComp = dynamic_cast<const LineString&>(
+ *(linearGeom.getGeometryN(componentIndex)) );
+ // check for endpoint
+ unsigned int nseg = lineComp.getNumPoints() - 1;
+ return segmentIndex >= nseg
+ || (segmentIndex == nseg && segmentFraction >= 1.0);
+}
+
+
ostream& operator<<(ostream &out, const LinearLocation &obj)
{
- return out << "LinearLocation(" << obj.componentIndex << ", " <<
- obj.segmentIndex << ", " << obj.segmentFraction << ")";
+ return out << "LinearLoc[" << obj.componentIndex << ", " <<
+ obj.segmentIndex << ", " << obj.segmentFraction << "]";
}
} // namespace geos.linearref
Modified: trunk/src/linearref/LocationIndexOfPoint.cpp
===================================================================
--- trunk/src/linearref/LocationIndexOfPoint.cpp 2011-09-23 12:14:39 UTC (rev 3483)
+++ trunk/src/linearref/LocationIndexOfPoint.cpp 2011-09-23 12:14:53 UTC (rev 3484)
@@ -3,6 +3,7 @@
* GEOS - Geometry Engine Open Source
* http://geos.refractions.net
*
+ * Copyright (C) 2011 Sandro Santilli <strk at keybit.net>
* Copyright (C) 2005-2006 Refractions Research Inc.
* Copyright (C) 2001-2002 Vivid Solutions Inc.
*
@@ -13,7 +14,7 @@
*
**********************************************************************
*
- * Last port: linearref/LocationIndexOfPoint.java rev. 1.35
+ * Last port: linearref/LocationIndexOfPoint.java r466
*
**********************************************************************/
@@ -36,7 +37,9 @@
namespace linearref // geos.linearref
{
-LinearLocation LocationIndexOfPoint::indexOfFromStart(const Coordinate& inputPt, LinearLocation* minIndex) const
+LinearLocation
+LocationIndexOfPoint::indexOfFromStart(const Coordinate& inputPt,
+ const LinearLocation* minIndex) const
{
double minDistance = numeric_limits<double>::max();
int minComponentIndex = 0;
@@ -82,7 +85,7 @@
return locater.indexOf(inputPt);
}
-LinearLocation LocationIndexOfPoint::indexOfAfter(const Geometry *linearGeom, const Coordinate& inputPt, LinearLocation* minIndex)
+LinearLocation LocationIndexOfPoint::indexOfAfter(const Geometry *linearGeom, const Coordinate& inputPt, const LinearLocation* minIndex)
{
LocationIndexOfPoint locater(linearGeom);
return locater.indexOfAfter(inputPt, minIndex);
@@ -97,7 +100,9 @@
return indexOfFromStart(inputPt, 0);
}
-LinearLocation LocationIndexOfPoint::indexOfAfter(const Coordinate& inputPt, LinearLocation* minIndex) const
+LinearLocation
+LocationIndexOfPoint::indexOfAfter(const Coordinate& inputPt,
+ const LinearLocation* minIndex) const
{
if (!minIndex) return indexOf(inputPt);
More information about the geos-commits
mailing list