[geos-commits] r2619 - in trunk: . source source/headers/geos
source/headers/geos/geom source/headers/geos/linearref
source/linearref tests/unit tests/unit/linearref
svn_geos at osgeo.org
svn_geos at osgeo.org
Wed Aug 12 15:01:57 EDT 2009
Author: pramsey
Date: 2009-08-12 15:01:57 -0400 (Wed, 12 Aug 2009)
New Revision: 2619
Added:
trunk/source/headers/geos/linearref/
trunk/source/headers/geos/linearref/ExtractLineByLocation.h
trunk/source/headers/geos/linearref/LengthIndexOfPoint.h
trunk/source/headers/geos/linearref/LengthIndexedLine.h
trunk/source/headers/geos/linearref/LengthLocationMap.h
trunk/source/headers/geos/linearref/LinearGeometryBuilder.h
trunk/source/headers/geos/linearref/LinearIterator.h
trunk/source/headers/geos/linearref/LinearLocation.h
trunk/source/headers/geos/linearref/LocationIndexOfLine.h
trunk/source/headers/geos/linearref/LocationIndexOfPoint.h
trunk/source/headers/geos/linearref/Makefile.am
trunk/source/linearref/
trunk/source/linearref/ExtractLineByLocation.cpp
trunk/source/linearref/LengthIndexOfPoint.cpp
trunk/source/linearref/LengthIndexedLine.cpp
trunk/source/linearref/LengthLocationMap.cpp
trunk/source/linearref/LinearGeometryBuilder.cpp
trunk/source/linearref/LinearIterator.cpp
trunk/source/linearref/LinearLocation.cpp
trunk/source/linearref/LocationIndexOfLine.cpp
trunk/source/linearref/LocationIndexOfPoint.cpp
trunk/source/linearref/Makefile.am
trunk/tests/unit/linearref/
trunk/tests/unit/linearref/LengthIndexedLineTest.cpp
Modified:
trunk/configure.in
trunk/source/Makefile.am
trunk/source/headers/geos/Makefile.am
trunk/source/headers/geos/geom/CoordinateList.h
trunk/tests/unit/Makefile.am
Log:
Port of JTS linear referencing (from David Turner) (#283)
Modified: trunk/configure.in
===================================================================
--- trunk/configure.in 2009-08-02 23:39:51 UTC (rev 2618)
+++ trunk/configure.in 2009-08-12 19:01:57 UTC (rev 2619)
@@ -361,6 +361,7 @@
source/headers/geos/index/strtree/Makefile
source/headers/geos/index/sweepline/Makefile
source/headers/geos/io/Makefile
+ source/headers/geos/linearref/Makefile
source/headers/geos/noding/Makefile
source/headers/geos/noding/snapround/Makefile
source/headers/geos/operation/Makefile
@@ -388,6 +389,7 @@
source/index/strtree/Makefile
source/index/sweepline/Makefile
source/io/Makefile
+ source/linearref/Makefile
source/noding/Makefile
source/noding/snapround/Makefile
source/operation/Makefile
Modified: trunk/source/Makefile.am
===================================================================
--- trunk/source/Makefile.am 2009-08-02 23:39:51 UTC (rev 2618)
+++ trunk/source/Makefile.am 2009-08-12 19:01:57 UTC (rev 2619)
@@ -4,6 +4,7 @@
headers \
index \
io \
+ linearref \
noding \
operation \
planargraph \
@@ -31,6 +32,7 @@
geomgraph/libgeomgraph.la \
index/libindex.la \
io/libio.la \
+ linearref/liblinearref.la \
noding/libnoding.la \
operation/liboperation.la \
planargraph/libplanargraph.la \
Modified: trunk/source/headers/geos/Makefile.am
===================================================================
--- trunk/source/headers/geos/Makefile.am 2009-08-02 23:39:51 UTC (rev 2618)
+++ trunk/source/headers/geos/Makefile.am 2009-08-12 19:01:57 UTC (rev 2619)
@@ -4,6 +4,7 @@
geomgraph \
index \
io \
+ linearref \
noding \
operation \
planargraph \
Modified: trunk/source/headers/geos/geom/CoordinateList.h
===================================================================
--- trunk/source/headers/geos/geom/CoordinateList.h 2009-08-02 23:39:51 UTC (rev 2618)
+++ trunk/source/headers/geos/geom/CoordinateList.h 2009-08-12 19:01:57 UTC (rev 2619)
@@ -59,6 +59,12 @@
{
}
+ CoordinateList()
+ :
+ coords()
+ {
+ }
+
size_type size() const
{
return coords.size();
Added: trunk/source/headers/geos/linearref/ExtractLineByLocation.h
===================================================================
--- trunk/source/headers/geos/linearref/ExtractLineByLocation.h (rev 0)
+++ trunk/source/headers/geos/linearref/ExtractLineByLocation.h 2009-08-12 19:01:57 UTC (rev 2619)
@@ -0,0 +1,91 @@
+/**********************************************************************
+ * $Id: ExtractLineByLocation.h 1938 2009-07-23 10:45:16Z novalis $
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.refractions.net
+ *
+ * Copyright (C) 2005-2006 Refractions Research Inc.
+ * Copyright (C) 2001-2002 Vivid Solutions Inc.
+ *
+ * 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/ExtractLineByLocation.java rev. 1.10
+ *
+ **********************************************************************/
+
+#ifndef GEOS_LINEARREF_EXTRACTLINEBYLOCATION_H
+#define GEOS_LINEARREF_EXTRACTLINEBYLOCATION_H
+
+#include <geos/geom/Coordinate.h>
+#include <geos/geom/Geometry.h>
+#include <geos/linearref/LinearLocation.h>
+
+namespace geos
+{
+namespace linearref // geos::linearref
+{
+
+/**
+ * Extracts the subline of a linear {@link Geometry} between
+ * two {@link LinearLocation}s on the line.
+ */
+class ExtractLineByLocation
+{
+
+private:
+ geom::Geometry *line;
+ geom::Geometry *reverse(geom::Geometry *linear);
+
+ /**
+ * Assumes input is valid (e.g. start <= end)
+ *
+ * @param start
+ * @param end
+ * @return a linear geometry
+ */
+ geom::LineString* computeLine(const LinearLocation& start, const LinearLocation& end);
+
+ /**
+ * Assumes input is valid (e.g. start <= end)
+ *
+ * @param start
+ * @param end
+ * @return a linear geometry
+ */
+ geom::Geometry *computeLinear(const LinearLocation& start, const LinearLocation& end);
+
+public:
+ /**
+ * Computes the subline of a {@link LineString} between
+ * two {@link LineStringLocation}s on the line.
+ * If the start location is after the end location,
+ * the computed geometry is reversed.
+ *
+ * @param line the line to use as the baseline
+ * @param start the start location
+ * @param end the end location
+ * @return the extracted subline
+ */
+ static geom::Geometry *extract(geom::Geometry *line, const LinearLocation& start, const LinearLocation& end);
+
+ ExtractLineByLocation(geom::Geometry *line);
+
+ /**
+ * Extracts a subline of the input.
+ * If <code>end < start</code> the linear geometry computed will be reversed.
+ *
+ * @param start the start location
+ * @param end the end location
+ * @return a linear geometry
+ */
+ geom::Geometry *extract(const LinearLocation& start, const LinearLocation& end);
+
+};
+}
+}
+#endif
Added: trunk/source/headers/geos/linearref/LengthIndexOfPoint.h
===================================================================
--- trunk/source/headers/geos/linearref/LengthIndexOfPoint.h (rev 0)
+++ trunk/source/headers/geos/linearref/LengthIndexOfPoint.h 2009-08-12 19:01:57 UTC (rev 2619)
@@ -0,0 +1,82 @@
+/**********************************************************************
+ * $Id: LengthIndexOfPoint.h 1938 2009-07-23 10:45:16Z novalis $
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.refractions.net
+ *
+ * Copyright (C) 2005-2006 Refractions Research Inc.
+ * Copyright (C) 2001-2002 Vivid Solutions Inc.
+ *
+ * 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/LengthIndexOfPoint.java rev. 1.10
+ *
+ **********************************************************************/
+
+#ifndef GEOS_LINEARREF_LENGTHINDEXOFPOINT_H
+#define GEOS_LINEARREF_LENGTHINDEXOFPOINT_H
+
+#include <string>
+
+#include <geos/geom/Coordinate.h>
+#include <geos/geom/Geometry.h>
+#include <geos/geom/LineSegment.h>
+#include <geos/linearref/LinearLocation.h>
+
+
+namespace geos
+{
+namespace linearref // geos::linearref
+{
+
+class LengthIndexOfPoint
+{
+
+private:
+ geom::Geometry *linearGeom;
+
+ double indexOfFromStart(geom::Coordinate& inputPt, double minIndex);
+
+ double segmentNearestMeasure(geom::LineSegment *seg, geom::Coordinate& inputPt,
+ double segmentStartMeasure);
+public:
+ static double indexOf(geom::Geometry *linearGeom, geom::Coordinate& inputPt);
+
+ static double indexOfAfter(geom::Geometry *linearGeom, geom::Coordinate& inputPt, double minIndex);
+
+ LengthIndexOfPoint(geom::Geometry *linearGeom);
+
+ /**
+ * Find the nearest location along a linear {@link Geometry} to a given point.
+ *
+ * @param inputPt the coordinate to locate
+ * @return the location of the nearest point
+ */
+ double indexOf(geom::Coordinate& inputPt);
+
+ /**
+ * Finds the nearest index along the linear {@link Geometry}
+ * to a given {@link Coordinate}
+ * after the specified minimum index.
+ * If possible the location returned will be strictly greater than the
+ * <code>minLocation</code>.
+ * If this is not possible, the
+ * value returned will equal <code>minLocation</code>.
+ * (An example where this is not possible is when
+ * minLocation = [end of line] ).
+ *
+ * @param inputPt the coordinate to locate
+ * @param minLocation the minimum location for the point location
+ * @return the location of the nearest point
+ */
+ double indexOfAfter(geom::Coordinate& inputPt, double minIndex);
+
+};
+}
+}
+#endif
Added: trunk/source/headers/geos/linearref/LengthIndexedLine.h
===================================================================
--- trunk/source/headers/geos/linearref/LengthIndexedLine.h (rev 0)
+++ trunk/source/headers/geos/linearref/LengthIndexedLine.h 2009-08-12 19:01:57 UTC (rev 2619)
@@ -0,0 +1,203 @@
+/**********************************************************************
+ * $Id: LengthIndexedLine.h 1938 2009-07-23 10:45:16Z novalis $
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.refractions.net
+ *
+ * Copyright (C) 2005-2006 Refractions Research Inc.
+ * Copyright (C) 2001-2002 Vivid Solutions Inc.
+ *
+ * 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/LengthIndexedLine.java rev. 1.10
+ *
+ **********************************************************************/
+
+#ifndef GEOS_LINEARREF_LENGTHINDEXEDLINE_H
+#define GEOS_LINEARREF_LENGTHINDEXEDLINE_H
+
+#include <geos/geom/Coordinate.h>
+#include <geos/geom/Geometry.h>
+#include <geos/linearref/LinearLocation.h>
+
+namespace geos
+{
+namespace linearref // geos::linearref
+{
+
+/** \brief
+ * Supports linear referencing along a linear {@link Geometry}
+ * using the length along the line as the index.
+ * Negative length values are taken as measured in the reverse direction
+ * from the end of the geometry.
+ * Out-of-range index values are handled by clamping
+ * them to the valid range of values.
+ * Non-simple lines (i.e. which loop back to cross or touch
+ * themselves) are supported.
+ */
+
+class LengthIndexedLine
+{
+private:
+ geom::Geometry *linearGeom;
+ LinearLocation locationOf(double index);
+
+public:
+
+ /** \brief
+ * Constructs an object which allows a linear {@link Geometry}
+ * to be linearly referenced using length as an index.
+ *
+ * @param linearGeom the linear geometry to reference along
+ */
+
+ LengthIndexedLine(geom::Geometry *linearGeom);
+
+ /** \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(double index);
+
+
+ /**
+ * 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(double index, double offsetDistance);
+
+ /**
+ * 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(double startIndex, double endIndex);
+
+
+ /**
+ * Computes the minimum index for a point on the line.
+ * If the line is not simple (i.e. loops back on itself)
+ * a single point may have more than one possible index.
+ * In this case, the smallest index is returned.
+ *
+ * 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 minimum index of the point
+ *
+ * @see project
+ */
+ double indexOf(geom::Coordinate& pt);
+
+ /**
+ * 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
+ */
+ double indexOfAfter(geom::Coordinate& pt, double minIndex);
+
+ /**
+ * 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 occcur in the same order).
+ *
+ * @param subLine a subLine of the line
+ * @return a pair of indices for the start and end of the subline.
+ */
+ double* indicesOf(geom::Geometry *subLine);
+
+
+ /**
+ * 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
+ */
+ double project(geom::Coordinate pt);
+
+ /**
+ * Returns the index of the start of the line
+ * @return the start index
+ */
+ double getStartIndex();
+
+ /**
+ * Returns the index of the end of the line
+ * @return the end index
+ */
+ double getEndIndex();
+
+ /**
+ * 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(double index);
+
+
+ /**
+ * Computes a valid index for this line
+ * by clamping the given index to the valid range of index values
+ *
+ * @return a valid index value
+ */
+ double clampIndex(double index);
+};
+}
+}
+#endif
Added: trunk/source/headers/geos/linearref/LengthLocationMap.h
===================================================================
--- trunk/source/headers/geos/linearref/LengthLocationMap.h (rev 0)
+++ trunk/source/headers/geos/linearref/LengthLocationMap.h 2009-08-12 19:01:57 UTC (rev 2619)
@@ -0,0 +1,91 @@
+/**********************************************************************
+ * $Id: LengthLocationMap.h 1938 2009-07-23 10:45:16Z novalis $
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.refractions.net
+ *
+ * Copyright (C) 2005-2006 Refractions Research Inc.
+ * Copyright (C) 2001-2002 Vivid Solutions Inc.
+ *
+ * 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/LengthLocationMap.java rev. 1.10
+ *
+ **********************************************************************/
+
+#ifndef GEOS_LINEARREF_LENGTHLOCATIONMAP_H
+#define GEOS_LINEARREF_LENGTHLOCATIONMAP_H
+
+#include <geos/geom/Coordinate.h>
+#include <geos/geom/Geometry.h>
+#include <geos/linearref/LinearLocation.h>
+
+namespace geos
+{
+namespace linearref // geos::linearref
+{
+
+/**
+ * Computes the {@link LinearLocation} for a given length
+ * along a linear {@link Geometry}.
+ * Negative lengths are measured in reverse from end of the linear geometry.
+ * Out-of-range values are clamped.
+ */
+class LengthLocationMap
+{
+
+
+private:
+ geom::Geometry *linearGeom;
+
+ LinearLocation getLocationForward(double length) const;
+
+public:
+
+ // TODO: cache computed cumulative length for each vertex
+ // TODO: support user-defined measures
+ // TODO: support measure index for fast mapping to a location
+
+ /**
+ * 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
+ * @return the {@link LinearLocation} for the length
+ */
+ static LinearLocation getLocation(geom::Geometry *linearGeom, double length);
+
+ /**
+ * Computes the length for a given {@link LinearLocation}
+ * on a linear {@link Geometry}.
+ *
+ * @param line the linear geometry to use
+ * @param loc the {@link LinearLocation} index of the location
+ * @return the length for the {@link LinearLocation}
+ */
+ static double getLength(geom::Geometry *linearGeom, const LinearLocation& loc);
+
+ LengthLocationMap(geom::Geometry *linearGeom);
+
+ /**
+ * 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.
+ *
+ * @param length the length index
+ * @return the corresponding LinearLocation
+ */
+ LinearLocation getLocation(double length) const;
+
+ double getLength(const LinearLocation& loc) const;
+
+};
+}
+}
+#endif
Added: trunk/source/headers/geos/linearref/LinearGeometryBuilder.h
===================================================================
--- trunk/source/headers/geos/linearref/LinearGeometryBuilder.h (rev 0)
+++ trunk/source/headers/geos/linearref/LinearGeometryBuilder.h 2009-08-12 19:01:57 UTC (rev 2619)
@@ -0,0 +1,98 @@
+/**********************************************************************
+ * $Id: LinearGeometryBuilder.h 1938 2009-07-23 10:45:16Z novalis $
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.refractions.net
+ *
+ * Copyright (C) 2005-2006 Refractions Research Inc.
+ * Copyright (C) 2001-2002 Vivid Solutions Inc.
+ *
+ * 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/LinearGeometryBuilder.java rev. 1.10
+ *
+ **********************************************************************/
+
+#ifndef GEOS_LINEARREF_LINEARGEOMETRYBUILDER_H
+#define GEOS_LINEARREF_LINEARGEOMETRYBUILDER_H
+
+#include <geos/geom/Coordinate.h>
+#include <geos/geom/CoordinateList.h>
+#include <geos/geom/Geometry.h>
+#include <geos/geom/GeometryFactory.h>
+#include <geos/linearref/LinearLocation.h>
+
+#include <vector>
+
+namespace geos
+{
+namespace linearref // geos::linearref
+{
+
+/**
+ * Builds a linear geometry ({@link LineString} or {@link MultiLineString})
+ * incrementally (point-by-point).
+ *
+ * @version 1.7
+ */
+class LinearGeometryBuilder
+{
+private:
+ const geom::GeometryFactory* geomFact;
+ std::vector<geom::Geometry *> lines;
+
+ bool ignoreInvalidLines;
+ bool fixInvalidLines;
+ geom::CoordinateSequence* coordList;
+
+ geom::Coordinate lastPt;
+
+public:
+ LinearGeometryBuilder(const geom::GeometryFactory* geomFact);
+
+ /**
+ * Allows invalid lines to be ignored rather than causing Exceptions.
+ * An invalid line is one which has only one unique point.
+ *
+ * @param ignoreShortLines <code>true</code> if short lines are to be ignored
+ */
+ void setIgnoreInvalidLines(bool ignoreInvalidLines);
+
+ /**
+ * Allows invalid lines to be ignored rather than causing Exceptions.
+ * An invalid line is one which has only one unique point.
+ *
+ * @param ignoreShortLines <code>true</code> if short lines are to be ignored
+ */
+ void setFixInvalidLines(bool fixInvalidLines);
+ /**
+ * Adds a point to the current line.
+ *
+ * @param pt the Coordinate to add
+ */
+ void add(const geom::Coordinate& pt);
+
+ /**
+ * Adds a point to the current line.
+ *
+ * @param pt the Coordinate to add
+ */
+ void add(const geom::Coordinate& pt, bool allowRepeatedPoints);
+
+ geom::Coordinate getLastCoordinate() const;
+
+ /**
+ * Terminate the current LineString.
+ */
+ void endLine();
+
+ geom::Geometry *getGeometry();
+};
+}
+}
+#endif
Added: trunk/source/headers/geos/linearref/LinearIterator.h
===================================================================
--- trunk/source/headers/geos/linearref/LinearIterator.h (rev 0)
+++ trunk/source/headers/geos/linearref/LinearIterator.h 2009-08-12 19:01:57 UTC (rev 2619)
@@ -0,0 +1,154 @@
+/**********************************************************************
+ * $Id: LinearIterator.h 1938 2009-07-23 10:45:16Z novalis $
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.refractions.net
+ *
+ * Copyright (C) 2005-2006 Refractions Research Inc.
+ * Copyright (C) 2001-2002 Vivid Solutions Inc.
+ *
+ * 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/LinearIterator.java rev. 1.10
+ *
+ **********************************************************************/
+
+#ifndef GEOS_LINEARREF_LINEARITERATOR_H
+#define GEOS_LINEARREF_LINEARITERATOR_H
+
+#include <string>
+
+#include <geos/geom/Coordinate.h>
+#include <geos/geom/Geometry.h>
+#include <geos/geom/LineSegment.h>
+#include <geos/linearref/LinearLocation.h>
+
+namespace geos
+{
+namespace linearref // geos::linearref
+{
+
+/**
+ * An iterator over the components and coordinates of a linear geometry
+ * ({@link LineString}s and {@link MultiLineString}s.
+ *
+ * The standard usage pattern for a {@link LinearIterator} is:
+ *
+ * <pre>
+ * for (LinearIterator it = new LinearIterator(...); it.hasNext(); it.next()) {
+ * ...
+ * int ci = it.getComponentIndex(); // for example
+ * int vi = it.getVertexIndex(); // for example
+ * ...
+ * }
+ * </pre>
+ *
+ * @version 1.7
+ */
+class LinearIterator
+{
+private:
+ static unsigned int segmentEndVertexIndex(const LinearLocation& loc);
+
+ const geom::LineString *currentLine;
+ unsigned int vertexIndex;
+ unsigned int componentIndex;
+ geom::Geometry *linear;
+ const unsigned int numLines;
+
+ /**
+ * Invariant: currentLine <> null if the iterator is pointing at a valid coordinate
+ */
+
+ void loadCurrentLine();
+
+
+public:
+ /**
+ * Creates an iterator initialized to the start of a linear {@link Geometry}
+ *
+ * @param linear the linear geometry to iterate over
+ */
+ LinearIterator(geom::Geometry *linear);
+
+ /**
+ * Creates an iterator starting at
+ * a {@link LinearLocation} on a linear {@link Geometry}
+ *
+ * @param linear the linear geometry to iterate over
+ * @param start the location to start at
+ */
+ LinearIterator(geom::Geometry *linear, const LinearLocation& start);
+
+ /**
+ * Creates an iterator starting at
+ * a component and vertex in a linear {@link Geometry}
+ *
+ * @param linear the linear geometry to iterate over
+ * @param componentIndex the component to start at
+ * @param vertexIndex the vertex to start at
+ */
+ LinearIterator(geom::Geometry *linear, unsigned int componentIndex, unsigned int vertexIndex);
+
+ /**
+ * Tests whether there are any vertices left to iterator over.
+ * @return <code>true</code> if there are more vertices to scan
+ */
+ bool hasNext() const;
+
+
+ /**
+ * Moves the iterator ahead to the next vertex and (possibly) linear component.
+ */
+ void next();
+
+ /**
+ * Checks whether the iterator cursor is pointing to the
+ * endpoint of a linestring.
+ *
+ * @return <code>true</true> if the iterator is at an endpoint
+ */
+ bool isEndOfLine() const;
+
+ /**
+ * The component index of the vertex the iterator is currently at.
+ * @return the current component index
+ */
+ unsigned int getComponentIndex() const;
+
+ /**
+ * The vertex index of the vertex the iterator is currently at.
+ * @return the current vertex index
+ */
+ unsigned int getVertexIndex() const;
+
+ /**
+ * Gets the {@link LineString} component the iterator is current at.
+ * @return a linestring
+ */
+ const geom::LineString* getLine() const;
+
+ /**
+ * Gets the first {@link Coordinate} of the current segment.
+ * (the coordinate of the current vertex).
+ * @return a {@link Coordinate}
+ */
+ geom::Coordinate getSegmentStart() const;
+
+ /**
+ * Gets the second {@link Coordinate} of the current segment.
+ * (the coordinate of the next vertex).
+ * If the iterator is at the end of a line, <code>null</code> is returned.
+ *
+ * @return a {@link Coordinate} or <code>null</code>
+ */
+ geom::Coordinate getSegmentEnd() const;
+};
+}
+}
+#endif
Added: trunk/source/headers/geos/linearref/LinearLocation.h
===================================================================
--- trunk/source/headers/geos/linearref/LinearLocation.h (rev 0)
+++ trunk/source/headers/geos/linearref/LinearLocation.h 2009-08-12 19:01:57 UTC (rev 2619)
@@ -0,0 +1,238 @@
+/**********************************************************************
+ * $Id: LinearLocation.h 1938 2009-07-23 10:45:16Z novalis $
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.refractions.net
+ *
+ * Copyright (C) 2005-2006 Refractions Research Inc.
+ * Copyright (C) 2001-2002 Vivid Solutions Inc.
+ *
+ * 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/LinearLocation.java rev. 1.10
+ *
+ **********************************************************************/
+
+#ifndef GEOS_LINEARREF_LINEARLOCATION_H
+#define GEOS_LINEARREF_LINEARLOCATION_H
+
+#include <string>
+
+#include <geos/geom/Coordinate.h>
+#include <geos/geom/Geometry.h>
+#include <geos/geom/LineSegment.h>
+
+namespace geos
+{
+namespace linearref // geos::linearref
+{
+
+
+/**
+ * Represents a location along a {@link LineString} or {@link MultiLineString}.
+ * The referenced geometry is not maintained within
+ * this location, but must be provided for operations which require it.
+ * Various methods are provided to manipulate the location value
+ * and query the geometry it references.
+ */
+class LinearLocation
+{
+private:
+ unsigned int componentIndex;
+ unsigned int segmentIndex;
+ double segmentFraction;
+
+ /**
+ * Ensures the individual values are locally valid.
+ * Does <b>not</b> ensure that the indexes are valid for
+ * a particular linear geometry.
+ *
+ * @see clamp
+ */
+ void normalize();
+
+public:
+ /**
+ * Gets a location which refers to the end of a linear {@link Geometry}.
+ * @param linear the linear geometry
+ * @return a new <tt>LinearLocation</tt>
+ */
+ static LinearLocation getEndLocation(geom::Geometry* linear);
+
+ /**
+ * Computes the {@link Coordinate} of a point a given fraction
+ * along the line segment <tt>(p0, p1)</tt>.
+ * If the fraction is greater than 1.0 the last
+ * point of the segment is returned.
+ * If the fraction is less than or equal to 0.0 the first point
+ * of the segment is returned.
+ * The Z ordinate is interpolated from the Z-ordinates of the given points,
+ * if they are specified.
+ *
+ * @param p0 the first point of the line segment
+ * @param p1 the last point of the line segment
+ * @param frac the length to the desired point
+ * @return the <tt>Coordinate</tt> of the desired point
+ */
+ static geom::Coordinate pointAlongSegmentByFraction(geom::Coordinate& p0, geom::Coordinate& p1, double frac);
+
+
+ /**
+ * Creates a location referring to the start of a linear geometry
+ */
+
+ LinearLocation(unsigned int segmentIndex = 0, double segmentFraction = 0.0);
+
+ LinearLocation(unsigned int componentIndex, unsigned int segmentIndex, double segmentFraction);
+
+ /**
+ * Ensures the indexes are valid for a given linear {@link Geometry}.
+ *
+ * @param linear a linear geometry
+ */
+ void clamp(geom::Geometry* linear);
+
+ /**
+ * Snaps the value of this location to
+ * the nearest vertex on the given linear {@link Geometry},
+ * if the vertex is closer than <tt>minDistance</tt>.
+ *
+ * @param linearGeom a linear geometry
+ * @param minDistance the minimum allowable distance to a vertex
+ */
+ void snapToVertex(geom::Geometry* linearGeom, double minDistance);
+
+ /**
+ * Gets the length of the segment in the given
+ * Geometry containing this location.
+ *
+ * @param linearGeom a linear geometry
+ * @return the length of the segment
+ */
+ double getSegmentLength(geom::Geometry* linearGeom) const;
+ /**
+ * Sets the value of this location to
+ * refer the end of a linear geometry
+ *
+ * @param linear the linear geometry to set
+ */
+ void setToEnd(geom::Geometry* linear);
+
+ /**
+ * Gets the component index for this location.
+ *
+ * @return the component index
+ */
+ unsigned int getComponentIndex() const;
+
+ /**
+ * Gets the segment index for this location
+ *
+ * @return the segment index
+ */
+ unsigned int getSegmentIndex() const;
+
+ /**
+ * Gets the segment fraction for this location
+ *
+ * @return the segment fraction
+ */
+ double getSegmentFraction() const;
+
+ /**
+ * Tests whether this location refers to a vertex
+ *
+ * @return true if the location is a vertex
+ */
+ bool isVertex() const;
+
+ /**
+ * Gets the {@link Coordinate} along the
+ * given linear {@link Geometry} which is
+ * referenced by this location.
+ *
+ * @param linearGeom a linear geometry
+ * @return the <tt>Coordinate</tt> at the location
+ */
+ geom::Coordinate getCoordinate(geom::Geometry* linearGeom) const;
+
+ /**
+ * Gets a {@link LineSegment} representing the segment of the
+ * given linear {@link Geometry} which contains this location.
+ *
+ * @param linearGeom a linear geometry
+ * @return the <tt>LineSegment</tt> containing the location
+ */
+ geom::LineSegment *getSegment(geom::Geometry* linearGeom) const;
+
+ /**
+ * Tests whether this location refers to a valid
+ * location on the given linear {@link Geometry}.
+ *
+ * @param linearGeom a linear geometry
+ * @return true if this location is valid
+ */
+ bool isValid(geom::Geometry* linearGeom) const;
+
+ /**
+ * Compares this object with the specified object for order.
+ *
+ *@param o the <code>LineStringLocation</code> with which this <code>Coordinate</code>
+ * is being compared
+ *@return a negative integer, zero, or a positive integer as this <code>LineStringLocation</code>
+ * is less than, equal to, or greater than the specified <code>LineStringLocation</code>
+ */
+ int compareTo(const LinearLocation& other) const;
+
+ /**
+ * Compares this object with the specified index values for order.
+ *
+ * @param componentIndex1 a component index
+ * @param segmentIndex1 a segment index
+ * @param segmentFraction1 a segment fraction
+ * @return a negative integer, zero, or a positive integer as this <code>LineStringLocation</code>
+ * is less than, equal to, or greater than the specified locationValues
+ */
+ int compareLocationValues(unsigned int componentIndex1, unsigned int segmentIndex1, double segmentFraction1) const;
+
+ /**
+ * Compares two sets of location values for order.
+ *
+ * @param componentIndex0 a component index
+ * @param segmentIndex0 a segment index
+ * @param segmentFraction0 a segment fraction
+ * @param componentIndex1 another component index
+ * @param segmentIndex1 another segment index
+ * @param segmentFraction1 another segment fraction
+ *@return a negative integer, zero, or a positive integer
+ * as the first set of location values
+ * is less than, equal to, or greater than the second set of locationValues
+ */
+ static int compareLocationValues(
+ unsigned int componentIndex0, unsigned int segmentIndex0, double segmentFraction0,
+ unsigned int componentIndex1, unsigned int segmentIndex1, double segmentFraction1);
+
+ /**
+ * Tests whether two locations
+ * are on the same segment in the parent {@link Geometry}.
+ *
+ * @param loc a location on the same geometry
+ * @return true if the locations are on the same segment of the parent geometry
+ */
+ bool isOnSameSegment(const LinearLocation& loc) const;
+
+
+ friend std::ostream& operator<< (std::ostream& out, const LinearLocation& obj );
+
+};
+
+
+}
+}
+
+#endif
Added: trunk/source/headers/geos/linearref/LocationIndexOfLine.h
===================================================================
--- trunk/source/headers/geos/linearref/LocationIndexOfLine.h (rev 0)
+++ trunk/source/headers/geos/linearref/LocationIndexOfLine.h 2009-08-12 19:01:57 UTC (rev 2619)
@@ -0,0 +1,62 @@
+/**********************************************************************
+ * $Id: LinearGeometryBuilder.h 1938 2009-07-23 10:45:16Z novalis $
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.refractions.net
+ *
+ * Copyright (C) 2005-2006 Refractions Research Inc.
+ * Copyright (C) 2001-2002 Vivid Solutions Inc.
+ *
+ * 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/LinearGeometryBuilder.java rev. 1.10
+ *
+ **********************************************************************/
+
+#ifndef GEOS_LINEARREF_LINEARGEOMETRYBUILDER_H
+#define GEOS_LINEARREF_LINEARGEOMETRYBUILDER_H
+
+#include <geos/geom/Coordinate.h>
+#include <geos/geom/Geometry.h>
+#include <geos/linearref/LinearLocation.h>
+
+namespace geos
+{
+namespace linearref // geos::linearref
+{
+
+/**
+ * Determines the location of a subline along a linear {@link Geometry}.
+ * The location is reported as a pair of {@link LinearLocation}s.
+ * <p>
+ * <b>Note:</b> Currently this algorithm is not guaranteed to
+ * return the correct substring in some situations where
+ * an endpoint of the test line occurs more than once in the input line.
+ * (However, the common case of a ring is always handled correctly).
+ */
+class LocationIndexOfLine
+{
+ /**
+ * MD - this algorithm has been extracted into a class
+ * because it is intended to validate that the subline truly is a subline,
+ * and also to use the internal vertex information to unambiguously locate the subline.
+ */
+private:
+ geom::Geometry* linearGeom;
+
+public:
+ static LinearLocation* indicesOf(geom::Geometry* linearGeom, geom::Geometry* subLine);
+
+ LocationIndexOfLine(geom::Geometry* linearGeom);
+
+ LinearLocation* indicesOf(geom::Geometry* subLine) const;
+};
+}
+}
+
+#endif
Added: trunk/source/headers/geos/linearref/LocationIndexOfPoint.h
===================================================================
--- trunk/source/headers/geos/linearref/LocationIndexOfPoint.h (rev 0)
+++ trunk/source/headers/geos/linearref/LocationIndexOfPoint.h 2009-08-12 19:01:57 UTC (rev 2619)
@@ -0,0 +1,81 @@
+/**********************************************************************
+ * $Id: LinearGeometryBuilder.h 1938 2009-07-23 10:45:16Z novalis $
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.refractions.net
+ *
+ * Copyright (C) 2005-2006 Refractions Research Inc.
+ * Copyright (C) 2001-2002 Vivid Solutions Inc.
+ *
+ * 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/LinearGeometryBuilder.java rev. 1.10
+ *
+ **********************************************************************/
+
+#ifndef GEOS_LINEARREF_LOCATIONINDEXOFPOINT_H
+#define GEOS_LINEARREF_LOCATIONINDEXOFPOINT_H
+
+#include <geos/geom/Coordinate.h>
+#include <geos/geom/Geometry.h>
+#include <geos/linearref/LinearLocation.h>
+
+namespace geos
+{
+namespace linearref // geos::linearref
+{
+
+/**
+ * Computes the {@link LinearLocation} of the point
+ * on a linear {@link Geometry} nearest a given {@link Coordinate}.
+ * The nearest point is not necessarily unique; this class
+ * always computes the nearest point closest to
+ * the start of the geometry.
+ */
+class LocationIndexOfPoint
+{
+
+private:
+ geom::Geometry *linearGeom;
+
+ LinearLocation indexOfFromStart(const geom::Coordinate& inputPt, LinearLocation* minIndex) const;
+
+public:
+ static LinearLocation indexOf(geom::Geometry *linearGeom, const geom::Coordinate& inputPt);
+
+ static LinearLocation indexOfAfter(geom::Geometry *linearGeom, const geom::Coordinate& inputPt, LinearLocation* minIndex);
+
+ LocationIndexOfPoint(geom::Geometry *linearGeom);
+
+ /**
+ * Find the nearest location along a linear {@link Geometry} to a given point.
+ *
+ * @param inputPt the coordinate to locate
+ * @return the location of the nearest point
+ */
+ LinearLocation indexOf(const geom::Coordinate& inputPt) const;
+ /**
+ * Find the nearest {@link LinearLocation} along the linear {@link Geometry}
+ * to a given {@link Coordinate}
+ * after the specified minimum {@link LinearLocation}.
+ * If possible the location returned will be strictly greater than the
+ * <code>minLocation</code>.
+ * If this is not possible, the
+ * value returned will equal <code>minLocation</code>.
+ * (An example where this is not possible is when
+ * minLocation = [end of line] ).
+ *
+ * @param inputPt the coordinate to locate
+ * @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;
+};
+}
+}
+#endif
Added: trunk/source/headers/geos/linearref/Makefile.am
===================================================================
--- trunk/source/headers/geos/linearref/Makefile.am (rev 0)
+++ trunk/source/headers/geos/linearref/Makefile.am 2009-08-12 19:01:57 UTC (rev 2619)
@@ -0,0 +1,15 @@
+
+EXTRA_DIST =
+
+geosdir = $(includedir)/geos/algorithm
+
+geos_HEADERS = \
+ ExtractLineByLocation.h \
+ LengthIndexedLine.h \
+ LengthIndexOfPoint.h \
+ LengthLocationMap.h \
+ LinearIterator.h \
+ LinearGeometryBuilder.h \
+ LinearLocation.h \
+ LocationIndexOfLine.h \
+ LocationIndexOfPoint.h
Added: trunk/source/linearref/ExtractLineByLocation.cpp
===================================================================
--- trunk/source/linearref/ExtractLineByLocation.cpp (rev 0)
+++ trunk/source/linearref/ExtractLineByLocation.cpp 2009-08-12 19:01:57 UTC (rev 2619)
@@ -0,0 +1,160 @@
+/**********************************************************************
+ * $Id: ExtractLineByLocation.cpp 1938 2006-12-07 10:45:16Z strk $
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.refractions.net
+ *
+ * Copyright (C) 2005-2006 Refractions Research Inc.
+ * Copyright (C) 2001-2002 Vivid Solutions Inc.
+ *
+ * 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/ExtractLineByLocation.java rev. 1.35
+ *
+ **********************************************************************/
+
+#include <geos/geom/Coordinate.h>
+#include <geos/geom/CoordinateArraySequence.h>
+#include <geos/geom/MultiLineString.h>
+#include <geos/geom/LineString.h>
+#include <geos/linearref/ExtractLineByLocation.h>
+#include <geos/linearref/LinearIterator.h>
+#include <geos/linearref/LinearLocation.h>
+#include <geos/linearref/LengthLocationMap.h>
+#include <geos/linearref/LengthIndexOfPoint.h>
+#include <geos/linearref/LinearGeometryBuilder.h>
+
+#include <cassert>
+#include <typeinfo>
+
+using namespace std;
+
+using namespace geos::geom;
+
+namespace geos
+{
+namespace linearref // geos.linearref
+{
+
+
+Geometry *ExtractLineByLocation::extract(Geometry *line, const LinearLocation& start, const LinearLocation& end)
+{
+ ExtractLineByLocation ls(line);
+ return ls.extract(start, end);
+}
+
+ExtractLineByLocation::ExtractLineByLocation(Geometry *line) :
+ line(line) {}
+
+
+Geometry *ExtractLineByLocation::extract(const LinearLocation& start, const LinearLocation& end)
+{
+ if (end.compareTo(start) < 0)
+ {
+ Geometry* backwards = computeLinear(end, start);
+ Geometry* forwards = reverse(backwards);
+ delete backwards;
+ return forwards;
+ }
+ return computeLinear(start, end);
+}
+
+Geometry *ExtractLineByLocation::reverse(Geometry *linear)
+{
+ LineString* ls = dynamic_cast<LineString *>(linear);
+ if (ls)
+ {
+ return ls->reverse();
+ }
+ else
+ {
+ MultiLineString* mls = dynamic_cast<MultiLineString *>(linear);
+ if (mls)
+ {
+ return mls->reverse();
+ }
+ else
+ {
+ assert(!"non-linear geometry encountered");
+ }
+ }
+}
+
+LineString* ExtractLineByLocation::computeLine(const LinearLocation& start, const LinearLocation& end)
+{
+ CoordinateSequence* coordinates = line->getCoordinates();
+ CoordinateArraySequence newCoordinateArray;
+
+ unsigned int startSegmentIndex = start.getSegmentIndex();
+ if (start.getSegmentFraction() > 0.0)
+ startSegmentIndex += 1;
+ unsigned int lastSegmentIndex = end.getSegmentIndex();
+ if (end.getSegmentFraction() == 1.0)
+ lastSegmentIndex += 1;
+ if (lastSegmentIndex >= coordinates->size())
+ lastSegmentIndex = coordinates->size() - 1;
+ // not needed - LinearLocation values should always be correct
+ //Assert.isTrue(end.getSegmentFraction() <= 1.0, "invalid segment fraction value");
+
+ if (! start.isVertex())
+ newCoordinateArray.add(start.getCoordinate(line));
+ for (unsigned int i = startSegmentIndex; i <= lastSegmentIndex; i++)
+ {
+ newCoordinateArray.add((*coordinates)[i]);
+ }
+ if (! end.isVertex())
+ newCoordinateArray.add(end.getCoordinate(line));
+
+ // ensure there is at least one coordinate in the result
+ if (newCoordinateArray.size() == 0)
+ newCoordinateArray.add(start.getCoordinate(line));
+
+ /**
+ * Ensure there is enough coordinates to build a valid line.
+ * Make a 2-point line with duplicate coordinates, if necessary.
+ * There will always be at least one coordinate in the coordList.
+ */
+ if (newCoordinateArray.size() <= 1)
+ {
+ newCoordinateArray.add(newCoordinateArray[0]);
+ }
+
+ return line->getFactory()->createLineString(newCoordinateArray);
+}
+
+Geometry *ExtractLineByLocation::computeLinear(const LinearLocation& start, const LinearLocation& end)
+{
+ LinearGeometryBuilder builder(line->getFactory());
+ builder.setFixInvalidLines(true);
+
+ if (! start.isVertex())
+ {
+ builder.add(start.getCoordinate(line));
+ }
+
+ for (LinearIterator it(line, start); it.hasNext(); it.next())
+ {
+ if (end.compareLocationValues(it.getComponentIndex(), it.getVertexIndex(), 0.0) < 0)
+ {
+ break;
+ }
+ Coordinate pt = it.getSegmentStart();
+ builder.add(pt);
+ if (it.isEndOfLine())
+ {
+ builder.endLine();
+ }
+ }
+ if (! end.isVertex())
+ {
+ builder.add(end.getCoordinate(line));
+ }
+ return builder.getGeometry();
+}
+}
+}
Added: trunk/source/linearref/LengthIndexOfPoint.cpp
===================================================================
--- trunk/source/linearref/LengthIndexOfPoint.cpp (rev 0)
+++ trunk/source/linearref/LengthIndexOfPoint.cpp 2009-08-12 19:01:57 UTC (rev 2619)
@@ -0,0 +1,124 @@
+/**********************************************************************
+ * $Id: LineIntersector.cpp 1938 2006-12-07 10:45:16Z strk $
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.refractions.net
+ *
+ * Copyright (C) 2005-2006 Refractions Research Inc.
+ * Copyright (C) 2001-2002 Vivid Solutions Inc.
+ *
+ * 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: algorithm/RobustLineIntersector.java rev. 1.35
+ *
+ **********************************************************************/
+
+#include <geos/linearref/ExtractLineByLocation.h>
+#include <geos/linearref/LengthIndexedLine.h>
+#include <geos/linearref/LinearIterator.h>
+#include <geos/linearref/LengthLocationMap.h>
+#include <geos/linearref/LengthIndexOfPoint.h>
+#include <geos/util/IllegalArgumentException.h>
+
+#include <limits>
+
+using namespace std;
+
+using namespace geos::geom;
+
+namespace geos
+{
+namespace linearref // geos.linearref
+{
+
+double LengthIndexOfPoint::indexOf(Geometry *linearGeom, Coordinate& inputPt)
+{
+ LengthIndexOfPoint locater(linearGeom);
+ return locater.indexOf(inputPt);
+}
+
+double LengthIndexOfPoint::indexOfAfter(Geometry *linearGeom, Coordinate& inputPt, double minIndex)
+{
+ LengthIndexOfPoint locater(linearGeom);
+ return locater.indexOfAfter(inputPt, minIndex);
+}
+
+LengthIndexOfPoint::LengthIndexOfPoint(Geometry *linearGeom):
+ linearGeom(linearGeom) {}
+
+double LengthIndexOfPoint::indexOf(Coordinate& inputPt)
+{
+ return indexOfFromStart(inputPt, -1.0);
+}
+
+
+double LengthIndexOfPoint::indexOfAfter(Coordinate& inputPt, double minIndex)
+{
+ if (minIndex < 0.0) return indexOf(inputPt);
+
+ // sanity check for minIndex at or past end of line
+ double endIndex = linearGeom->getLength();
+ if (endIndex < minIndex)
+ return endIndex;
+
+ double closestAfter = indexOfFromStart(inputPt, minIndex);
+ /**
+ * Return the minDistanceLocation found.
+ * This will not be null, since it was initialized to minLocation
+ */
+ if (closestAfter <= minIndex)
+ {
+ throw util::IllegalArgumentException("computed index is before specified minimum index");
+ }
+ return closestAfter;
+}
+
+double LengthIndexOfPoint::indexOfFromStart(Coordinate& inputPt, double minIndex)
+{
+ double minDistance = numeric_limits<double>::max();
+
+ double ptMeasure = minIndex;
+ double segmentStartMeasure = 0.0;
+ LineSegment seg;
+ LinearIterator it(linearGeom);
+ while (it.hasNext())
+ {
+ if (! it.isEndOfLine())
+ {
+ seg.p0 = it.getSegmentStart();
+ seg.p1 = it.getSegmentEnd();
+ double segDistance = seg.distance(inputPt);
+ double segMeasureToPt = segmentNearestMeasure(&seg, inputPt, segmentStartMeasure);
+ if (segDistance < minDistance
+ && segMeasureToPt > minIndex)
+ {
+ ptMeasure = segMeasureToPt;
+ minDistance = segDistance;
+ }
+ segmentStartMeasure += seg.getLength();
+ }
+ it.next();
+ }
+ return ptMeasure;
+}
+
+double LengthIndexOfPoint::segmentNearestMeasure(LineSegment* seg, Coordinate& inputPt,
+ double segmentStartMeasure)
+{
+ // found new minimum, so compute location distance of point
+ double projFactor = seg->projectionFactor(inputPt);
+ if (projFactor <= 0.0)
+ return segmentStartMeasure;
+ if (projFactor <= 1.0)
+ return segmentStartMeasure + projFactor * seg->getLength();
+ // projFactor > 1.0
+ return segmentStartMeasure + seg->getLength();
+}
+}
+}
+
Added: trunk/source/linearref/LengthIndexedLine.cpp
===================================================================
--- trunk/source/linearref/LengthIndexedLine.cpp (rev 0)
+++ trunk/source/linearref/LengthIndexedLine.cpp 2009-08-12 19:01:57 UTC (rev 2619)
@@ -0,0 +1,126 @@
+/**********************************************************************
+ * $Id: LengthIndexedLine.cpp 1938 2006-12-07 10:45:16Z strk $
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.refractions.net
+ *
+ * Copyright (C) 2005-2006 Refractions Research Inc.
+ * Copyright (C) 2001-2002 Vivid Solutions Inc.
+ *
+ * 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/LengthIndexedLine.java rev. 1.35
+ *
+ **********************************************************************/
+
+#include <geos/linearref/ExtractLineByLocation.h>
+#include <geos/linearref/LengthIndexedLine.h>
+#include <geos/linearref/LinearLocation.h>
+#include <geos/linearref/LengthLocationMap.h>
+#include <geos/linearref/LengthIndexOfPoint.h>
+#include <geos/linearref/LocationIndexOfLine.h>
+
+using namespace std;
+
+using namespace geos::geom;
+
+namespace geos
+{
+namespace linearref // geos.linearref
+{
+
+LengthIndexedLine::LengthIndexedLine(Geometry* linearGeom) :
+ linearGeom(linearGeom) {}
+
+Coordinate LengthIndexedLine::extractPoint(double index)
+{
+ LinearLocation loc = LengthLocationMap::getLocation(linearGeom, index);
+ Coordinate coord = loc.getCoordinate(linearGeom);
+ return coord;
+}
+
+Coordinate LengthIndexedLine::extractPoint(double index, double offsetDistance)
+{
+ LinearLocation loc = LengthLocationMap::getLocation(linearGeom, index);
+ Coordinate ret;
+ loc.getSegment(linearGeom)->pointAlongOffset(loc.getSegmentFraction(), offsetDistance, ret);
+ return ret;
+}
+
+
+Geometry *LengthIndexedLine::extractLine(double startIndex, double endIndex)
+{
+
+ LinearLocation startLoc = locationOf(startIndex);
+ LinearLocation endLoc = locationOf(endIndex);
+ Geometry* g = ExtractLineByLocation::extract(linearGeom, startLoc, endLoc);
+ return g;
+}
+
+LinearLocation LengthIndexedLine::locationOf(double index)
+{
+ return LengthLocationMap::getLocation(linearGeom, index);
+}
+
+
+double LengthIndexedLine::indexOf(Coordinate& pt)
+{
+ return LengthIndexOfPoint::indexOf(linearGeom, pt);
+}
+
+
+double LengthIndexedLine::indexOfAfter(Coordinate& pt, double minIndex)
+{
+ return LengthIndexOfPoint::indexOfAfter(linearGeom, pt, minIndex);
+}
+
+
+double* LengthIndexedLine::indicesOf(Geometry* subLine)
+{
+ LinearLocation* locIndex = LocationIndexOfLine::indicesOf(linearGeom, subLine);
+ double* index = new double[2];
+ index[0] = LengthLocationMap::getLength(linearGeom, locIndex[0]);
+ index[1] = LengthLocationMap::getLength(linearGeom, locIndex[1]);
+ delete locIndex;
+ return index;
+}
+
+
+double LengthIndexedLine::project(Coordinate pt)
+{
+ return LengthIndexOfPoint::indexOf(linearGeom, pt);
+}
+
+double LengthIndexedLine::getStartIndex()
+{
+ return 0.0;
+}
+
+double LengthIndexedLine::getEndIndex()
+{
+ return linearGeom->getLength();
+}
+
+bool LengthIndexedLine::isValidIndex(double index)
+{
+ return (index >= getStartIndex()
+ && index <= getEndIndex());
+}
+
+double LengthIndexedLine::clampIndex(double index)
+{
+ double startIndex = getStartIndex();
+ if (index < startIndex) return startIndex;
+
+ double endIndex = getEndIndex();
+ if (index > endIndex) return endIndex;
+
+ return index;
+}
+}
+}
Added: trunk/source/linearref/LengthLocationMap.cpp
===================================================================
--- trunk/source/linearref/LengthLocationMap.cpp (rev 0)
+++ trunk/source/linearref/LengthLocationMap.cpp 2009-08-12 19:01:57 UTC (rev 2619)
@@ -0,0 +1,122 @@
+/**********************************************************************
+ * $Id: LengthLocationMap.cpp 1938 2006-12-07 10:45:16Z strk $
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.refractions.net
+ *
+ * Copyright (C) 2005-2006 Refractions Research Inc.
+ * Copyright (C) 2001-2002 Vivid Solutions Inc.
+ *
+ * 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: algorithm/LengthLocationMap.java rev. 1.35
+ *
+ **********************************************************************/
+
+
+#include <geos/linearref/LengthIndexedLine.h>
+#include <geos/linearref/LinearIterator.h>
+#include <geos/linearref/LinearLocation.h>
+#include <geos/linearref/LengthLocationMap.h>
+
+using namespace std;
+
+using namespace geos::geom;
+
+namespace geos
+{
+namespace linearref // geos.linearref
+{
+
+
+LinearLocation LengthLocationMap::getLocation(Geometry* linearGeom, double length)
+{
+ LengthLocationMap locater(linearGeom);
+ return locater.getLocation(length);
+}
+
+double LengthLocationMap::getLength(Geometry* linearGeom, const LinearLocation& loc)
+{
+ LengthLocationMap locater(linearGeom);
+ return locater.getLength(loc);
+}
+
+
+LengthLocationMap::LengthLocationMap(Geometry* linearGeom) :
+ linearGeom(linearGeom) {}
+
+LinearLocation LengthLocationMap::getLocation(double length) const
+{
+ double forwardLength = length;
+ if (length < 0.0)
+ {
+ double lineLen = linearGeom->getLength();
+ forwardLength = lineLen + length;
+ }
+ return getLocationForward(forwardLength);
+}
+
+LinearLocation LengthLocationMap::getLocationForward(double length) const
+{
+ if (length <= 0.0)
+ return LinearLocation();
+
+ double totalLength = 0.0;
+
+ LinearIterator it (linearGeom);
+ while (it.hasNext())
+ {
+ if (! it.isEndOfLine())
+ {
+ Coordinate p0 = it.getSegmentStart();
+ Coordinate p1 = it.getSegmentEnd();
+ double segLen = p1.distance(p0);
+ // length falls in this segment
+ if (totalLength + segLen > length)
+ {
+ double frac = (length - totalLength) / segLen;
+ unsigned int compIndex = it.getComponentIndex();
+ unsigned int segIndex = it.getVertexIndex();
+ return LinearLocation(compIndex, segIndex, frac);
+ }
+ totalLength += segLen;
+ }
+ it.next();
+ }
+ // length is longer than line - return end location
+ return LinearLocation::getEndLocation(linearGeom);
+}
+
+
+double LengthLocationMap::getLength(const LinearLocation& loc) const
+{
+ double totalLength = 0.0;
+
+ LinearIterator it(linearGeom);
+ while (it.hasNext())
+ {
+ if (! it.isEndOfLine())
+ {
+ Coordinate p0 = it.getSegmentStart();
+ Coordinate p1 = it.getSegmentEnd();
+ double segLen = p1.distance(p0);
+ // length falls in this segment
+ if (loc.getComponentIndex() == it.getComponentIndex()
+ && loc.getSegmentIndex() == it.getVertexIndex())
+ {
+ return totalLength + segLen * loc.getSegmentFraction();
+ }
+ totalLength += segLen;
+ }
+ it.next();
+ }
+ return totalLength;
+}
+
+}
+}
Added: trunk/source/linearref/LinearGeometryBuilder.cpp
===================================================================
--- trunk/source/linearref/LinearGeometryBuilder.cpp (rev 0)
+++ trunk/source/linearref/LinearGeometryBuilder.cpp 2009-08-12 19:01:57 UTC (rev 2619)
@@ -0,0 +1,141 @@
+/**********************************************************************
+ * $Id: ExtractLineByLocation.cpp 1938 2006-12-07 10:45:16Z strk $
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.refractions.net
+ *
+ * Copyright (C) 2005-2006 Refractions Research Inc.
+ * Copyright (C) 2001-2002 Vivid Solutions Inc.
+ *
+ * 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/ExtractLineByLocation.java rev. 1.35
+ *
+ **********************************************************************/
+
+#include <geos/geom/CoordinateSequence.h>
+#include <geos/geom/CoordinateArraySequence.h>
+#include <geos/geom/LineString.h>
+#include <geos/linearref/ExtractLineByLocation.h>
+#include <geos/linearref/LengthIndexedLine.h>
+#include <geos/linearref/LinearLocation.h>
+#include <geos/linearref/LengthLocationMap.h>
+#include <geos/linearref/LengthIndexOfPoint.h>
+#include <geos/linearref/LinearGeometryBuilder.h>
+#include <geos/util/IllegalArgumentException.h>
+
+using namespace std;
+
+using namespace geos::geom;
+
+namespace geos
+{
+namespace linearref // geos.linearref
+{
+
+LinearGeometryBuilder::LinearGeometryBuilder(const GeometryFactory* geomFact) :
+ geomFact(geomFact),
+ ignoreInvalidLines(false),
+ fixInvalidLines(false),
+ coordList(0) {}
+
+void LinearGeometryBuilder::setIgnoreInvalidLines(bool ignoreInvalidLines)
+{
+ this->ignoreInvalidLines = ignoreInvalidLines;
+}
+
+/**
+ * Allows invalid lines to be ignored rather than causing Exceptions.
+ * An invalid line is one which has only one unique point.
+ *
+ * @param ignoreShortLines <code>true</code> if short lines are to be ignored
+ */
+void LinearGeometryBuilder::setFixInvalidLines(bool fixInvalidLines)
+{
+ this->fixInvalidLines = fixInvalidLines;
+}
+
+/**
+ * Adds a point to the current line.
+ *
+ * @param pt the Coordinate to add
+ */
+void LinearGeometryBuilder::add(const Coordinate& pt)
+{
+ add(pt, true);
+}
+
+/**
+ * Adds a point to the current line.
+ *
+ * @param pt the Coordinate to add
+ */
+void LinearGeometryBuilder::add(const Coordinate& pt, bool allowRepeatedPoints)
+{
+ if (!coordList)
+ coordList = new CoordinateArraySequence();
+ coordList->add(pt, allowRepeatedPoints);
+ lastPt = pt;
+}
+
+Coordinate LinearGeometryBuilder::getLastCoordinate() const
+{
+ return lastPt;
+}
+
+/**
+ * Terminate the current LineString.
+ */
+void LinearGeometryBuilder::endLine()
+{
+ if (!coordList)
+ {
+ return;
+ }
+ if (coordList->size() < 2)
+ {
+ if (ignoreInvalidLines)
+ {
+ if (coordList)
+ {
+ delete coordList;
+ coordList = 0;
+ }
+ return;
+ }
+ else if (fixInvalidLines)
+ {
+ add((*coordList)[0]);
+ }
+ }
+
+ LineString* line = 0;
+ try
+ {
+ line = geomFact->createLineString(coordList);
+ }
+ catch (util::IllegalArgumentException ex)
+ {
+ // exception is due to too few points in line.
+ // only propagate if not ignoring short lines
+ if (! ignoreInvalidLines)
+ throw ex;
+ }
+
+ if (line) lines.push_back(line);
+ coordList = 0;
+}
+
+Geometry* LinearGeometryBuilder::getGeometry()
+{
+ // end last line in case it was not done by user
+ endLine();
+ return geomFact->buildGeometry(lines);
+}
+}
+}
Added: trunk/source/linearref/LinearIterator.cpp
===================================================================
--- trunk/source/linearref/LinearIterator.cpp (rev 0)
+++ trunk/source/linearref/LinearIterator.cpp 2009-08-12 19:01:57 UTC (rev 2619)
@@ -0,0 +1,141 @@
+/**********************************************************************
+ * $Id: LinearIterator.cpp 1938 2006-12-07 10:45:16Z strk $
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.refractions.net
+ *
+ * Copyright (C) 2005-2006 Refractions Research Inc.
+ * Copyright (C) 2001-2002 Vivid Solutions Inc.
+ *
+ * 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/LinearIterator.java rev. 1.35
+ *
+ **********************************************************************/
+
+
+#include <geos/geom/LineString.h>
+#include <geos/linearref/LinearIterator.h>
+#include <geos/linearref/LinearLocation.h>
+#include <geos/linearref/LengthLocationMap.h>
+
+using namespace geos::geom;
+
+namespace geos
+{
+namespace linearref // geos.linearref
+{
+
+unsigned int LinearIterator::segmentEndVertexIndex(const LinearLocation& loc)
+{
+ if (loc.getSegmentFraction() > 0.0)
+ return loc.getSegmentIndex() + 1;
+ return loc.getSegmentIndex();
+}
+
+LinearIterator::LinearIterator(Geometry* linear) :
+ vertexIndex(0),
+ componentIndex(0),
+ linear(linear),
+ numLines(linear->getNumGeometries())
+{
+ loadCurrentLine();
+}
+
+
+LinearIterator::LinearIterator(Geometry* linear, const LinearLocation& start):
+ vertexIndex(segmentEndVertexIndex(start)),
+ componentIndex(start.getComponentIndex()),
+ linear(linear),
+ numLines(linear->getNumGeometries())
+{
+ loadCurrentLine();
+}
+
+LinearIterator::LinearIterator(Geometry* linear, unsigned int componentIndex, unsigned int vertexIndex) :
+ vertexIndex(vertexIndex),
+ componentIndex(componentIndex),
+ linear(linear),
+ numLines(linear->getNumGeometries())
+{
+ loadCurrentLine();
+}
+
+void LinearIterator::loadCurrentLine()
+{
+ if (componentIndex >= numLines)
+ {
+ currentLine = 0;
+ return;
+ }
+ currentLine = dynamic_cast<const LineString *> (linear->getGeometryN(componentIndex));
+}
+
+bool LinearIterator::hasNext() const
+{
+ if (componentIndex >= numLines) return false;
+ if (componentIndex == numLines - 1
+ && vertexIndex >= currentLine->getNumPoints())
+ return false;
+ return true;
+}
+
+void LinearIterator::next()
+{
+ if (! hasNext()) return;
+
+ vertexIndex++;
+ if (vertexIndex >= currentLine->getNumPoints())
+ {
+ componentIndex++;
+ loadCurrentLine();
+ vertexIndex = 0;
+ }
+}
+
+bool LinearIterator::isEndOfLine() const
+{
+ if (componentIndex >= numLines) return false;
+ //LineString currentLine = (LineString) linear.getGeometryN(componentIndex);
+ if (!currentLine)
+ return false;
+ if (vertexIndex < currentLine->getNumPoints() - 1)
+ return false;
+ return true;
+}
+
+unsigned int LinearIterator::getComponentIndex() const
+{
+ return componentIndex;
+}
+
+unsigned int LinearIterator::getVertexIndex() const
+{
+ return vertexIndex;
+}
+
+const LineString* LinearIterator::getLine() const
+{
+ return currentLine;
+}
+
+Coordinate LinearIterator::getSegmentStart() const
+{
+ return currentLine->getCoordinateN(vertexIndex);
+}
+
+Coordinate LinearIterator::getSegmentEnd() const
+{
+ if (vertexIndex < getLine()->getNumPoints() - 1)
+ return currentLine->getCoordinateN(vertexIndex + 1);
+ Coordinate c;
+ c.setNull();
+ return c;
+}
+}
+}
Added: trunk/source/linearref/LinearLocation.cpp
===================================================================
--- trunk/source/linearref/LinearLocation.cpp (rev 0)
+++ trunk/source/linearref/LinearLocation.cpp 2009-08-12 19:01:57 UTC (rev 2619)
@@ -0,0 +1,284 @@
+/**********************************************************************
+ * $Id: LinearLocation.cpp 1938 2006-12-07 10:45:16Z strk $
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.refractions.net
+ *
+ * Copyright (C) 2005-2006 Refractions Research Inc.
+ * Copyright (C) 2001-2002 Vivid Solutions Inc.
+ *
+ * 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/LinearLocation.java rev. 1.35
+ *
+ **********************************************************************/
+
+#include <geos/geom/LineString.h>
+#include <geos/linearref/LengthIndexedLine.h>
+#include <geos/linearref/LinearLocation.h>
+#include <geos/linearref/LengthLocationMap.h>
+
+using namespace std;
+
+using namespace geos::geom;
+
+namespace geos
+{
+namespace linearref // geos.linearref
+{
+
+LinearLocation LinearLocation::getEndLocation(Geometry* linear)
+{
+ // assert: linear is LineString or MultiLineString
+ LinearLocation loc;
+ loc.setToEnd(linear);
+ return loc;
+}
+
+Coordinate LinearLocation::pointAlongSegmentByFraction(Coordinate& p0, Coordinate& p1, double frac)
+{
+ if (frac <= 0.0) return p0;
+ if (frac >= 1.0) return p1;
+
+ double x = (p1.x - p0.x) * frac + p0.x;
+ double y = (p1.y - p0.y) * frac + p0.y;
+ // interpolate Z value. If either input Z is NaN, result z will be NaN as well.
+ double z = (p1.z - p0.z) * frac + p0.z;
+ return Coordinate(x, y, z);
+}
+
+LinearLocation::LinearLocation(unsigned int segmentIndex, double segmentFraction) :
+ componentIndex(0), segmentIndex(segmentIndex), segmentFraction(segmentFraction) {}
+
+
+LinearLocation::LinearLocation(unsigned int componentIndex, unsigned int segmentIndex, double segmentFraction):
+ componentIndex(componentIndex), segmentIndex(segmentIndex), segmentFraction(segmentFraction)
+{
+ normalize();
+}
+
+void LinearLocation::normalize()
+{
+ if (segmentFraction < 0.0)
+ {
+ segmentFraction = 0.0;
+ }
+ if (segmentFraction > 1.0)
+ {
+ segmentFraction = 1.0;
+ }
+
+ if (componentIndex < 0)
+ {
+ componentIndex = 0;
+ segmentIndex = 0;
+ segmentFraction = 0.0;
+ }
+ if (segmentIndex < 0)
+ {
+ segmentIndex = 0;
+ segmentFraction = 0.0;
+ }
+ if (segmentFraction == 1.0)
+ {
+ segmentFraction = 0.0;
+ segmentIndex += 1;
+ }
+}
+
+
+
+void LinearLocation::clamp(Geometry* linear)
+{
+ if (componentIndex >= linear->getNumGeometries())
+ {
+ setToEnd(linear);
+ return;
+ }
+ if (segmentIndex >= linear->getNumPoints())
+ {
+ const LineString* line = dynamic_cast<const LineString*> (linear->getGeometryN(componentIndex));
+ segmentIndex = line->getNumPoints() - 1;
+ segmentFraction = 1.0;
+ }
+}
+
+void LinearLocation::snapToVertex(Geometry* linearGeom, double minDistance)
+{
+ if (segmentFraction <= 0.0 || segmentFraction >= 1.0)
+ return;
+ double segLen = getSegmentLength(linearGeom);
+ double lenToStart = segmentFraction * segLen;
+ double lenToEnd = segLen - lenToStart;
+ if (lenToStart <= lenToEnd && lenToStart < minDistance)
+ {
+ segmentFraction = 0.0;
+ }
+ else if (lenToEnd <= lenToStart && lenToEnd < minDistance)
+ {
+ segmentFraction = 1.0;
+ }
+}
+
+double LinearLocation::getSegmentLength(Geometry* linearGeom) const
+{
+ const LineString* lineComp = dynamic_cast<const LineString*> (linearGeom->getGeometryN(componentIndex));
+
+ // ensure segment index is valid
+ unsigned int segIndex = segmentIndex;
+ if (segmentIndex >= lineComp->getNumPoints() - 1)
+ segIndex = lineComp->getNumPoints() - 2;
+
+ Coordinate p0 = lineComp->getCoordinateN(segIndex);
+ Coordinate p1 = lineComp->getCoordinateN(segIndex + 1);
+ return p0.distance(p1);
+}
+
+void LinearLocation::setToEnd(Geometry* linear)
+{
+ componentIndex = linear->getNumGeometries() - 1;
+ const LineString* lastLine = dynamic_cast<const LineString*>(linear->getGeometryN(componentIndex));
+ segmentIndex = lastLine->getNumPoints() - 1;
+ segmentFraction = 1.0;
+}
+
+unsigned int LinearLocation::getComponentIndex() const
+{
+ return componentIndex;
+}
+
+unsigned int LinearLocation::getSegmentIndex() const
+{
+ return segmentIndex;
+}
+
+double LinearLocation::getSegmentFraction() const
+{
+ return segmentFraction;
+}
+
+bool LinearLocation::isVertex() const
+{
+ return segmentFraction <= 0.0 || segmentFraction >= 1.0;
+}
+
+Coordinate LinearLocation::getCoordinate(Geometry* linearGeom) const
+{
+ const LineString* lineComp = dynamic_cast<const LineString *> (linearGeom->getGeometryN(componentIndex));
+ Coordinate p0 = lineComp->getCoordinateN(segmentIndex);
+ if (segmentIndex >= lineComp->getNumPoints() - 1)
+ return p0;
+ Coordinate p1 = lineComp->getCoordinateN(segmentIndex + 1);
+ return pointAlongSegmentByFraction(p0, p1, segmentFraction);
+}
+
+LineSegment* LinearLocation::getSegment(Geometry* linearGeom) const
+{
+ const LineString* lineComp = dynamic_cast<const LineString *> (linearGeom->getGeometryN(componentIndex));
+ Coordinate p0 = lineComp->getCoordinateN(segmentIndex);
+ // check for endpoint - return last segment of the line if so
+ if (segmentIndex >= lineComp->getNumPoints() - 1)
+ {
+ Coordinate prev = lineComp->getCoordinateN(lineComp->getNumPoints() - 2);
+ return new LineSegment(prev, p0);
+ }
+ Coordinate p1 = lineComp->getCoordinateN(segmentIndex + 1);
+ return new LineSegment(p0, p1);
+}
+
+
+bool LinearLocation::isValid(Geometry* linearGeom) const
+{
+ if (componentIndex < 0 || componentIndex >= linearGeom->getNumGeometries())
+ return false;
+
+ const LineString* lineComp = dynamic_cast<const LineString*> (linearGeom->getGeometryN(componentIndex));
+ if (segmentIndex < 0 || segmentIndex > lineComp->getNumPoints())
+ return false;
+ if (segmentIndex == lineComp->getNumPoints() && segmentFraction != 0.0)
+ return false;
+
+ if (segmentFraction < 0.0 || segmentFraction > 1.0)
+ return false;
+ return true;
+}
+
+
+int LinearLocation::compareTo(const LinearLocation& other) const
+{
+ // compare component indices
+ if (componentIndex < other.componentIndex) return -1;
+ if (componentIndex > other.componentIndex) return 1;
+ // compare segments
+ if (segmentIndex < other.segmentIndex) return -1;
+ if (segmentIndex > other.segmentIndex) return 1;
+ // same segment, so compare segment fraction
+ if (segmentFraction < other.segmentFraction) return -1;
+ if (segmentFraction > other.segmentFraction) return 1;
+ // same location
+ return 0;
+}
+
+
+int LinearLocation::compareLocationValues(unsigned int componentIndex1, unsigned int segmentIndex1, double segmentFraction1) const
+{
+ // compare component indices
+ if (componentIndex < componentIndex1) return -1;
+ if (componentIndex > componentIndex1) return 1;
+ // compare segments
+ if (segmentIndex < segmentIndex1) return -1;
+ if (segmentIndex > segmentIndex1) return 1;
+ // same segment, so compare segment fraction
+ if (segmentFraction < segmentFraction1) return -1;
+ if (segmentFraction > segmentFraction1) return 1;
+ // same location
+ return 0;
+}
+
+
+int LinearLocation::compareLocationValues(
+ unsigned int componentIndex0, unsigned int segmentIndex0, double segmentFraction0,
+ unsigned int componentIndex1, unsigned int segmentIndex1, double segmentFraction1)
+{
+ // compare component indices
+ if (componentIndex0 < componentIndex1) return -1;
+ if (componentIndex0 > componentIndex1) return 1;
+ // compare segments
+ if (segmentIndex0 < segmentIndex1) return -1;
+ if (segmentIndex0 > segmentIndex1) return 1;
+ // same segment, so compare segment fraction
+ if (segmentFraction0 < segmentFraction1) return -1;
+ if (segmentFraction0 > segmentFraction1) return 1;
+ // same location
+ return 0;
+}
+
+
+bool LinearLocation::isOnSameSegment(const LinearLocation& loc) const
+{
+ if (componentIndex != loc.componentIndex) return false;
+ if (segmentIndex == loc.segmentIndex) return true;
+ if (loc.segmentIndex - segmentIndex == 1
+ && loc.segmentFraction == 0.0)
+ return true;
+ if (segmentIndex - loc.segmentIndex == 1
+ && segmentFraction == 0.0)
+ return true;
+ return false;
+}
+
+
+ostream& operator<<(ostream &out, const LinearLocation &obj)
+{
+ return out << "LinearLocation(" << obj.componentIndex << ", " <<
+ obj.segmentIndex << ", " << obj.segmentFraction << ")";
+}
+
+}
+}
+
Added: trunk/source/linearref/LocationIndexOfLine.cpp
===================================================================
--- trunk/source/linearref/LocationIndexOfLine.cpp (rev 0)
+++ trunk/source/linearref/LocationIndexOfLine.cpp 2009-08-12 19:01:57 UTC (rev 2619)
@@ -0,0 +1,77 @@
+/**********************************************************************
+ * $Id: LengthIndexedLine.cpp 1938 2006-12-07 10:45:16Z strk $
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.refractions.net
+ *
+ * Copyright (C) 2005-2006 Refractions Research Inc.
+ * Copyright (C) 2001-2002 Vivid Solutions Inc.
+ *
+ * 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/LengthIndexedLine.java rev. 1.35
+ *
+ **********************************************************************/
+
+#include <geos/geom/Geometry.h>
+#include <geos/geom/LineString.h>
+#include <geos/linearref/LinearLocation.h>
+#include <geos/linearref/LocationIndexOfLine.h>
+#include <geos/linearref/LocationIndexOfPoint.h>
+
+using namespace std;
+
+using namespace geos::geom;
+
+namespace geos
+{
+namespace linearref // geos.linearref
+{
+
+/**
+ * Determines the location of a subline along a linear {@link Geometry}.
+ * The location is reported as a pair of {@link LinearLocation}s.
+ * <p>
+ * <b>Note:</b> Currently this algorithm is not guaranteed to
+ * return the correct substring in some situations where
+ * an endpoint of the test line occurs more than once in the input line.
+ * (However, the common case of a ring is always handled correctly).
+ */
+
+LinearLocation* LocationIndexOfLine::indicesOf(Geometry* linearGeom, Geometry* subLine)
+{
+ LocationIndexOfLine locater(linearGeom);
+ return locater.indicesOf(subLine);
+}
+
+LocationIndexOfLine::LocationIndexOfLine(Geometry* linearGeom) :
+ linearGeom(linearGeom) {}
+
+LinearLocation* LocationIndexOfLine::indicesOf(Geometry* subLine) const
+{
+ Coordinate startPt = dynamic_cast<const LineString*> (subLine->getGeometryN(0))->getCoordinateN(0);
+ const LineString* lastLine = dynamic_cast<const LineString*> (subLine->getGeometryN(subLine->getNumGeometries() - 1));
+ Coordinate endPt = lastLine->getCoordinateN(lastLine->getNumPoints() - 1);
+
+ LocationIndexOfPoint locPt(linearGeom);
+ LinearLocation *subLineLoc = new LinearLocation[2];
+ subLineLoc[0] = locPt.indexOf(startPt);
+
+ // check for case where subline is zero length
+ if (subLine->getLength() == 0.0)
+ {
+ subLineLoc[1] = subLineLoc[0];
+ }
+ else
+ {
+ subLineLoc[1] = locPt.indexOfAfter(endPt, &subLineLoc[0]);
+ }
+ return subLineLoc;
+}
+}
+}
Added: trunk/source/linearref/LocationIndexOfPoint.cpp
===================================================================
--- trunk/source/linearref/LocationIndexOfPoint.cpp (rev 0)
+++ trunk/source/linearref/LocationIndexOfPoint.cpp 2009-08-12 19:01:57 UTC (rev 2619)
@@ -0,0 +1,122 @@
+/**********************************************************************
+ * $Id: LocationIndexOfPoint.cpp 1938 2006-12-07 10:45:16Z strk $
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.refractions.net
+ *
+ * Copyright (C) 2005-2006 Refractions Research Inc.
+ * Copyright (C) 2001-2002 Vivid Solutions Inc.
+ *
+ * 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/LocationIndexOfPoint.java rev. 1.35
+ *
+ **********************************************************************/
+
+
+#include <geos/geom/LineSegment.h>
+#include <geos/linearref/LinearIterator.h>
+#include <geos/linearref/LinearLocation.h>
+#include <geos/linearref/LocationIndexOfPoint.h>
+#include <geos/util/IllegalArgumentException.h>
+
+#include <cassert>
+#include <limits>
+
+using namespace std;
+
+using namespace geos::geom;
+
+namespace geos
+{
+namespace linearref // geos.linearref
+{
+
+LinearLocation LocationIndexOfPoint::indexOfFromStart(const Coordinate& inputPt, LinearLocation* minIndex) const
+{
+ double minDistance = numeric_limits<double>::max();
+ int minComponentIndex = 0;
+ int minSegmentIndex = 0;
+ double minFrac = -1.0;
+
+ LineSegment seg;
+ for (LinearIterator it(linearGeom);
+ it.hasNext(); it.next())
+ {
+ if (! it.isEndOfLine())
+ {
+ seg.p0 = it.getSegmentStart();
+ seg.p1 = it.getSegmentEnd();
+ double segDistance = seg.distance(inputPt);
+ double segFrac = seg.segmentFraction(inputPt);
+
+ int candidateComponentIndex = it.getComponentIndex();
+ int candidateSegmentIndex = it.getVertexIndex();
+ if (segDistance < minDistance)
+ {
+ // ensure after minLocation, if any
+ if (!minIndex ||
+ minIndex->compareLocationValues(candidateComponentIndex, candidateSegmentIndex, segFrac) < 0)
+ {
+ // otherwise, save this as new minimum
+ minComponentIndex = candidateComponentIndex;
+ minSegmentIndex = candidateSegmentIndex;
+ minFrac = segFrac;
+ minDistance = segDistance;
+ }
+ }
+ }
+ }
+ LinearLocation loc(minComponentIndex, minSegmentIndex, minFrac);
+ return loc;
+}
+
+
+LinearLocation LocationIndexOfPoint::indexOf(Geometry *linearGeom, const Coordinate& inputPt)
+{
+ LocationIndexOfPoint locater(linearGeom);
+ return locater.indexOf(inputPt);
+}
+
+LinearLocation LocationIndexOfPoint::indexOfAfter(Geometry *linearGeom, const Coordinate& inputPt, LinearLocation* minIndex)
+{
+ LocationIndexOfPoint locater(linearGeom);
+ return locater.indexOfAfter(inputPt, minIndex);
+}
+
+LocationIndexOfPoint::LocationIndexOfPoint(Geometry *linearGeom) :
+ linearGeom(linearGeom)
+{}
+
+LinearLocation LocationIndexOfPoint::indexOf(const Coordinate& inputPt) const
+{
+ return indexOfFromStart(inputPt, 0);
+}
+
+LinearLocation LocationIndexOfPoint::indexOfAfter(const Coordinate& inputPt, LinearLocation* minIndex) const
+{
+ if (!minIndex) return indexOf(inputPt);
+
+ // sanity check for minLocation at or past end of line
+ LinearLocation endLoc = LinearLocation::getEndLocation(linearGeom);
+ if (endLoc.compareTo(*minIndex) <= 0)
+ return endLoc;
+
+ LinearLocation closestAfter = indexOfFromStart(inputPt, minIndex);
+ /**
+ * Return the minDistanceLocation found.
+ * This will not be null, since it was initialized to minLocation
+ */
+ if (closestAfter.compareTo(*minIndex) < 0)
+ {
+ throw util::IllegalArgumentException("computed location is before specified minimum location");
+ }
+ return closestAfter;
+}
+}
+}
Added: trunk/source/linearref/Makefile.am
===================================================================
--- trunk/source/linearref/Makefile.am (rev 0)
+++ trunk/source/linearref/Makefile.am 2009-08-12 19:01:57 UTC (rev 2619)
@@ -0,0 +1,20 @@
+
+noinst_LTLIBRARIES = liblinearref.la
+
+INCLUDES = -I$(top_srcdir)/source/headers
+
+liblinearref_la_SOURCES = \
+ ExtractLineByLocation.cpp \
+ LengthIndexedLine.cpp \
+ LengthIndexOfPoint.cpp \
+ LengthLocationMap.cpp \
+ LinearIterator.cpp \
+ LinearGeometryBuilder.cpp \
+ LinearLocation.cpp \
+ LocationIndexOfLine.cpp \
+ LocationIndexOfPoint.cpp
+
+# Deprecated files
+# (http://geos.refractions.net/pipermail/geos-devel/2006-March/001828.html):
+#NonRobustLineIntersector.cpp
+#RobustLineIntersector.cpp
Modified: trunk/tests/unit/Makefile.am
===================================================================
--- trunk/tests/unit/Makefile.am 2009-08-02 23:39:51 UTC (rev 2618)
+++ trunk/tests/unit/Makefile.am 2009-08-12 19:01:57 UTC (rev 2619)
@@ -61,6 +61,7 @@
index/quadtree/DoubleBitsTest.cpp \
io/ByteOrderValuesTest.cpp \
io/WKBReaderTest.cpp \
+ linearref/LengthIndexedLineTest.cpp \
noding/BasicSegmentStringTest.cpp \
noding/NodedSegmentStringTest.cpp \
noding/SegmentNodeTest.cpp \
Added: trunk/tests/unit/linearref/LengthIndexedLineTest.cpp
===================================================================
--- trunk/tests/unit/linearref/LengthIndexedLineTest.cpp (rev 0)
+++ trunk/tests/unit/linearref/LengthIndexedLineTest.cpp 2009-08-12 19:01:57 UTC (rev 2619)
@@ -0,0 +1,414 @@
+// $Id$
+//
+// Ported from JTS junit/linearref/AbstractIndexedLineTest.java rev. 1.10
+// and junit/linearref/LengthIndexedLineTest.java rev. 1.10
+
+#include <tut.hpp>
+#include <utility.h>
+// geos
+#include <geos/io/WKTReader.h>
+#include <geos/geom/PrecisionModel.h>
+#include <geos/geom/GeometryFactory.h>
+#include <geos/geom/Geometry.h> // required for use in auto_ptr
+#include <geos/geom/LineString.h>
+#include <geos/geom/Coordinate.h>
+#include <geos/linearref/LengthIndexedLine.h>
+
+// std
+#include <sstream>
+#include <string>
+#include <memory>
+
+using namespace geos::geom;
+using namespace geos::linearref;
+using namespace std;
+
+/**
+ * Tests the {@link LocationIndexedLine} class
+ */
+
+namespace tut {
+
+ typedef auto_ptr<Geometry> GeomPtr;
+ static const double TOLERANCE_DIST = 0.001;
+
+ struct test_lengthindexedline_data {
+
+ test_lengthindexedline_data()
+ :
+ pm(),
+ gf(&pm),
+ reader(&gf)
+ {
+ }
+
+ PrecisionModel pm;
+ GeometryFactory gf;
+ geos::io::WKTReader reader;
+
+ void checkExpected(Geometry* result, const string expected)
+ {
+ GeomPtr subLine(reader.read(expected));
+ ensure_equals_geometry(subLine.get(), result);
+ }
+
+ void checkExpected(Geometry* result, const Geometry* expected)
+ {
+ ensure_equals_geometry(expected, result);
+ }
+
+ void runIndicesOfThenExtract(string inputStr,
+ string subLineStr)
+ {
+ GeomPtr input(reader.read(inputStr));
+ GeomPtr subLine(reader.read(subLineStr));
+ GeomPtr result(indicesOfThenExtract(input.get(), subLine.get()));
+
+ checkExpected(result.get(), subLine.get());
+ }
+
+
+/*
+ // example of indicesOfThenLocate method
+ private Geometry indicesOfThenLocate(LineString input, LineString subLine)
+ {
+ LocationIndexedLine indexedLine = new LocationIndexedLine(input);
+ LineStringLocation[] loc = indexedLine.indicesOf(subLine);
+ Geometry result = indexedLine.locate(loc[0], loc[1]);
+ return result;
+ }
+*/
+
+ bool indexOfAfterCheck(Geometry* linearGeom, Coordinate testPt)
+ {
+ LengthIndexedLine indexedLine(linearGeom);
+
+ // check locations are consecutive
+ double loc1 = indexedLine.indexOf(testPt);
+ double loc2 = indexedLine.indexOfAfter(testPt, loc1);
+ if (loc2 <= loc1) return false;
+
+ // check extracted points are the same as the input
+ Coordinate pt1 = indexedLine.extractPoint(loc1);
+ Coordinate pt2 = indexedLine.extractPoint(loc2);
+ if (! pt1.equals2D(testPt)) return false;
+ if (! pt2.equals2D(testPt)) return false;
+
+ return true;
+ }
+
+
+ void runIndexOfAfterTest(string inputStr,
+ string testPtWKT)
+ {
+ GeomPtr input(reader.read(inputStr));
+ GeomPtr testPoint(reader.read(testPtWKT));
+ const Coordinate* testPt = testPoint->getCoordinate();
+ bool resultOK = indexOfAfterCheck(input.get(), *testPt);
+ ensure(resultOK);
+ }
+
+
+ void runOffsetTest(const string inputWKT,
+ const string testPtWKT, double offsetDistance, string expectedPtWKT)
+ {
+ GeomPtr input(reader.read(inputWKT));
+ GeomPtr testPoint(reader.read(testPtWKT));
+ GeomPtr expectedPoint(reader.read(expectedPtWKT));
+ const Coordinate* testPt = testPoint->getCoordinate();
+ const Coordinate* expectedPt = expectedPoint->getCoordinate();
+ Coordinate offsetPt = extractOffsetAt(input.get(), *testPt, offsetDistance);
+
+ bool isOk = offsetPt.distance(*expectedPt) < TOLERANCE_DIST;
+ if (! isOk)
+ cout << "Expected = " << *expectedPoint << " Actual = " << offsetPt << endl;
+ ensure(isOk);
+ }
+
+
+ Coordinate extractOffsetAt(Geometry* linearGeom, Coordinate testPt, double offsetDistance)
+ {
+ LengthIndexedLine indexedLine(linearGeom);
+ double index = indexedLine.indexOf(testPt);
+ return indexedLine.extractPoint(index, offsetDistance);
+ }
+
+ void checkExtractLine(const char* wkt, double start, double end, const char* expected)
+ {
+ string wktstr(wkt);
+ GeomPtr linearGeom(reader.read(wktstr));
+ LengthIndexedLine indexedLine(linearGeom.get());
+ GeomPtr result(indexedLine.extractLine(start, end));
+ checkExpected(result.get(), expected);
+ }
+
+
+ Geometry* indicesOfThenExtract(Geometry* linearGeom, Geometry* subLine)
+ {
+ LengthIndexedLine indexedLine(linearGeom);
+ double* loc = indexedLine.indicesOf(subLine);
+ Geometry* result = indexedLine.extractLine(loc[0], loc[1]);
+ delete loc;
+ return result;
+ }
+
+};
+ typedef test_group<test_lengthindexedline_data> group;
+ typedef group::object object;
+
+ group test_lengthindexedline_group(
+ "geos::linearref::LocationIndexedLine");
+
+ //1 - testML
+ template<>
+ template<>
+ void object::test<1>()
+ {
+ runIndicesOfThenExtract("MULTILINESTRING ((0 0, 10 10), (20 20, 30 30))",
+ "MULTILINESTRING ((1 1, 10 10), (20 20, 25 25))");
+}
+
+
+ //2 - testPartOfSegmentNoVertex
+ template<>
+ template<>
+ void object::test<2>()
+ {
+ runIndicesOfThenExtract("LINESTRING (0 0, 10 10, 20 20)",
+ "LINESTRING (1 1, 9 9)");
+ }
+
+ //3 - testPartOfSegmentContainingVertex()
+ template<>
+ template<>
+ void object::test<3>()
+ {
+ runIndicesOfThenExtract("LINESTRING (0 0, 10 10, 20 20)",
+ "LINESTRING (5 5, 10 10, 15 15)");
+ }
+
+ /**
+ * Tests that duplicate coordinates are handled correctly.
+ *
+ * @throws Exception
+ */
+ // 4 - testPartOfSegmentContainingDuplicateCoords
+ template<>
+ template<>
+ void object::test<4>()
+ {
+ runIndicesOfThenExtract("LINESTRING (0 0, 10 10, 10 10, 20 20)",
+ "LINESTRING (5 5, 10 10, 10 10, 15 15)");
+ }
+
+ /**
+ * Following tests check that correct portion of loop is identified.
+ * This requires that the correct vertex for (0,0) is selected.
+ */
+
+ //5 - testLoopWithStartSubLine
+ template<>
+ template<>
+ void object::test<5>()
+ {
+ runIndicesOfThenExtract("LINESTRING (0 0, 0 10, 10 10, 10 0, 0 0)",
+ "LINESTRING (0 0, 0 10, 10 10)");
+ }
+
+ //6 - testLoopWithEndingSubLine()
+ template<>
+ template<>
+ void object::test<6>()
+ {
+ runIndicesOfThenExtract("LINESTRING (0 0, 0 10, 10 10, 10 0, 0 0)",
+ "LINESTRING (10 10, 10 0, 0 0)");
+ }
+
+ // test a subline equal to the parent loop
+ //7 - testLoopWithIdenticalSubLine()
+ template<>
+ template<>
+ void object::test<7>()
+ {
+ runIndicesOfThenExtract("LINESTRING (0 0, 0 10, 10 10, 10 0, 0 0)",
+ "LINESTRING (0 0, 0 10, 10 10, 10 0, 0 0)");
+ }
+
+ // test a zero-length subline equal to the start point
+ //8 - testZeroLenSubLineAtStart()
+ template<>
+ template<>
+ void object::test<8>()
+ {
+ runIndicesOfThenExtract("LINESTRING (0 0, 0 10, 10 10, 10 0, 0 0)",
+ "LINESTRING (0 0, 0 0)");
+ }
+
+ // test a zero-length subline equal to a mid point
+ //9 - testZeroLenSubLineAtMidVertex()
+ template<>
+ template<>
+ void object::test<9>()
+ {
+ runIndicesOfThenExtract("LINESTRING (0 0, 0 10, 10 10, 10 0, 0 0)",
+ "LINESTRING (10 10, 10 10)");
+ }
+
+ //10 - testIndexOfAfterSquare()
+ template<>
+ template<>
+ void object::test<10>()
+ {
+ runIndexOfAfterTest("LINESTRING (0 0, 0 10, 10 10, 10 0, 0 0)",
+ "POINT (0 0)");
+ }
+
+ //11 - testIndexOfAfterRibbon()
+ template<>
+ template<>
+ void object::test<11>()
+ {
+ runIndexOfAfterTest("LINESTRING (0 0, 0 60, 50 60, 50 20, -20 20)",
+ "POINT (0 20)");
+ }
+
+ //12 - testOffsetStartPoint()
+ template<>
+ template<>
+ void object::test<12>()
+ {
+ runOffsetTest("LINESTRING (0 0, 10 10, 10 10, 20 20)", "POINT(0 0)", 1.0, "POINT (-0.7071067811865475 0.7071067811865475)");
+ runOffsetTest("LINESTRING (0 0, 10 10, 10 10, 20 20)", "POINT(0 0)", -1.0, "POINT (0.7071067811865475 -0.7071067811865475)");
+ runOffsetTest("LINESTRING (0 0, 10 10, 10 10, 20 20)", "POINT(10 10)", 5.0, "POINT (6.464466094067262 13.535533905932738)");
+ runOffsetTest("LINESTRING (0 0, 10 10, 10 10, 20 20)", "POINT(10 10)", -5.0, "POINT (13.535533905932738 6.464466094067262)");
+ }
+
+
+ //13 - testExtractLineBeyondRange()
+ template<>
+ template<>
+ void object::test<13>()
+ {
+ checkExtractLine("LINESTRING (0 0, 10 10)", -100, 100, "LINESTRING (0 0, 10 10)");
+ }
+
+ //14 - testExtractLineReverse()
+ template<>
+ template<>
+ void object::test<14>()
+ {
+ checkExtractLine("LINESTRING (0 0, 10 0)", 9, 1, "LINESTRING (9 0, 1 0)");
+ }
+
+ //15 - testExtractLineReverseMulti()
+ template<>
+ template<>
+ void object::test<15>()
+ {
+ checkExtractLine("MULTILINESTRING ((0 0, 10 0), (20 0, 25 0, 30 0))",
+ 19, 1, "MULTILINESTRING ((29 0, 25 0, 20 0), (10 0, 1 0))");
+ }
+
+ //16 - testExtractLineNegative()
+ template<>
+ template<>
+ void object::test<16>()
+ {
+ checkExtractLine("LINESTRING (0 0, 10 0)", -9, -1, "LINESTRING (1 0, 9 0)");
+ }
+
+ //17 - testExtractLineNegativeReverse()
+ template<>
+ template<>
+ void object::test<17>()
+ {
+ checkExtractLine("LINESTRING (0 0, 10 0)", -1, -9, "LINESTRING (9 0, 1 0)");
+ }
+
+ //18 - testExtractLineIndexAtEndpoint()
+ template<>
+ template<>
+ void object::test<18>()
+ {
+ checkExtractLine("MULTILINESTRING ((0 0, 10 0), (20 0, 25 0, 30 0))",
+ 10, -1, "LINESTRING (20 0, 25 0, 29 0)");
+ }
+
+ //19 - testExtractLineBothIndicesAtEndpoint()
+ template<>
+ template<>
+ void object::test<19>()
+ {
+ checkExtractLine("MULTILINESTRING ((0 0, 10 0), (20 0, 25 0, 30 0))",
+ 10, 10, "LINESTRING (20 0, 20 0)");
+ }
+
+ //20 - testExtractLineBothIndicesAtEndpointNegative()
+ template<>
+ template<>
+ void object::test<20>()
+ {
+ checkExtractLine("MULTILINESTRING ((0 0, 10 0), (20 0, 25 0, 30 0))",
+ -10, 10, "LINESTRING (20 0, 20 0)");
+ }
+
+ //21 - testExtractPointBeyondRange()
+ template<>
+ template<>
+ void object::test<21>()
+ {
+ GeomPtr linearGeom(reader.read("LINESTRING (0 0, 10 10)"));
+ LengthIndexedLine indexedLine(linearGeom.get());
+ Coordinate pt = indexedLine.extractPoint(100);
+ ensure(pt == Coordinate(10, 10));
+
+ Coordinate pt2 = indexedLine.extractPoint(0);
+ ensure(pt2 == Coordinate(0, 0));
+ }
+
+ //22 - testProjectPointWithDuplicateCoords()
+ template<>
+ template<>
+ void object::test<22>()
+ {
+ GeomPtr linearGeom(reader.read("LINESTRING (0 0, 10 0, 10 0, 20 0)"));
+ LengthIndexedLine indexedLine(linearGeom.get());
+ double projIndex = indexedLine.project(Coordinate(10, 1));
+ ensure(projIndex == 10.0);
+ }
+
+ /**
+ * Tests that z values are interpolated
+ *
+ */
+ //23 - testComputeZ()
+ template<>
+ template<>
+ void object::test<23>()
+ {
+ GeomPtr linearGeom(reader.read("LINESTRING (0 0 0, 10 10 10)"));
+ LengthIndexedLine indexedLine(linearGeom.get());
+ double projIndex = indexedLine.project(Coordinate(5, 5));
+ Coordinate projPt = indexedLine.extractPoint(projIndex);
+// System.out.println(projPt);
+ ensure(projPt.equals3D(Coordinate(5, 5, 5)));
+ }
+
+ /**
+ * Tests that if the input does not have Z ordinates, neither does the output.
+ *
+ */
+ //24 - testComputeZNaN()
+ template<>
+ template<>
+ void object::test<24>()
+ {
+
+ GeomPtr linearGeom(reader.read("LINESTRING (0 0, 10 10 10)"));
+ LengthIndexedLine indexedLine(linearGeom.get());
+ double projIndex = indexedLine.project(Coordinate(5, 5));
+ Coordinate projPt = indexedLine.extractPoint(projIndex);
+ ensure(isnan(projPt.z));
+ }
+
+}
More information about the geos-commits
mailing list