Complete Note#1 in the http://wiki.osgeo.org/wiki/GEOS_Provenance_Review to get out...
[geos.git] / src / linearref / LocationIndexOfPoint.cpp
blob568c821bab1324fd66d8c538ec21eb4b10d6afe0
1 /**********************************************************************
3 * GEOS - Geometry Engine Open Source
4 * http://geos.osgeo.org
6 * Copyright (C) 2011 Sandro Santilli <strk@keybit.net>
7 * Copyright (C) 2005-2006 Refractions Research Inc.
8 * Copyright (C) 2001-2002 Vivid Solutions Inc.
10 * This is free software; you can redistribute and/or modify it under
11 * the terms of the GNU Lesser General Public Licence as published
12 * by the Free Software Foundation.
13 * See the COPYING file for more information.
15 **********************************************************************
17 * Last port: linearref/LocationIndexOfPoint.java r466
19 **********************************************************************/
22 #include <geos/geom/LineSegment.h>
23 #include <geos/linearref/LinearIterator.h>
24 #include <geos/linearref/LinearLocation.h>
25 #include <geos/linearref/LocationIndexOfPoint.h>
26 #include <geos/util/IllegalArgumentException.h>
28 #include <cassert>
29 #include <limits>
31 using namespace std;
33 using namespace geos::geom;
35 namespace geos
37 namespace linearref // geos.linearref
40 LinearLocation
41 LocationIndexOfPoint::indexOfFromStart(const Coordinate& inputPt,
42 const LinearLocation* minIndex) const
44 double minDistance = numeric_limits<double>::max();
45 int minComponentIndex = 0;
46 int minSegmentIndex = 0;
47 double minFrac = -1.0;
49 LineSegment seg;
50 for (LinearIterator it(linearGeom);
51 it.hasNext(); it.next())
53 if (! it.isEndOfLine())
55 seg.p0 = it.getSegmentStart();
56 seg.p1 = it.getSegmentEnd();
57 double segDistance = seg.distance(inputPt);
58 double segFrac = seg.segmentFraction(inputPt);
60 int candidateComponentIndex = it.getComponentIndex();
61 int candidateSegmentIndex = it.getVertexIndex();
62 if (segDistance < minDistance)
64 // ensure after minLocation, if any
65 if (!minIndex ||
66 minIndex->compareLocationValues(candidateComponentIndex, candidateSegmentIndex, segFrac) < 0)
68 // otherwise, save this as new minimum
69 minComponentIndex = candidateComponentIndex;
70 minSegmentIndex = candidateSegmentIndex;
71 minFrac = segFrac;
72 minDistance = segDistance;
77 LinearLocation loc(minComponentIndex, minSegmentIndex, minFrac);
78 return loc;
82 LinearLocation LocationIndexOfPoint::indexOf(const Geometry *linearGeom, const Coordinate& inputPt)
84 LocationIndexOfPoint locater(linearGeom);
85 return locater.indexOf(inputPt);
88 LinearLocation LocationIndexOfPoint::indexOfAfter(const Geometry *linearGeom, const Coordinate& inputPt, const LinearLocation* minIndex)
90 LocationIndexOfPoint locater(linearGeom);
91 return locater.indexOfAfter(inputPt, minIndex);
94 LocationIndexOfPoint::LocationIndexOfPoint(const Geometry *linearGeom) :
95 linearGeom(linearGeom)
98 LinearLocation LocationIndexOfPoint::indexOf(const Coordinate& inputPt) const
100 return indexOfFromStart(inputPt, 0);
103 LinearLocation
104 LocationIndexOfPoint::indexOfAfter(const Coordinate& inputPt,
105 const LinearLocation* minIndex) const
107 if (!minIndex) return indexOf(inputPt);
109 // sanity check for minLocation at or past end of line
110 LinearLocation endLoc = LinearLocation::getEndLocation(linearGeom);
111 if (endLoc.compareTo(*minIndex) <= 0)
112 return endLoc;
114 LinearLocation closestAfter = indexOfFromStart(inputPt, minIndex);
116 * Return the minDistanceLocation found.
117 * This will not be null, since it was initialized to minLocation
119 if (closestAfter.compareTo(*minIndex) < 0)
121 throw util::IllegalArgumentException("computed location is before specified minimum location");
123 return closestAfter;