WaySublineMatchString MaximalNearestSublineMatcher::findMatch(const ConstOsmMapPtr &map, const ConstWayPtr& way1, const ConstWayPtr &way2, double &score, Meters maxRelevantDistance) const { score = 0; Meters mrd = maxRelevantDistance == -1 ? way1->getCircularError() + way2->getCircularError() : maxRelevantDistance; vector<long> wayIds; wayIds.push_back(way1->getId()); wayIds.push_back(way2->getId()); OsmMapPtr mapCopy(map->copyWays(wayIds)); WayPtr way1NonConst = mapCopy->getWay(way1->getId()); WayPtr way2NonConst = mapCopy->getWay(way2->getId()); MaximalNearestSubline mns1( mapCopy, way1NonConst, way2NonConst, _minSplitSize, mrd, _maxRelevantAngle, _headingDelta); // use the maximal nearest subline code to find the best subline std::vector<WayLocation> interval1 = mns1.getInterval(); if (!interval1[0].isValid() || !interval1[1].isValid() || interval1[0] == interval1[1]) { // if the interval isn't valid then return an invalid result. return WaySublineMatchString(); } _snapToEnds(map, interval1); WayPtr subline1 = WaySubline(interval1[0], interval1[1]).toWay(mapCopy); MaximalNearestSubline mns2(mapCopy, way2NonConst, subline1, _minSplitSize, -1, -1, _headingDelta); std::vector<WayLocation> interval2 = mns2.getInterval(); if (!interval2[0].isValid() || !interval2[1].isValid() || interval2[0] == interval2[1]) { return WaySublineMatchString(); } _snapToEnds(map, interval2); WaySublineMatch match = WaySublineMatch(WaySubline(interval1[0], interval1[1]), WaySubline(interval2[0], interval2[1])); if (subline1->getNodeCount() > 1) { shared_ptr<LineString> ls = ElementConverter(mapCopy).convertToLineString(subline1); if (ls->isValid()) { score = ls->getLength(); } } vector<WaySublineMatch> v; // switch the subline match to reference a different map. v.push_back(WaySublineMatch(match, map)); return WaySublineMatchString(v); }
void WayMergeManipulation::applyManipulation(OsmMapPtr map, set<ElementId> &impactedElements, set<ElementId> &newElements) const { OsmMapPtr result = map; // insert the impacted ways impactedElements = getImpactedElementIds(map); impactedElements.erase(ElementId::way(_left)); impactedElements.erase(ElementId::way(_right)); // remove any ways that spanned the left & right _removeSpans(result, impactedElements); WayPtr left = result->getWay(_left); WayPtr right = result->getWay(_right); Meters minSplitSize = _minSplitSize; minSplitSize = min(minSplitSize, ElementConverter(map).convertToLineString(left)->getLength() * .7); minSplitSize = min(minSplitSize, ElementConverter(map).convertToLineString(right)->getLength() * .7); // split left into its maximal nearest sublines MaximalNearestSubline mns1(map, left, right, minSplitSize, left->getCircularError() + right->getCircularError()); int mnsLeftIndex; vector< WayPtr > splitsLeft = mns1.splitWay(result, mnsLeftIndex); assert(splitsLeft.size() != 0); WayPtr mnsLeft = splitsLeft[mnsLeftIndex]; // split right into its maximal nearest sublines MaximalNearestSubline mns2(map, right, mnsLeft, minSplitSize, left->getCircularError() + right->getCircularError()); int mnsRightIndex; vector< WayPtr > splitsRight = mns2.splitWay(result, mnsRightIndex); assert(splitsRight.size() != 0); WayPtr mnsRight = splitsRight[mnsRightIndex]; for (size_t i = 0; i < splitsLeft.size(); i++) { if ((int)i != mnsLeftIndex) { newElements.insert(ElementId::way(splitsLeft[i]->getId())); } result->addWay(splitsLeft[i]); } for (size_t i = 0; i < splitsRight.size(); i++) { if ((int)i != mnsRightIndex) { newElements.insert(ElementId::way(splitsRight[i]->getId())); } result->addWay(splitsRight[i]); } // average the two MNSs WayPtr w = WayAverager::average(map, mnsRight, mnsLeft); w->setStatus(Status::Conflated); RemoveWayOp::removeWay(result, _left); RemoveWayOp::removeWay(result, _right); result->addWay(w); // insert the new merged way newElements.insert(ElementId::way(w->getId())); for (set<ElementId>::iterator it = impactedElements.begin(); it != impactedElements.end(); ++it) { if (result->containsElement(*it) == false) { LOG_ERROR("" << "Internal error: bad way " << it->toString()); } } }
void WayMergeManipulation::_splitWays(OsmMapPtr map, WayPtr& left, WayPtr& right) const { OsmMapPtr result = map; // insert the impacted ways set<ElementId> impactedElements = getImpactedElementIds(map); impactedElements.erase(ElementId::way(_left)); impactedElements.erase(ElementId::way(_right)); // remove any ways that spanned the left & right _removeSpans(result, impactedElements); left = result->getWay(_left); right = result->getWay(_right); Meters minSplitSize = _minSplitSize; minSplitSize = min(minSplitSize, ElementConverter(map).convertToLineString(left)->getLength() * .7); minSplitSize = min(minSplitSize, ElementConverter(map).convertToLineString(right)->getLength() * .7); // split left into its maximal nearest sublines MaximalNearestSubline mns1(result, left, right, minSplitSize, left->getCircularError() + right->getCircularError()); int mnsLeftIndex; vector< WayPtr > splitsLeft = mns1.splitWay(result, mnsLeftIndex); assert(splitsLeft.size() != 0); WayPtr mnsLeft = splitsLeft[mnsLeftIndex]; // split right into its maximal nearest sublines MaximalNearestSubline mns2(result, right, mnsLeft, minSplitSize, left->getCircularError() + right->getCircularError()); int mnsRightIndex; vector< WayPtr > splitsRight = mns2.splitWay(result, mnsRightIndex); assert(splitsRight.size() != 0); WayPtr mnsRight = splitsRight[mnsRightIndex]; for (size_t i = 0; i < splitsLeft.size(); i++) { if (splitsLeft[i] != left) { result->addWay(splitsLeft[i]); } } for (size_t i = 0; i < splitsRight.size(); i++) { if (splitsRight[i] != right) { result->addWay(splitsRight[i]); } } RemoveWayOp::removeWay(result, _left); RemoveWayOp::removeWay(result, _right); for (set<ElementId>::iterator it = impactedElements.begin(); it != impactedElements.end(); ++it) { if (result->containsElement(*it) == false) { LOG_ERROR("" << "Internal error: bad way " << it->toString()); } } left = mnsLeft; right = mnsRight; }