v0.2.55..v0.2.56 changeset DiffConflator.cpp
Garret Voltz edited this page Aug 14, 2020
·
3 revisions
diff --git a/hoot-core/src/main/cpp/hoot/core/conflate/DiffConflator.cpp b/hoot-core/src/main/cpp/hoot/core/conflate/DiffConflator.cpp
index 8965d6a..75fe114 100644
--- a/hoot-core/src/main/cpp/hoot/core/conflate/DiffConflator.cpp
+++ b/hoot-core/src/main/cpp/hoot/core/conflate/DiffConflator.cpp
@@ -86,6 +86,7 @@ HOOT_FACTORY_REGISTER(OsmMapOperation, DiffConflator)
DiffConflator::DiffConflator() :
_matchFactory(MatchFactory::getInstance()),
_settings(Settings::getInstance()),
+_intraDatasetElementIdsPopulated(false),
_taskStatusUpdateInterval(ConfigOptions().getTaskStatusUpdateInterval()),
_numSnappedWays(0)
{
@@ -96,6 +97,7 @@ DiffConflator::DiffConflator(const std::shared_ptr<MatchThreshold>& matchThresho
_matchFactory(MatchFactory::getInstance()),
_matchThreshold(matchThreshold),
_settings(Settings::getInstance()),
+_intraDatasetElementIdsPopulated(false),
_taskStatusUpdateInterval(ConfigOptions().getTaskStatusUpdateInterval()),
_numSnappedWays(0)
{
@@ -107,6 +109,13 @@ DiffConflator::~DiffConflator()
_reset();
}
+void DiffConflator::setConfiguration(const Settings &conf)
+{
+ _settings = conf;
+ _matchThreshold.reset();
+ _reset();
+}
+
void DiffConflator::_updateProgress(const int currentStep, const QString message)
{
// Always check for a valid task weight and that the job was set to running. Otherwise, this is
@@ -130,7 +139,7 @@ void DiffConflator::apply(OsmMapPtr& map)
_tagChangesetStats = "";
_unifiedChangesetStats = "";
- // Store the map - we might need it for tag diff later.
+ // Store the map, as we might need it for tag diff later.
_pMap = map;
// This status progress reporting could get way more granular, but we'll go with this for now to
@@ -158,7 +167,9 @@ void DiffConflator::apply(OsmMapPtr& map)
_stats.append(SingleStat("Project to Planar Time (sec)", timer.getElapsedAndRestart()));
OsmMapWriterFactory::writeDebugMap(_pMap, "after-projecting-to-planar");
- // find all the matches in this _pMap
+ // find all the matches in this map
+ _intraDatasetMatchOnlyElementIds.clear();
+ _intraDatasetElementIdsPopulated = false;
if (_matchThreshold.get())
{
_matchFactory.createMatches(_pMap, _matches, _bounds, _matchThreshold);
@@ -253,34 +264,53 @@ void DiffConflator::_removeMatches(const Status& status)
const bool treatReviewsAsMatches = ConfigOptions().getDifferentialTreatReviewsAsMatches();
LOG_VARD(treatReviewsAsMatches);
+
+ if (!_intraDatasetElementIdsPopulated)
+ {
+ _intraDatasetMatchOnlyElementIds = _getElementIdsInvolvedInOnlyIntraDatasetMatches(_matches);
+ _intraDatasetElementIdsPopulated = true;
+ }
+
for (std::vector<ConstMatchPtr>::iterator mit = _matches.begin(); mit != _matches.end(); ++mit)
{
ConstMatchPtr match = *mit;
+ LOG_VART(match);
if (treatReviewsAsMatches || match->getType() != MatchType::Review)
{
- std::set<std::pair<ElementId, ElementId>> pairs = (*mit)->getMatchPairs();
+ std::set<std::pair<ElementId, ElementId>> pairs = match->getMatchPairs();
for (std::set<std::pair<ElementId, ElementId>>::iterator pit = pairs.begin();
pit != pairs.end(); ++pit)
- {
+ {
+ ElementPtr e1;
+ ElementPtr e2;
+
if (!pit->first.isNull())
{
LOG_VART(pit->first);
- ElementPtr e = _pMap->getElement(pit->first);
- if (e && e->getStatus() == status)
- {
- //LOG_VART(e->getTags().get("name"));
- RecursiveElementRemover(pit->first).apply(_pMap);
- }
+ e1 = _pMap->getElement(pit->first);
+
}
if (!pit->second.isNull())
{
LOG_VART(pit->second);
- ElementPtr e = _pMap->getElement(pit->second);
- if (e && e->getStatus() == status)
- {
- //LOG_VART(e->getTags().get("name"));
- RecursiveElementRemover(pit->second).apply(_pMap);
- }
+ e2 = _pMap->getElement(pit->second);
+ }
+
+ if (e1 && e1->getStatus() == status &&
+ // poi/poly is the only conflation type that allows intra-dataset matches. We don't want
+ // these to be removed from the diff output.
+ !(match->getMatchName() == PoiPolygonMatch::MATCH_NAME &&
+ _intraDatasetMatchOnlyElementIds.contains(pit->first)))
+ {
+ LOG_VART(e1);
+ RecursiveElementRemover(pit->first).apply(_pMap);
+ }
+ if (e2 && e2->getStatus() == status &&
+ !(match->getMatchName() == PoiPolygonMatch::MATCH_NAME &&
+ _intraDatasetMatchOnlyElementIds.contains(pit->second)))
+ {
+ LOG_VART(e2);
+ RecursiveElementRemover(pit->second).apply(_pMap);
}
}
}
@@ -289,11 +319,70 @@ void DiffConflator::_removeMatches(const Status& status)
OsmMapWriterFactory::writeDebugMap(_pMap, "after-removing-" + status.toString() + "-matches");
}
-void DiffConflator::setConfiguration(const Settings &conf)
+QSet<ElementId> DiffConflator::_getElementIdsInvolvedInOnlyIntraDatasetMatches(
+ const std::vector<ConstMatchPtr>& matches)
{
- _settings = conf;
- _matchThreshold.reset();
- _reset();
+ QSet<ElementId> elementIds;
+
+ const bool allowReviews = ConfigOptions().getDifferentialTreatReviewsAsMatches();
+
+ // Go through and record any element's involved in an intra-dataset match, since we don't want
+ // those types of matches from preventing an element from passing through to the diff output.
+
+ for (std::vector<ConstMatchPtr>::const_iterator matchItr = matches.begin();
+ matchItr != matches.end(); ++matchItr)
+ {
+ ConstMatchPtr match = *matchItr;
+ if (match->getType() == MatchType::Match ||
+ (allowReviews && match->getType() == MatchType::Review))
+ {
+ std::set<std::pair<ElementId, ElementId>> pairs = match->getMatchPairs();
+ for (std::set<std::pair<ElementId, ElementId>>::const_iterator pairItr = pairs.begin();
+ pairItr != pairs.end(); ++pairItr)
+ {
+ std::pair<ElementId, ElementId> pair = *pairItr;
+ ConstElementPtr e1 = _pMap->getElement(pair.first);
+ ConstElementPtr e2 = _pMap->getElement(pair.second);
+ // Any match with elements having the same status (came from the same dataset) is an
+ // intra-dataset match.
+ if (e1 && e2 && e1->getStatus() == e2->getStatus())
+ {
+ elementIds.insert(pair.first);
+ elementIds.insert(pair.second);
+ }
+ }
+ }
+ }
+
+ // Now, go back through and exclude any previously added that are also involved in an
+ // inter-dataset match, since we don't want those in the diff output.
+
+ for (std::vector<ConstMatchPtr>::const_iterator matchItr = matches.begin();
+ matchItr != matches.end(); ++matchItr)
+ {
+ ConstMatchPtr match = *matchItr;
+ if (match->getType() == MatchType::Match ||
+ (allowReviews && match->getType() == MatchType::Review))
+ {
+ std::set<std::pair<ElementId, ElementId>> pairs = match->getMatchPairs();
+ for (std::set<std::pair<ElementId, ElementId>>::const_iterator pairItr = pairs.begin();
+ pairItr != pairs.end(); ++pairItr)
+ {
+ std::pair<ElementId, ElementId> pair = *pairItr;
+ ConstElementPtr e1 = _pMap->getElement(pair.first);
+ ConstElementPtr e2 = _pMap->getElement(pair.second);
+ // Any match with elements having a different status (came from different datasets) is an
+ // inter-dataset match.
+ if (e1 && e2 && e1->getStatus() != e2->getStatus())
+ {
+ elementIds.remove(pair.first);
+ elementIds.remove(pair.second);
+ }
+ }
+ }
+ }
+
+ return elementIds;
}
MemChangesetProviderPtr DiffConflator::getTagDiff()
@@ -516,8 +605,11 @@ Change DiffConflator::_getChange(ConstElementPtr pOldElement, ConstElementPtr pN
// Need to merge tags into the new element. Keeps all names, chooses tags1 in event of a conflict.
Tags newTags =
- TagComparator::getInstance().overwriteMerge(pNewElement->getTags(), pOldElement->getTags(), QStringList(),
- ConfigOptions().getDuplicateNameCaseSensitive());
+ TagComparator::getInstance().overwriteMerge(
+ pNewElement->getTags(), pOldElement->getTags(),
+ ConfigOptions().getTagMergerOverwriteExclude(),
+ ConfigOptions().getTagMergerOverwriteAccumulateValuesKeys(),
+ ConfigOptions().getDuplicateNameCaseSensitive());
pChangeElement->setTags(newTags);
// Create the change