void RemoveDuplicateReviewsOp::apply(shared_ptr<OsmMap>& map) { _map = map; // go through all the relations to get duplicate reviews const RelationMap& relations = map->getRelationMap(); QMap< set<ElementId>, QList<ReviewMarker::ReviewUid> > membersToReview; for (RelationMap::const_iterator it = relations.begin(); it != relations.end(); it++) { ElementId eid = ElementId::relation(it->first); if (ReviewMarker::isReviewUid(map, eid)) { membersToReview[ReviewMarker::getReviewElements(map, eid)].append(eid); } } //loop through dupplicate reviews QMap< set<ElementId>, QList<ReviewMarker::ReviewUid> >::iterator it = membersToReview.begin(); while (it != membersToReview.end()) { set<ElementId> eids = it.key(); //remove duplicate reviews QList<ReviewMarker::ReviewUid> duplicateReviews = it.value(); //Only remove reviews and process if there is more than one review // See discussion here: https://github.com/ngageoint/hootenanny/issues/81#issuecomment-162980656 if (eids.size() == 2 && duplicateReviews.size() > 1) { for (int i = 0; i < duplicateReviews.size(); i++) { ReviewMarker::removeElement(map, duplicateReviews[i]); } ElementId beid = *eids.begin(); ElementId eeid = *eids.rbegin(); OsmMapPtr copy(new OsmMap()); CopySubsetOp(map, beid, eeid).apply(copy); copy->getElement(beid)->setStatus(Status::Unknown1); copy->getElement(eeid)->setStatus(Status::Unknown2); Match* match = MatchFactory::getInstance().createMatch(copy, beid, eeid); if (match && match->getType() != MatchType::Miss) { QString explain = match->explain(); if (match->getType() == MatchType::Match) { if (explain.isEmpty()) { explain = "Multiple overlapping high confidence reviews"; } else { explain = "Multiple overlapping high confidence reviews: " + explain; } } ReviewMarker::mark(map, map->getElement(beid), map->getElement(eeid), explain, match->getMatchName(), match->getClassification().getReviewP()); } } ++it; } }
Handle<Value> SublineStringMatcherJs::extractMatchingSublines(const Arguments& args) { HandleScope scope; SublineStringMatcherJs* smJs = ObjectWrap::Unwrap<SublineStringMatcherJs>(args.This()); SublineStringMatcherPtr sm = smJs->getSublineStringMatcher(); OsmMapJs* mapJs = ObjectWrap::Unwrap<OsmMapJs>(args[0]->ToObject()); ElementJs* e1Js = ObjectWrap::Unwrap<ElementJs>(args[1]->ToObject()); ElementJs* e2Js = ObjectWrap::Unwrap<ElementJs>(args[2]->ToObject()); ConstOsmMapPtr m = mapJs->getConstMap(); ConstElementPtr e1 = e1Js->getConstElement(); ConstElementPtr e2 = e2Js->getConstElement(); Handle<Value> result; try { WaySublineMatchString match = sm->findMatch(m, e1, e2); if (match.isEmpty()) { return Undefined(); } // convert match into elements in a new map. set<ElementId> eids; eids.insert(e1->getElementId()); eids.insert(e2->getElementId()); OsmMapPtr copiedMap(new OsmMap(m->getProjection())); CopySubsetOp(m, eids).apply(copiedMap); WaySublineMatchString copiedMatch(match, copiedMap); // split the shared line based on the matching subline ElementPtr match1, scraps1; ElementPtr match2, scraps2; WaySublineString string1 = copiedMatch.getSublineString1(); WaySublineString string2 = copiedMatch.getSublineString2(); try { MultiLineStringSplitter().split(copiedMap, string1, copiedMatch.getReverseVector1(), match1, scraps1); MultiLineStringSplitter().split(copiedMap, string2, copiedMatch.getReverseVector2(), match2, scraps2); } catch (const IllegalArgumentException& e) { // this is unusual print out some information useful to debugging. MapReprojector::reprojectToWgs84(copiedMap); LOG_WARN(OsmWriter::toString(copiedMap)); throw e; } if (!match1 || !match2) { result = Undefined(); } else { Handle<Object> obj = Object::New(); obj->Set(String::NewSymbol("map"), OsmMapJs::create(copiedMap)); obj->Set(String::NewSymbol("match1"), ElementJs::New(match1)); obj->Set(String::NewSymbol("match2"), ElementJs::New(match2)); result = obj; } } catch (const HootException& e) { return v8::ThrowException(HootExceptionJs::create(e)); } return scope.Close(result); }
MaximalSublineStringMatcher::ScoredMatch MaximalSublineStringMatcher::_evaluateMatch( const ConstOsmMapPtr &map, Meters maxDistance, const vector<ConstWayPtr>& ways1, const vector<ConstWayPtr> &ways2, const vector<bool>& reversed1, const vector<bool> &reversed2) const { vector<WaySublineMatch> matches; // make a copy of the map and the ways we need so we can reverse the ways as needed. set<ElementId> eids; _insertElementIds(ways1, eids); _insertElementIds(ways2, eids); OsmMapPtr copiedMap(new OsmMap(map->getProjection())); CopySubsetOp(map, eids).apply(copiedMap); vector<WayPtr> prep1 = _changeMap(ways1, copiedMap); vector<WayPtr> prep2 = _changeMap(ways2, copiedMap); // reversed ways as appropriate _reverseWays(prep1, reversed1); _reverseWays(prep2, reversed2); double scoreSum = 0; // go through and match each way against every other way for (size_t i = 0; i < prep1.size(); i++) { for (size_t j = 0; j < prep2.size(); j++) { double score; WaySublineMatchString m = _sublineMatcher->findMatch(copiedMap, prep1[i], prep2[j], score, maxDistance); scoreSum += score; matches.insert(matches.end(), m.getMatches().begin(), m.getMatches().end()); } } HashMap<long, bool> wayIdToReversed1, wayIdToReversed2; // create a map from way id to reverse status for (size_t i = 0; i < prep1.size(); i++) { wayIdToReversed1[prep1[i]->getId()] = reversed1[i]; } for (size_t i = 0; i < prep2.size(); i++) { wayIdToReversed2[prep2[i]->getId()] = reversed2[i]; } // go through all the matches for (size_t i = 0; i < matches.size(); i++) { WaySubline ws1, ws2; // if the direction is reversed on one but not both ways then mark the match as reversed. long m1Id = matches[i].getSubline1().getStart().getWay()->getId(); long m2Id = matches[i].getSubline2().getStart().getWay()->getId(); if (wayIdToReversed1[m1Id]) { // make sure the way subline is pointed to the right way (not reversed) ConstWayPtr w = map->getWay(matches[i].getSubline1().getElementId()); ws1 = matches[i].getSubline1().reverse(w); } else { ws1 = WaySubline(matches[i].getSubline1(), map); } if (wayIdToReversed2[m2Id]) { // make sure the way subline is pointed to the right way (not reversed) ConstWayPtr w = map->getWay(matches[i].getSubline2().getElementId()); ws2 = matches[i].getSubline2().reverse(w); } else { ws2 = WaySubline(matches[i].getSubline2(), map); } if (wayIdToReversed1[m1Id] != wayIdToReversed2[m2Id]) { matches[i] = WaySublineMatch(ws1, ws2, true); } else { matches[i] = WaySublineMatch(ws1, ws2, false); } } return ScoredMatch(scoreSum, matches); }