double LengthIndexOfPoint::indexOfFromStart(const Coordinate& inputPt, double minIndex) const { 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; }
WayLocation LocationOfPoint::locate(const Coordinate& inputPt) const { double minDistance = std::numeric_limits<double>().max(); int minIndex = 0; double minFrac = -1.0; LineSegment seg; if (_length == -1) { _length = ElementConverter(_map).convertToLineString(_way)->getLength(); } if (_length <= 0.0) { return WayLocation(_map, _way, 0, 0); } for (size_t i = 0; i < _way->getNodeCount() - 1; i++) { seg.p0 = _map->getNode(_way->getNodeId(i))->toCoordinate(); seg.p1 = _map->getNode(_way->getNodeId(i + 1))->toCoordinate(); double segDistance = seg.distance(inputPt); double segFrac = segmentFraction(seg, inputPt); if (segDistance < minDistance) { minIndex = i; minFrac = segFrac; minDistance = segDistance; } } return WayLocation(_map, _way, minIndex, minFrac); }
WayLocation LocationOfPoint::locateAfter(const Coordinate& inputPt, const WayLocation& minLocation) const { if (minLocation.isValid() == false) { return locate(inputPt); } assert(minLocation.getWay() == _way); double minDistance = std::numeric_limits<double>().max(); WayLocation nextClosestLocation = minLocation; LineSegment seg; size_t startIndex = 0; startIndex = (size_t)minLocation.getSegmentIndex(); for (size_t i = startIndex; i < _way->getNodeCount() - 1; i++) { seg.p0 = _map->getNode(_way->getNodeId(i))->toCoordinate(); seg.p1 = _map->getNode(_way->getNodeId(i + 1))->toCoordinate(); if (i == startIndex) { seg.p0 = minLocation.getCoordinate(); } double segDistance = seg.distance(inputPt); double segFrac = segmentFraction(seg, inputPt); if (segDistance < minDistance) { // if this is the first case (a partial line segment) if (i == startIndex) { // recalculate the segFrac in terms of the whole line segment. segFrac = minLocation.getSegmentFraction() + (1 - minLocation.getSegmentFraction()) * segFrac; } nextClosestLocation = WayLocation(_map, _way, i, segFrac); minDistance = segDistance; } } // Return the minDistanceLocation found. // This will not be null, since it was initialized to minLocation Assert::isFalse(nextClosestLocation >= minLocation, "computed location is before specified minimum location"); return nextClosestLocation; }
/* NOTE: this is called findSegmentIndexToSnap in JTS */ CoordinateList::iterator LineStringSnapper::findSegmentToSnap( const Coordinate& snapPt, CoordinateList::iterator from, CoordinateList::iterator too_far) { LineSegment seg; double minDist = snapTolerance; // make sure the first closer then // snapTolerance is accepted CoordinateList::iterator match=too_far; // TODO: use std::find_if for ( ; from != too_far; ++from) { seg.p0 = *from; CoordinateList::iterator to = from; ++to; seg.p1 = *to; #if GEOS_DEBUG cerr << " Checking segment " << seg << endl; #endif /** * Check if the snap pt is equal to one of * the segment endpoints. * * If the snap pt is already in the src list, * don't snap at all (unless allowSnappingToSourceVertices * is set to true) */ if ( seg.p0.equals2D(snapPt) || seg.p1.equals2D(snapPt) ) { if (allowSnappingToSourceVertices) { #if GEOS_DEBUG cerr << " snap point matches a segment endpoint, checking next segment" << endl; #endif continue; } else { #if GEOS_DEBUG cerr << " snap point matches a segment endpoint, giving up seek" << endl; #endif return too_far; } } double dist = seg.distance(snapPt); if ( dist >= minDist) { #if GEOS_DEBUG cerr << " snap point distance " << dist << " not smaller than tolerance " << snapTolerance << " or previous closest " << minDist << endl; #endif continue; } #if GEOS_DEBUG cerr << " snap point distance " << dist << " within tolerance " << snapTolerance << " and closer than previous candidate " << minDist << endl; #endif if ( dist == 0.0 ) return from; // can't find any closer match = from; minDist = dist; } return match; }