[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