void MaximalSublineStringMatcher::_validateElement(const ConstOsmMapPtr& map, ElementId eid) const { ConstElementPtr e = map->getElement(eid); if (e->getElementType() == ElementType::Relation) { ConstRelationPtr r = dynamic_pointer_cast<const Relation>(e); if (OsmSchema::getInstance().isMultiLineString(*r) == false) { throw NeedsReviewException("Internal Error: When matching sublines expected a multilinestring " "relation not a " + r->getType() + ". A non-multilinestring should never be found here. " "Please report this to [email protected]"); } const vector<RelationData::Entry>& entries = r->getMembers(); for (size_t i = 0; i < entries.size(); i++) { if (entries[i].getElementId().getType() != ElementType::Way) { throw NeedsReviewException("MultiLineString relations can only contain ways when matching " "sublines."); } } } if (e->getElementType() == ElementType::Way) { ConstWayPtr w = dynamic_pointer_cast<const Way>(e); if (w->getNodeCount() <= 1) { throw NeedsReviewException("Internal Error: Attempting to match against a zero length way."); } } }
void MaximalSublineStringMatcher::_validateElement(const ConstOsmMapPtr& map, ElementId eid) const { ConstElementPtr e = map->getElement(eid); if (e->getElementType() == ElementType::Relation) { ConstRelationPtr r = dynamic_pointer_cast<const Relation>(e); if (OsmSchema::getInstance().isMultiLineString(*r) == false) { throw NeedsReviewException("When matching sublines expected a multilinestring relation not" " a " + r->getType()); } const vector<RelationData::Entry>& entries = r->getMembers(); for (size_t i = 0; i < entries.size(); i++) { if (entries[i].getElementId().getType() != ElementType::Way) { throw NeedsReviewException("MultiLineString relations can only contain ways when matching " "sublines."); } } } }
WaySublineMatchString MaximalSublineStringMatcher::findMatch(const ConstOsmMapPtr& map, const ConstElementPtr& e1, const ConstElementPtr& e2, Meters maxRelevantDistance) const { assert(_maxAngle >= 0); if (maxRelevantDistance == -1) { maxRelevantDistance = e1->getCircularError() + e2->getCircularError(); } // make sure the inputs are legit. If either element isn't legit then throw a NeedsReviewException _validateElement(map, e1->getElementId()); _validateElement(map, e2->getElementId()); // extract the ways from the elements. In most cases it will return a vector of 1, but // multilinestrings may contain multiple ways vector<ConstWayPtr> ways1 = ExtractWaysVisitor::extractWays(map, e1); vector<ConstWayPtr> ways2 = ExtractWaysVisitor::extractWays(map, e2); if ((ways1.size() > 4 && ways2.size() > 4) || (ways1.size() + ways2.size() > 7)) { throw NeedsReviewException("Elements contain too many ways and the computational complexity " "is unreasonable."); } // Try with all combinations of forward and reversed ways. This is very expensive for // multilinestrings with lots of ways in them. Though those shouldn't be common. vector<bool> reversed1(ways1.size(), false), reversed2(ways2.size(), false); ScoredMatch scoredResult = _findBestMatch(map, maxRelevantDistance, ways1, ways2, reversed1, reversed2); // convert the best match into a WaySublineStringMatch and return. try { WaySublineMatchString result = scoredResult.matches; // this likely shouldn't be necessary. See #4593 result.removeEmptyMatches(); return result; } catch(OverlappingMatchesException &e) { throw NeedsReviewException("Internal Error: Multiple overlapping way matches were found within " "one set of ways. Please report this to [email protected]."); } }