bool PoiPolygonMergerCreator::_isConflictingSet(const MatchSet& matches) const { // _map must be set using setOsmMap() assert(_map != 0); bool conflicting = false; for (MatchSet::const_iterator it = matches.begin(); it != matches.end(); ++it) { const Match* m1 = *it; for (MatchSet::const_iterator jt = matches.begin(); jt != matches.end(); ++jt) { const Match* m2 = *jt; if (m1 != m2) { ConstOsmMapPtr map = _map->shared_from_this(); if (MergerFactory::getInstance().isConflicting(map, m1, m2)) { conflicting = true; } } } } return conflicting; }
bool PoiPolygonMergerCreator::createMergers(const MatchSet& matches, vector<Merger*>& mergers) const { bool result = false; assert(matches.size() > 0); bool foundAPoi = false; bool foundAPolygon = false; // go through all the matches for (MatchSet::const_iterator it = matches.begin(); it != matches.end(); ++it) { const Match* m = *it; if (m->getMatchMembers() & MatchMembers::Poi) { foundAPoi = true; } if (m->getMatchMembers() & MatchMembers::Polygon) { foundAPolygon = true; } } // if there is at least one POI and at least one polygon, then we need to merge things in a // special way. if (foundAPoi && foundAPolygon) { set< pair<ElementId, ElementId> > eids; // go through all the matches for (MatchSet::const_iterator it = matches.begin(); it != matches.end(); ++it) { set< pair<ElementId, ElementId> > s = (*it)->getMatchPairs(); eids.insert(s.begin(), s.end()); } if (_isConflictingSet(matches)) { mergers.push_back(new MarkForReviewMerger(eids, "Conflicting information", 1)); } else { mergers.push_back(new PoiPolygonMerger(eids)); } result = true; } return result; }
bool PlacesPoiMergerCreator::createMergers(const MatchSet& matches, vector<Merger*>& mergers) const { bool result = false; assert(matches.size() > 0); set< pair<ElementId, ElementId> > eids; // go through all the matches for (MatchSet::const_iterator it = matches.begin(); it != matches.end(); ++it) { const PlacesPoiMatch* pm = dynamic_cast<const PlacesPoiMatch*>(*it); // check to make sure all the input matches are building matches. if (pm == 0) { // return an empty result return false; } // add all the element to element pairs to a set else { set< pair<ElementId, ElementId> > s = pm->getMatchPairs(); eids.insert(s.begin(), s.end()); } } // only add the POI merge if there are elements to merge. if (eids.size() > 0) { mergers.push_back(new PlacesPoiMerger(eids)); result = true; } return result; }
// filter extraneous matches static void filterMatches(MatchSet &matches) { set<size_t> eom; // first, collect all end-offset matches for (const auto &match : matches) { eom.insert(match.second); } // now, go through all the end-offsets and filter extra matches for (const auto &elem : eom) { // find minimum SOM for this EOM size_t min_som = -1U; for (const auto &match : matches) { // skip entries with wrong EOM if (match.second != elem) { continue; } min_som = min(min_som, match.first); } auto msit = matches.begin(); while (msit != matches.end()) { // skip everything that doesn't match if (msit->second != elem || msit->first <= min_som) { ++msit; continue; } DEBUG_PRINTF("erasing match %zu, %zu\n", msit->first, msit->second); matches.erase(msit++); } } }
void runFindSubgraphsTest() { // See this for a visual. // https://insightcloud.digitalglobe.com/redmine/attachments/download/1638/Hootenanny%20-%20Graph%20Based%20Conflation%20-%202013-06-21.pptx ElementId a1 = ElementId::way(1); ElementId a2 = ElementId::way(2); ElementId a3 = ElementId::way(3); // unused //ElementId a4 = ElementId::way(4); ElementId b1 = ElementId::way(5); ElementId b2 = ElementId::way(5); ElementId b3 = ElementId::way(6); vector<const Match*> matches; // force the pointers to be in order which forces the set to be consistent between runs. ConstrainedFakeMatch* fm = new ConstrainedFakeMatch[4]; shared_ptr<MatchThreshold> mt(new MatchThreshold(0.5, 0.5)); matches.push_back(fm[0].init(a1, b1, 0.8, mt)->addConflict(&fm[1])); matches.push_back(fm[1].init(a2, b1, 1, mt)->addConflict(&fm[2])); matches.push_back(fm[2].init(a2, b2, 0.9, mt)); matches.push_back(fm[3].init(a3, b3, 0.9, mt)); ConstOsmMapPtr empty; OptimalConstrainedMatches uut(empty); uut.addMatches(matches.begin(), matches.end()); vector<const Match*> subsetVector = uut.calculateSubset(); MatchSet matchSet; matchSet.insert(subsetVector.begin(), subsetVector.end()); CPPUNIT_ASSERT_DOUBLES_EQUAL(2.6, uut.getScore(), 0.001); CPPUNIT_ASSERT_EQUAL((size_t)3, matchSet.size()); CPPUNIT_ASSERT_EQUAL(true, matchSet.find(&fm[0]) != matchSet.end()); CPPUNIT_ASSERT_EQUAL(true, matchSet.find(&fm[2]) != matchSet.end()); CPPUNIT_ASSERT_EQUAL(true, matchSet.find(&fm[3]) != matchSet.end()); }
bool HighwayMergerCreator::createMergers(const MatchSet& matches, vector<Merger*>& mergers) const { LOG_TRACE("Creating mergers with " << className() << "..."); bool result = false; assert(matches.size() > 0); set<pair<ElementId, ElementId>> eids; boost::shared_ptr<SublineStringMatcher> sublineMatcher; // go through all the matches for (MatchSet::const_iterator it = matches.begin(); it != matches.end(); ++it) { const Match* m = *it; LOG_VART(m->toString()); const HighwayMatch* hm = dynamic_cast<const HighwayMatch*>(m); // check to make sure all the input matches are building matches. if (hm == 0) { // return an empty result LOG_TRACE("Returning empty result due to match not being HighwayMatch: " << m->toString()); return false; } // add all the element to element pairs to a set else { // there should only be one HighwayMatch in a set. sublineMatcher = hm->getSublineMatcher(); set<pair<ElementId, ElementId>> s = hm->getMatchPairs(); LOG_VART(s); eids.insert(s.begin(), s.end()); } } LOG_VART(eids); // only add the highway merge if there are elements to merge. if (eids.size() > 0) { if (!ConfigOptions().getHighwayMergeTagsOnly()) { mergers.push_back(new HighwaySnapMerger(eids, sublineMatcher)); } else { mergers.push_back(new HighwayTagOnlyMerger(eids, sublineMatcher)); } result = true; } return result; }
bool MarkForReviewMergerCreator::createMergers(const MatchSet& matches, vector<Merger*>& mergers) const { bool result = false; set< pair<ElementId, ElementId> > eids; int reviewCount = 0; QStringList matchStrings; double score = 0; // go through all the matches for (MatchSet::const_iterator it = matches.begin(); it != matches.end(); ++it) { const Match* match = (*it); //MatchType type = _mt.getType(*(*it)); MatchType type = match->getType(); if (type == MatchType::Review) { set< pair<ElementId, ElementId> > s = (*it)->getMatchPairs(); eids.insert(s.begin(), s.end()); matchStrings.append((*it)->explain()); score = max<double>((*it)->getClassification().getReviewP(), score); reviewCount++; } } if (reviewCount > 0 && reviewCount != int(matches.size())) { throw HootException("Expected the whole set to be review matches."); } // only add the mark for review merger if there are elements to merge. if (eids.size() > 0) { mergers.push_back(new MarkForReviewMerger(eids, matchStrings.join(","), score)); result = true; } return result; }
bool HighwaySnapMergerCreator::createMergers(const MatchSet& matches, vector<Merger*>& mergers) const { bool result = false; assert(matches.size() > 0); set< pair<ElementId, ElementId> > eids; shared_ptr<SublineStringMatcher> sublineMatcher; // go through all the matches for (MatchSet::const_iterator it = matches.begin(); it != matches.end(); ++it) { const HighwayMatch* hm = dynamic_cast<const HighwayMatch*>(*it); // check to make sure all the input matches are building matches. if (hm == 0) { // return an empty result return false; } // add all the element to element pairs to a set else { // there should only be one HighwayMatch in a set. sublineMatcher = hm->getSublineMatcher(); set< pair<ElementId, ElementId> > s = hm->getMatchPairs(); eids.insert(s.begin(), s.end()); } } // only add the highway merge if there are elements to merge. if (eids.size() > 0) { mergers.push_back(new HighwaySnapMerger(_minSplitSize, eids, sublineMatcher)); result = true; } return result; }
bool NetworkMergerCreator::createMergers(const MatchSet& matchesIn, vector<Merger*>& mergers) const { LOG_TRACE("Creating mergers with " << className() << "..."); LOG_TRACE("Creating mergers for match set: " << matchesIn); QString matchesList = ""; if (hoot::Log::Trace == hoot::Log::getInstance().getLevel()) { for (MatchSet::const_iterator it = matchesIn.begin(); it != matchesIn.end(); ++it) { const NetworkMatch* nmi = dynamic_cast<const NetworkMatch*>(*it); if (nmi) { matchesList += nmi->getEdgeMatch()->getUid() + " "; } } } LOG_TRACE(matchesList.size()); LOG_TRACE(matchesList); MatchSet matches = matchesIn; LOG_VART(matches); bool result = false; assert(matches.size() > 0); const NetworkMatch* m = dynamic_cast<const NetworkMatch*>(*matches.begin()); if (m) { const bool matchOverlap = _containsOverlap(matches); LOG_VART(matchOverlap); if (!matchOverlap) { // create a merger that can merge multiple partial matches QSet<ConstEdgeMatchPtr> edgeMatches; int count = 0; set<pair<ElementId, ElementId>> pairs; foreach (const Match* itm, matches) { const NetworkMatch* nm = dynamic_cast<const NetworkMatch*>(itm); edgeMatches.insert(nm->getEdgeMatch()); set<pair<ElementId, ElementId>> p = nm->getMatchPairs(); pairs.insert(p.begin(), p.end()); count++; if (count % 100 == 0) { PROGRESS_INFO( "Added match " << count << " / " << matches.size() << " to partial network merger..."); } } if (!ConfigOptions().getHighwayMergeTagsOnly()) { mergers.push_back(new PartialNetworkMerger(pairs, edgeMatches, m->getNetworkDetails())); } else { // TODO: We need to allow for HighwayTagOnlyMerger to spawn off PartialNetworkMerger here, // I guess...but that's kind of nasty... (applies to the rest of the calls to // HighwayTagOnlyMerger in this class as well). mergers.push_back(new HighwayTagOnlyMerger(pairs)); } } else { // If one match completely contains the rest, use the larger match. This may need to be // reverted as we play with more data, but at this point it seems like a reasonable heuristic. if (const NetworkMatch* larger = _getLargestContainer(matches))
bool ScriptMergerCreator::createMergers(const MatchSet& matches, vector<Merger*>& mergers) const { bool result = false; assert(matches.size() > 0); set< pair<ElementId, ElementId> > eids; shared_ptr<PluginContext> script; Persistent<Object> plugin; QStringList matchType; // go through all the matches for (MatchSet::const_iterator it = matches.begin(); it != matches.end(); ++it) { const ScriptMatch* sm = dynamic_cast<const ScriptMatch*>(*it); // check to make sure all the input matches are building matches. if (sm == 0) { // return an empty result return false; } // add all the element to element pairs to a set else { script = sm->getScript(); HandleScope handleScope; Context::Scope context_scope(script->getContext()); plugin = sm->getPlugin(); set< pair<ElementId, ElementId> > s = sm->getMatchPairs(); eids.insert(s.begin(), s.end()); if (matchType.contains(sm->getMatchName()) == false) { matchType.append(sm->getMatchName()); } } } ScriptMerger* sm = new ScriptMerger(script, plugin, eids); // only add the POI merge if there are elements to merge. if (sm->hasFunction("mergeSets")) { if (eids.size() >= 1) { mergers.push_back(sm); result = true; } else { delete sm; } } else { if (eids.size() == 1) { mergers.push_back(sm); result = true; } else if (eids.size() > 1) { delete sm; mergers.push_back(new MarkForReviewMerger(eids, "Overlapping matches", matchType.join(";"), 1.0)); result = true; } else { delete sm; } } return result; }