bool CustomPoiMatch::_isExactMatch(const ConstNodePtr& n1, const ConstNodePtr& n2) const { // distance that is considered an exact match. Defaults to 1mm. Meters epsilon = conf().getDouble(epsilonDistanceKey(), 1e-3); bool result = true; if (n1->getElementId() == n2->getElementId()) { // pass, return = true } else if (n1->toCoordinate().distance(n2->toCoordinate()) > epsilon) { result = false; } else { // if at least one name pair is an exact match then it is an exact string match. double stringDistance = NameExtractor(new ExactStringDistance()).extract(n1, n2); if (stringDistance != 1.0) { result = false; } } return result; }
void DualWaySplitter::_reconnectEnd(long centerNodeId, shared_ptr<Way> edge) { Coordinate centerNodeC = _result->getNode(centerNodeId)->toCoordinate(); // determine which end of edge we're operating on Coordinate edgeEnd; long edgeEndId; ConstNodePtr first = _result->getNode(edge->getNodeId(0)); ConstNodePtr last = _result->getNode(edge->getLastNodeId()); if (first->toCoordinate().distance(centerNodeC) < last->toCoordinate().distance(centerNodeC)) { edgeEnd = first->toCoordinate(); edgeEndId = first->getId(); } else { edgeEnd = last->toCoordinate(); edgeEndId = last->getId(); } // find all the nodes that are about the right distance from centerNodeId shared_ptr<DistanceNodeFilter> filterOuter(new DistanceNodeFilter(Filter::KeepMatches, centerNodeC, _splitSize * 1.01)); shared_ptr<DistanceNodeFilter> filterInner(new DistanceNodeFilter(Filter::FilterMatches, centerNodeC, _splitSize * .99)); ChainNodeFilter chain(filterOuter, filterInner); vector<long> nids = _result->filterNodes(chain, centerNodeC, _splitSize * 1.02); Radians bestAngle = std::numeric_limits<Radians>::max(); long bestNid = numeric_limits<long>::max(); Radians edgeAngle = WayHeading::calculateHeading(centerNodeC, edgeEnd); // find the smallest angle from edgeEnd to any of the candidate nodes for (size_t i = 0; i < nids.size(); i++) { if (edgeEndId != nids[i]) { Coordinate c = _result->getNode(nids[i])->toCoordinate(); Radians thisAngle = WayHeading::calculateHeading(centerNodeC, c); Radians deltaMagnitude = WayHeading::deltaMagnitude(edgeAngle, thisAngle); if (deltaMagnitude < bestAngle) { bestAngle = deltaMagnitude; bestNid = nids[i]; } } } // if the smallest angle is less than 45 deg, then connect them. if (toDegrees(bestAngle) < 45) { edge->replaceNode(edgeEndId, bestNid); } }
bool CustomPoiMatch::_isDistanceMatch(const ConstNodePtr &n1, const ConstNodePtr &n2) const { double d = n1->toCoordinate().distance(n2->toCoordinate()); double s1 = n1->getCircularError() / 2.0; double s2 = n2->getCircularError() / 2.0; // calculated the expected sigma for the distance value. double sigma = sqrt(s1 * s1 + s2 * s2); // if the distance is within 2 sigma of the expected distance, then call it a match. return d < sigma * 2.0; }
WayLocation::WayLocation(ConstOsmMapPtr map, ConstWayPtr way, double distance) : _map(map) { double d = 0.0; _segmentIndex = -1; _segmentFraction = -1; _way = way; double length = ElementConverter(map).convertToLineString(way)->getLength(); if (distance <= 0) { _segmentIndex = 0.0; _segmentFraction = 0; } else if (distance >= length) { _segmentIndex = _way->getNodeCount() - 1; _segmentFraction = 0.0; } else { Coordinate last = _map->getNode(way->getNodeId(0))->toCoordinate(); _segmentIndex = way->getNodeCount() - 1; _segmentFraction = 0; for (size_t i = 1; i < way->getNodeCount(); i++) { ConstNodePtr n = _map->getNode(_way->getNodeId(i)); Coordinate next = n->toCoordinate(); double delta = next.distance(last); last = next; if (d <= distance && d + delta > distance) { _segmentIndex = i - 1; _segmentFraction = (distance - d) / delta; // this can sometimes happen due to rounding errors. if (_segmentFraction >= 1.0) { _segmentFraction = 0.0; _segmentIndex++; } _way = way; break; } d += delta; } } assert(_segmentFraction < 1.0); assert((size_t)_segmentIndex <= _way->getNodeCount() - 1); }
Meters WayLocation::calculateDistanceOnWay() const { //LOG_TRACE("Calculating distance on way..."); Meters result = 0.0; Coordinate last = _map->getNode(_way->getNodeId(0))->toCoordinate(); for (int i = 1; i < (int)_way->getNodeCount() && i <= _segmentIndex; i++) { ConstNodePtr n = _map->getNode(_way->getNodeId(i)); Coordinate next = n->toCoordinate(); result += next.distance(last); last = next; } if (_segmentIndex < (int)_way->getNodeCount() - 1) { ConstNodePtr n = _map->getNode(_way->getNodeId(_segmentIndex + 1)); Coordinate next = n->toCoordinate(); Meters d = next.distance(last); result += d * _segmentFraction; } return result; }
set<long> _findNeighbors(const ConstNodePtr& n) { set<long> result; set<QString> allNames = _getNamePermutations(n->getTags().getNames()); double minSimilarity = conf().getDouble(PlacesPoiMatch::minimumEditSimilarityKey(), PlacesPoiMatch::minimumEditSimilarityDefault()); for (set<QString>::const_iterator it = allNames.begin(); it != allNames.end(); ++it) { const QString& s = *it; // if the string we're comparing against is longer then D may be bigger than // (1 - minSimilarity) * string length. Account for that below. int D = (int)round((double)s.size() / minSimilarity) - s.size(); set<long> r = _index->find(n->toCoordinate(), n->getCircularError(), s, D); result.insert(r.begin(), r.end()); } return result; }
WayLocation WayLocation::move(Meters distance) const { WayLocation result(*this); Coordinate last = result.getCoordinate(); // This odd statement avoid us adding irrelevantly small distances. while (1 + distance > 1) { // if we're at the end of the way if (result.isLast()) { return result; } ConstNodePtr n = _map->getNode(_way->getNodeId(result.getSegmentIndex() + 1)); Coordinate next = n->toCoordinate(); double delta = last.distance(next); // if the next node is too far if (distance - delta < 0) { // figure out what distance we need to move along the segment. Coordinate lastSegment = _map->getNode(_way->getNodeId(result.getSegmentIndex()))-> toCoordinate(); double segmentLength = lastSegment.distance(next); result._segmentFraction += (distance / segmentLength); // this can happen due to floating point errors when the new location is very close to a // node. if (result._segmentFraction >= 1.0) { result._segmentFraction = 0.0; result._segmentIndex = result._segmentIndex + 1; } distance = 0; } // if we need to go past the next node else { distance -= delta; last = next; result._segmentIndex = result.getSegmentIndex() + 1; result._segmentFraction = 0.0; } } // This odd statement avoid us subtracting irrelevantly small distances. while (1 + distance < 1) { // if we're at the end of the way if (result.isFirst()) { return result; } if (result._segmentFraction > 0) { Coordinate next = _map->getNode(_way->getNodeId(result.getSegmentIndex()))->toCoordinate(); Meters delta = last.distance(next); if (distance + delta > 0) { // figure out what distance we need to move along the segment. Coordinate last = _map->getNode(_way->getNodeId(result._segmentIndex + 1))->toCoordinate(); double segmentLength = last.distance(next); result._segmentFraction += (distance / segmentLength); // this can happen due to floating point errors when the new location is very close to a // node. if (result._segmentFraction >= 1.0) { result._segmentFraction = 0.0; result._segmentIndex = result._segmentIndex + 1; } distance = 0; } else { result._segmentFraction = 0; distance += delta; last = next; } } else { Coordinate next = _map->getNode(_way->getNodeId(result.getSegmentIndex() - 1))-> toCoordinate(); Meters delta = last.distance(next); if (distance + delta > 0) { // figure out what distance we need to move along the segment. Coordinate last = _map->getNode(_way->getNodeId(result.getSegmentIndex()))->toCoordinate(); double segmentLength = last.distance(next); result._segmentFraction = 1.0 + (distance / segmentLength); // if we're suffering from a floating point issue. if (result._segmentFraction >= 1.0) { // make sure the floating point issue is within the expected bounds. assert(result._segmentFraction < 1.0 + 1e-14); result._segmentFraction = 0; } else { result._segmentIndex = result.getSegmentIndex() - 1; } distance = 0; } else { result._segmentIndex--; distance += delta; last = next; } } } assert(result._segmentFraction < 1.0 && result._segmentFraction >= 0); assert(result._segmentIndex >= 0 && result._segmentIndex < (int)result.getWay()->getNodeCount()); return result; }