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); }
void MaximalSubline::_snapToTerminal(WayLocation& wl, bool startOfLines, double thresh) { Meters d1 = wl.calculateDistanceOnWay(); // if we're not at the start of the line if (!startOfLines) { // calculate the distance from the end to this way location. d1 = ElementConverter(wl.getMap()).convertToLineString(wl.getWay())->getLength() - d1; } if (thresh == -1) { thresh = _minSplitSize; } // if we should snap the end points if (d1 <= thresh) { // if we're at the start of the line if (startOfLines) { // snap to the beginning wl = WayLocation(wl.getMap(), wl.getWay(), 0, 0.0); } // if we're at the end of the line else { // snap to the end wl = WayLocation(wl.getMap(), wl.getWay(), wl.getWay()->getNodeCount(), 0.0); } } }
WaySublineCollection WaySublineCollection::invert() const { WaySublineCollection result; if (_sublines.size() == 0) { return result; } // We are going to sort all the way sublines so we can generate the inverted sublines starting // at the beginning and working on to the end. We'll maintain a simple variable for where the // next subline starts and then use a little simple logic to determine when we've found a legit // inverted subline and push it on to the result. // make a copy so we can sort. vector<WaySubline> sublines = _sublines; sort(sublines.begin(), sublines.end(), compareSublines); WayLocation sublineStart = WayLocation(_sublines[0].getMap(), sublines[0].getWay(), 0, 0); // go through all the sorted sublines for (size_t i = 0; i < sublines.size(); i++) { if (sublineStart.getWay() != sublines[i].getWay()) { // if this isn't an empty subline if (sublineStart.isLast() == false) { result.addSubline(WaySubline(sublineStart, WayLocation::createAtEndOfWay(_sublines[0].getMap(), sublineStart.getWay()))); } sublineStart = WayLocation(_sublines[0].getMap(), sublines[i].getWay(), 0, 0); } assert(sublineStart.getWay() == sublines[i].getWay()); if (sublineStart == sublines[i].getStart()) { // an empty subline at the beginning sublineStart = sublines[i].getEnd(); } else { // add another subline from the sublineStart to the beginning of the next subline. result.addSubline(WaySubline(sublineStart, sublines[i].getStart())); // the next negative subline starts at the end of this positive subline sublineStart = sublines[i].getEnd(); } } // if we haven't reached the end, then add one more subline for the end of the line. if (sublineStart.isLast() == false) { result.addSubline(WaySubline(sublineStart, WayLocation::createAtEndOfWay(_sublines[0].getMap(), sublineStart.getWay()))); } return result; }
WaySubline::WaySubline(const WaySubline& from, const ConstOsmMapPtr& newMap) { if (from.isValid()) { ConstWayPtr oldWay = from.getStart().getWay(); ConstWayPtr newWay = newMap->getWay(oldWay->getId()); _start = WayLocation(newMap, newWay, from.getStart().getSegmentIndex(), from.getStart().getSegmentFraction()); _end = WayLocation(newMap, newWay, from.getEnd().getSegmentIndex(), from.getEnd().getSegmentFraction()); } }
vector<WayPtr> WaySplitter::createSplits(const vector<WayLocation>& wl) { vector<WayPtr> result; WayLocation last = WayLocation(_map, _a, 0, 0.0); result.resize(wl.size() + 1); for (size_t i = 0; i < wl.size(); i++) { assert(wl[i].getWay() == _a); WayLocation curr = wl[i]; if (last.compareTo(curr) != 0) { result[i] = WaySubline(last, curr).toWay(_map); if (result[i]->getNodeCount() == 0) { result[i].reset(); } } last = curr; } WayLocation end(_map, _a, _a->getNodeCount() - 1, 0.0); if (last.compareTo(end) != 0) { result[result.size() - 1] = WaySubline(last, end).toWay(_map, _nf.get()); } return result; }
WaySubline WaySubline::reverse(const ConstWayPtr& reversedWay) const { WaySubline result; // sanity check to make sure they're actually reversed, this isn't conclusive but should help // if there is a major goof. assert(reversedWay->getNodeCount() == getWay()->getNodeCount()); assert(reversedWay->getNodeId(0) == getWay()->getLastNodeId()); double l = ElementConverter(getMap()).convertToLineString(getWay())->getLength(); result._start = WayLocation(getMap(), reversedWay, l - getEnd().calculateDistanceOnWay()); result._end = WayLocation(getMap(), reversedWay, l - getStart().calculateDistanceOnWay()); return result; }
WayLocation PertyWaySplitVisitor::_calcSplitPoint(shared_ptr<const Way> way) const { //create a way location that is the minimum node spacing distance from the beginning of the way WayLocation splitWayStart(_map->shared_from_this(), way, _minNodeSpacing); //create a way location that is the minimum node spacing from the end of the way WayLocation splitWayEnd = WayLocation::createAtEndOfWay(_map->shared_from_this(), way). move(-1 * _minNodeSpacing); //if the length between the way locations is greater than zero, then then a way location can be //selected that doesn't violate the min node spacing const double splitWayLength = splitWayEnd.calculateDistanceOnWay() - splitWayStart.calculateDistanceOnWay(); LOG_VARD(splitWayLength); if (splitWayLength > 0) { boost::uniform_real<> randomSplitPointDistribution(0.0, splitWayLength); const double splitPoint = randomSplitPointDistribution(*_rng); LOG_VARD(splitPoint); return splitWayStart.move(splitPoint); } //otherwise, return an empty location else { return WayLocation(); } }
void MaximalNearestSublineMatcher::_snapToEnds(const ConstOsmMapPtr &map, vector<WayLocation>& wl) const { if (wl[0].calculateDistanceOnWay() <= _minSplitSize) { wl[0] = WayLocation(map, wl[0].getWay(), 0, 0); } if (wl[1].calculateDistanceFromEnd() <= _minSplitSize) { wl[1] = WayLocation::createAtEndOfWay(map, wl[1].getWay()); } }
WayLocation MaximalSubline::_calculateEndWayLocation(const ConstOsmMapPtr &map, const ConstWayPtr& a, const ConstWayPtr& b, int indexA, int indexB) { Coordinate ca1 = map->getNode(a->getNodeId(indexA))->toCoordinate(); Coordinate ca2 = map->getNode(a->getNodeId(indexA + 1))->toCoordinate(); Coordinate cb2 = map->getNode(b->getNodeId(indexB + 1))->toCoordinate(); LineSegment lsA(ca1, ca2); Coordinate start; lsA.closestPoint(cb2, start); return LocationOfPoint(map, a).locateAfter(start, WayLocation(map, a, indexA, 0)); }
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; }
/** * Create a couple of simple way strings and verify that the generated subline match is correct. */ void runTest() { OsmMapPtr map(new OsmMap()); NodePtr n1a = TestUtils::createNode(map, Status::Unknown1, 0, 0); NodePtr n1b = TestUtils::createNode(map, Status::Unknown1, 100, 0); NodePtr n1c = TestUtils::createNode(map, Status::Unknown1, 200, 0); WayPtr w1 = TestUtils::createWay(map, QList<NodePtr>() << n1a << n1b); WayPtr w2 = TestUtils::createWay(map, QList<NodePtr>() << n1b << n1c); NodePtr n2a = TestUtils::createNode(map, Status::Unknown1, 0, 10); NodePtr n2b = TestUtils::createNode(map, Status::Unknown1, 150, 10); NodePtr n2c = TestUtils::createNode(map, Status::Unknown1, 210, 10); WayPtr w3 = TestUtils::createWay(map, QList<NodePtr>() << n2a << n2b); WayPtr w4 = TestUtils::createWay(map, QList<NodePtr>() << n2c << n2b); WayStringPtr wstr1(new WayString()); wstr1->append(WaySubline(WayLocation(map, w1, 0), WayLocation::createAtEndOfWay(map, w1))); wstr1->append(WaySubline(WayLocation(map, w2, 0), WayLocation::createAtEndOfWay(map, w2))); WayStringPtr wstr2(new WayString()); wstr2->append(WaySubline(WayLocation(map, w3, 0), WayLocation::createAtEndOfWay(map, w3))); wstr2->append(WaySubline(WayLocation::createAtEndOfWay(map, w4), WayLocation(map, w4, 0))); WayMatchStringMappingPtr mapping(new NaiveWayMatchStringMapping(wstr1, wstr2)); WaySublineMatchStringPtr wsms = WayMatchStringMappingConverter(). toWaySublineMatchString(mapping); //LOG_VAR(TestUtils::toQuotedString(hoot::toString(wsms))); HOOT_STR_EQUALS("matches:\n" "subline 1: start: way(-1) index: 0 fraction: 0 end: way(-1) index: 1 fraction: 0\n" "subline 2: start: way(-3) index: 0 fraction: 0 end: way(-3) index: 0 fraction: 0.7\n" "subline 1: start: way(-2) index: 0 fraction: 0 end: way(-2) index: 0 fraction: 0.428571428571429\n" "subline 2: start: way(-3) index: 0 fraction: 0.7 end: way(-3) index: 1 fraction: 0\n" "reversed, subline 1: start: way(-2) index: 0 fraction: 0.428571428571429 end: way(-2) index: 1 fraction: 0\n" "subline 2: start: way(-4) index: 0 fraction: 0 end: way(-4) index: 1 fraction: 0", wsms); }
WayLocation WayLocation::createAtEndOfWay(const ConstOsmMapPtr& map, const ConstWayPtr way) { return WayLocation(map, way, way->getNodeCount() - 1, 0.0); }
/// @todo this is in desperate need of a rewrite by someone with more rest than myself. -JRS vector<WaySublineMatch> MaximalSubline::_snapIntersections(const ConstOsmMapPtr& map, const ConstWayPtr& w1, const ConstWayPtr& w2, vector<WaySublineMatch>& rawSublineMatches) { // this only works if the rawSublineMatches are in order. We order by subline1 sort(rawSublineMatches.begin(), rawSublineMatches.end(), lessThan); // make sure that ordering by subline1 results in sorted subline2s. If this isn't the case then // there isn't much we can do. for (size_t i = 2; i < rawSublineMatches.size(); i++) { if (rawSublineMatches[i].getSubline2().getStart() > rawSublineMatches[i - 1].getSubline2().getStart()) { LOG_WARN("Way matches sublines out of order. This is unusual and may give a sub-optimal " "result."); return rawSublineMatches; } } for (size_t i = 0; i < rawSublineMatches.size(); i++) { // if any of the raw sublines are crazy small, then don't try to snap the intersections. if (rawSublineMatches[i].getSubline1().getLength() < _spacing * 2 || rawSublineMatches[i].getSubline2().getLength() < _spacing * 2) { return rawSublineMatches; } } //// // calculate a series of point pair matches along the lines. //// // discretize the first line into a series of points. vector< pair<WayLocation, WayLocation> > pairs; pairs = _discretizePointPairs(map, w1, w2, rawSublineMatches); assert(pairs.size() > 0); //LOG_DEBUG_VAR(pairs); // extract features on the point pairs and populate a matrix. Meters acc = w1->getCircularError() + w2->getCircularError(); cv::Mat m(pairs.size(), 2, CV_64F); size_t currentSubline = 0; vector<int> starts(rawSublineMatches.size(), numeric_limits<int>::max()); vector<int> ends(rawSublineMatches.size(), 0); for (size_t i = 0; i < pairs.size(); i++) { WayLocation& wl1 = pairs[i].first; WayLocation& wl2 = pairs[i].second; // If the rawSublineMatches is smaller than _spacing, then it may not directly overlap with // one of the point pairs. To avoid this, we create a subline that surrounds the point pair // and will guarantee that each rawSublineMatches will touch at least one point pair. WaySubline ws1 = WaySubline(wl1.move(-_spacing / 2.0), wl1.move(_spacing / 2.0)); WaySubline ws2 = WaySubline(wl2.move(-_spacing / 2.0), wl2.move(_spacing / 2.0)); if (currentSubline < rawSublineMatches.size()) { // figure out the first and last match for this subline. if (rawSublineMatches[currentSubline].getSubline1().touches(ws1) || rawSublineMatches[currentSubline].getSubline2().touches(ws2)) { starts[currentSubline] = min<int>(starts[currentSubline], i); ends[currentSubline] = max<int>(ends[currentSubline], i); } else { // if this is past the current subline, advance to the right subline. while (currentSubline < rawSublineMatches.size() && rawSublineMatches[currentSubline].getSubline1().getEnd() < ws1.getStart() && rawSublineMatches[currentSubline].getSubline2().getEnd() < ws2.getStart()) { currentSubline++; } } } Meters distance = wl1.getCoordinate().distance(wl2.getCoordinate()); Radians angle1 = WayHeading::calculateHeading(wl1); Radians angle2 = WayHeading::calculateHeading(wl2); Radians angleDiff = WayHeading::deltaMagnitude(angle1, angle2); m.at<double>(i, 0) = distance / acc; m.at<double>(i, 1) = angleDiff; } //LOG_DEBUG("starts: " << starts); //LOG_DEBUG("ends: " << ends); // create the matrix of constraints. vector<int> finalStarts; vector<int> finalEnds; if (starts[0] != 0) { finalStarts.push_back(0); finalEnds.push_back(starts[0] + (ends[0] - starts[0]) / 3); } // this maps finalStarts indexes to the rawSublineMatches indexes. E.g. // rawSublineMatches[i] maps to finalStarts[matchIndexes[i]] vector<int> matchIndexes(starts.size()); for (size_t i = 0; i < starts.size(); i++) { if (starts[i] == numeric_limits<int>::max()) { // Due to poor subline pair matching we cannot properly snap these intersections. Warn the // user and move on. It is likely they aren't a good match anyways. LOG_WARN("A solid set of point pair matches could not be found."); return rawSublineMatches; } matchIndexes[i] = finalStarts.size(); finalStarts.push_back(starts[i]); finalEnds.push_back(ends[i]); if (i != starts.size() - 1) { finalStarts.push_back(ends[i] - (ends[i] - starts[i]) / 3); finalEnds.push_back(starts[i + 1] + (ends[i + 1] - starts[i + 1]) / 3); } } int last = ends.size() - 1; if ((size_t)ends[last] != pairs.size() - 1) { finalStarts.push_back(ends[last] - (ends[last] - starts[last]) / 3); finalEnds.push_back(pairs.size() - 1); } //LOG_DEBUG("finalStarts: " << finalStarts); //LOG_DEBUG("finalEnds: " << finalEnds); Mat ranges(finalStarts.size(), 2, CV_32S); for (size_t i = 0; i < finalStarts.size(); i++) { ranges.at<int>(i, 0) = finalStarts[i]; ranges.at<int>(i, 1) = finalEnds[i]; } // run ExpectationIntersection to determine new intersection points. ExpectationIntersection ei; vector<double> splits = ei.snapMatches(m, ranges); //LOG_DEBUG_VAR(splits); vector<WaySublineMatch> result = rawSublineMatches; for (size_t i = 0; i < matchIndexes.size(); i++) { size_t mi = matchIndexes[i]; WayLocation w1Start; WayLocation w2Start; //LOG_DEBUG(rawSublineMatches[i]); // if this is the first subline, then it starts at the beginning of the subline. if (matchIndexes[i] == 0) { w1Start = WayLocation(rawSublineMatches[i].getSubline1().getStart()); w2Start = WayLocation(rawSublineMatches[i].getSubline2().getStart()); } else { int wi = (int)splits[mi - 1]; //LOG_DEBUG("start split: " << wi); double r = splits[mi - 1] - wi; Meters offset1 = pairs[wi].first.calculateDistanceOnWay() * r + pairs[wi + 1].first.calculateDistanceOnWay() * (1 - r); Meters offset2 = pairs[wi].second.calculateDistanceOnWay() * r + pairs[wi + 1].second.calculateDistanceOnWay() * (1 - r); //LOG_DEBUG("offset1: " << offset1 << " r: " << r); //LOG_DEBUG("offset2: " << offset2 << " r: " << r); w1Start = WayLocation(map, w1, offset1); w2Start = WayLocation(map, w2, offset2); } //LOG_DEBUG_VAR(w1Start); //LOG_DEBUG_VAR(w2Start); // if we are passed the point where we have a node pairing, then snap it back to a legit pair. if (w1Start < pairs.front().first.move(-_spacing)) { w1Start = pairs.front().first; } if (w2Start < pairs.front().second.move(-_spacing)) { w2Start = pairs.front().second; } //LOG_DEBUG_VAR(w1Start); //LOG_DEBUG_VAR(w2Start); WayLocation w1End(rawSublineMatches[i].getSubline1().getEnd()); WayLocation w2End(rawSublineMatches[i].getSubline2().getEnd()); // convert the end split location into a WayLocation if (matchIndexes[i] < (int)splits.size()) { int wi = (int)splits[mi]; //LOG_DEBUG("end split: " << wi << " matchIndexes[" << i << "]: " << mi); double r = splits[mi] - wi; Meters offset1 = pairs[wi].first.calculateDistanceOnWay() * r + pairs[wi + 1].first.calculateDistanceOnWay() * (1 - r); Meters offset2 = pairs[wi].second.calculateDistanceOnWay() * r + pairs[wi + 1].second.calculateDistanceOnWay() * (1 - r); w1End = WayLocation(map, w1, offset1); w2End = WayLocation(map, w2, offset2); //LOG_DEBUG("offset1: " << offset1 << " r: " << r); //LOG_DEBUG("offset2: " << offset2 << " r: " << r); } // if we are passed the point where we have a node pairing, then snap it back to a legit pair. //LOG_DEBUG_VAR(w1End); //LOG_DEBUG_VAR(pairs.back().first.move(_spacing)); if (w1End > pairs.back().first.move(_spacing)) { w1End = pairs.back().first; } if (w2End > pairs.back().second.move(_spacing)) { w2End = pairs.back().second; } //LOG_DEBUG("w1End: " << w1End.toString()); //LOG_DEBUG("w2End: " << w2End.toString()); WaySubline ws1Expanded = rawSublineMatches[i].getSubline1().expand( max(_minSplitSize, _spacing)); WaySubline ws2Expanded = rawSublineMatches[i].getSubline2().expand( max(_minSplitSize, _spacing)); if (ws1Expanded.contains(w1Start) == false || ws2Expanded.contains(w2Start) == false || ws1Expanded.contains(w1End) == false || ws2Expanded.contains(w2End) == false || w1Start > w1End || w2Start > w2End) { LOG_DEBUG("Point pair matching failed, skipping intersection snapping."); return rawSublineMatches; } // snap to the start if we're within spacing distance. _snapToStart(w1Start, max(_minSplitSize, _spacing)); _snapToStart(w2Start, max(_minSplitSize, _spacing)); // snap to the end if we're within spacing distance. _snapToEnd(w1End, max(_minSplitSize, _spacing)); _snapToEnd(w2End, max(_minSplitSize, _spacing)); //LOG_DEBUG_VAR(w1End); //LOG_DEBUG_VAR(w2End); WaySubline ws1(w1Start, w1End); WaySubline ws2(w2Start, w2End); result[i] = WaySublineMatch(ws1, ws2); } // Put the updated intersection points into the result. return result; }
double MaximalSubline::ThresholdMatchCriteria::match(int index1, int index2) const { Coordinate c11 = _map->getNode(_w1->getNodeId(index1))->toCoordinate(); Coordinate c12 = _map->getNode(_w1->getNodeId(index1 + 1))->toCoordinate(); Coordinate c21 = _map->getNode(_w2->getNodeId(index2))->toCoordinate(); Coordinate c22 = _map->getNode(_w2->getNodeId(index2 + 1))->toCoordinate(); LineSegment ls1(c11, c12); LineSegment ls2(c21, c22); Radians heading1, heading2; // if the line segment is zero length if (ls1.p0 == ls1.p1) { // calculate heading based on location in way. See #4765 for the drama associated with this fix. // This should find way headings appropriately even if there are one or more duplicate nodes in // the way. This is done by calculating the way location before and after this node location. // There may be some edge conditions when this will fail, but that seems very unlikely. heading1 = WayHeading::calculateHeading(WayLocation(_map, _w1, index1, 0)); } else { // little faster than above and better defined. heading1 = ls1.angle(); } // if the line segment is zero length if (ls2.p0 == ls2.p1) { // calculate heading based on location in way heading2 = WayHeading::calculateHeading(WayLocation(_map, _w2, index2, 0)); } else { // little faster than above and better defined. heading2 = ls2.angle(); } Radians angleDiff = WayHeading::deltaMagnitude(heading1, heading2); if (angleDiff > _maxAngleDiff) { return 0.0; } double maxD; // Treat this as a variation of Frechet's Distance. This means that we're looking for the longest // subline that is within _maxDistance of the other linestring. // find the subline that is within _maxDistance. Ultimately we'll need a proper implementation of // Frechet's distance, but that'll have to wait till later. See #3213 matchingSubline(ls1, ls2); // previously I found the maximalNearest subline, but that causes issues when there is a large // offset between the two datasets. //maximalNearestSubline(ls1, ls2); maxD = max(ls1.p0.distance(ls2.p0), ls1.p1.distance(ls2.p1)); double mns = min(ls1.getLength(), ls2.getLength()); const double epsilon = 1e-6; if (maxD > _maxDistance + epsilon) { return 0.0; } return 1.0 * mns; }
void runLocateAfterTest() { OsmMap::resetCounters(); shared_ptr<OsmMap> map(new OsmMap()); Coordinate c[] = { Coordinate(0.0, 0.0), Coordinate(100.0, 0.0), Coordinate(100.0, 10.0), Coordinate(0.0, 10.0), Coordinate::getNull() }; WayPtr w = TestUtils::createWay(map, Unknown1, c, 1, ""); WayLocation wl(w, 0, 0); HOOT_STR_EQUALS("way: -1 index: 0 fraction: 0", LocationOfPoint(w).locateAfter(Coordinate(0,0), wl)); HOOT_STR_EQUALS("way: -1 index: 0 fraction: 0.1", LocationOfPoint(w).locateAfter(Coordinate(0,0), WayLocation(w, 10.0))); HOOT_STR_EQUALS("way: -1 index: 0 fraction: 0.1", LocationOfPoint(w).locateAfter(Coordinate(10,0), WayLocation(w, 0.0))); HOOT_STR_EQUALS("way: -1 index: 0 fraction: 0.2", LocationOfPoint(w).locateAfter(Coordinate(20,0), WayLocation(w, 0.0))); HOOT_STR_EQUALS("way: -1 index: 0 fraction: 0.5", LocationOfPoint(w).locateAfter(Coordinate(50,0), WayLocation(w, 20.0))); HOOT_STR_EQUALS("way: -1 index: 2 fraction: 0.5", LocationOfPoint(w).locateAfter(Coordinate(50,10), WayLocation(w, 0.0))); HOOT_STR_EQUALS("way: -1 index: 2 fraction: 0.5", LocationOfPoint(w).locateAfter(Coordinate(50,0), WayLocation(w, 100.0))); HOOT_STR_EQUALS("way: -1 index: 1 fraction: 0", LocationOfPoint(w).locateAfter(Coordinate(100,0), WayLocation(w, 0.0))); HOOT_STR_EQUALS("way: -1 index: 1 fraction: 0.2", LocationOfPoint(w).locateAfter(Coordinate(100,0), WayLocation(w, 102.0))); HOOT_STR_EQUALS("way: -1 index: 1 fraction: 0.2", LocationOfPoint(w).locateAfter(Coordinate(100,2), WayLocation(w, 100.0))); HOOT_STR_EQUALS("way: -1 index: 2 fraction: 0", LocationOfPoint(w).locateAfter(Coordinate(100,10), WayLocation(w, 110.0))); HOOT_STR_EQUALS("way: -1 index: 2 fraction: 0.5", LocationOfPoint(w).locateAfter(Coordinate(50,10), WayLocation(w, 110.0))); HOOT_STR_EQUALS("way: -1 index: 3 fraction: 0", LocationOfPoint(w).locateAfter(Coordinate(0,10), WayLocation(w, 0.0))); HOOT_STR_EQUALS("way: -1 index: 3 fraction: 0", LocationOfPoint(w).locateAfter(Coordinate(0,0), WayLocation(w, 3, 0))); HOOT_STR_EQUALS("way: -1 index: 3 fraction: 0", LocationOfPoint(w).locateAfter(Coordinate(0,10), WayLocation(w, 2, 0.3))); }
void runTest() { OsmMapPtr map = createTestMap(); WayPtr w1 = map->getWay(FindWaysVisitor::findWaysByTag(map, "note", "w1")[0]); WayPtr w2 = map->getWay(FindWaysVisitor::findWaysByTag(map, "note", "w2")[0]); { WaySublineCollection uut; uut.addSubline(WaySubline(WayLocation(map, w1, 0.0), WayLocation(map, w1, 30.0))); HOOT_STR_EQUALS("", uut.invert()); } { WaySublineCollection uut; uut.addSubline(WaySubline(WayLocation(map, w1, 0.0), WayLocation(map, w1, 20.0))); HOOT_STR_EQUALS("start: way(-1) index: 2 fraction: 0 end: way(-1) index: 3 fraction: 0", uut.invert()); } { WaySublineCollection uut; uut.addSubline(WaySubline(WayLocation(map, w1, 20.0), WayLocation(map, w1, 30.0))); HOOT_STR_EQUALS("start: way(-1) index: 0 fraction: 0 end: way(-1) index: 2 fraction: 0", uut.invert()); } { WaySublineCollection uut; uut.addSubline(WaySubline(WayLocation(map, w1, 10.0), WayLocation(map, w1, 20.0))); HOOT_STR_EQUALS("start: way(-1) index: 0 fraction: 0 end: way(-1) index: 1 fraction: 0\n" "start: way(-1) index: 2 fraction: 0 end: way(-1) index: 3 fraction: 0", uut.invert()); } { WaySublineCollection uut; uut.addSubline(WaySubline(WayLocation(map, w1, 10.0), WayLocation(map, w1, 20.0))); uut.addSubline(WaySubline(WayLocation(map, w2, 10.0), WayLocation(map, w2, 20.0))); HOOT_STR_EQUALS("start: way(-2) index: 0 fraction: 0 end: way(-2) index: 1 fraction: 0\n" "start: way(-2) index: 2 fraction: 0 end: way(-2) index: 3 fraction: 0\n" "start: way(-1) index: 0 fraction: 0 end: way(-1) index: 1 fraction: 0\n" "start: way(-1) index: 2 fraction: 0 end: way(-1) index: 3 fraction: 0", uut.invert()); } { WaySublineCollection uut; uut.addSubline(WaySubline(WayLocation(map, w1, 10.0), WayLocation(map, w1, 30.0))); uut.addSubline(WaySubline(WayLocation(map, w2, 0.0), WayLocation(map, w2, 20.0))); HOOT_STR_EQUALS("start: way(-2) index: 2 fraction: 0 end: way(-2) index: 3 fraction: 0\n" "start: way(-1) index: 0 fraction: 0 end: way(-1) index: 1 fraction: 0", uut.invert()); } }