Skip to content

v0.2.49..v0.2.50 changeset DiffConflator.cpp

Garret Voltz edited this page Nov 6, 2019 · 1 revision
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 4270453..3318ec0 100644
--- a/hoot-core/src/main/cpp/hoot/core/conflate/DiffConflator.cpp
+++ b/hoot-core/src/main/cpp/hoot/core/conflate/DiffConflator.cpp
@@ -27,36 +27,36 @@
 #include "DiffConflator.h"
 
 // hoot
-#include <hoot/core/elements/InMemoryElementSorter.h>
 #include <hoot/core/algorithms/changeset/MultipleChangesetProvider.h>
+#include <hoot/core/conflate/matching/GreedyConstrainedMatches.h>
+#include <hoot/core/conflate/matching/MatchClassification.h>
 #include <hoot/core/conflate/matching/MatchFactory.h>
 #include <hoot/core/conflate/matching/MatchThreshold.h>
-#include <hoot/core/conflate/matching/GreedyConstrainedMatches.h>
 #include <hoot/core/conflate/matching/OptimalConstrainedMatches.h>
+#include <hoot/core/conflate/poi-polygon/PoiPolygonMatch.h>
 #include <hoot/core/criterion/BuildingCriterion.h>
 #include <hoot/core/criterion/PoiCriterion.h>
 #include <hoot/core/criterion/StatusCriterion.h>
 #include <hoot/core/criterion/TagKeyCriterion.h>
+#include <hoot/core/elements/ElementId.h>
+#include <hoot/core/elements/InMemoryElementSorter.h>
+#include <hoot/core/elements/OsmUtils.h>
 #include <hoot/core/io/OsmMapWriterFactory.h>
 #include <hoot/core/io/OsmXmlChangesetFileWriter.h>
 #include <hoot/core/ops/RecursiveElementRemover.h>
 #include <hoot/core/ops/NonConflatableElementRemover.h>
+#include <hoot/core/ops/UnconnectedWaySnapper.h>
+#include <hoot/core/schema/MetadataTags.h>
+#include <hoot/core/schema/TagComparator.h>
 #include <hoot/core/util/ConfigOptions.h>
 #include <hoot/core/util/Factory.h>
 #include <hoot/core/util/MapProjector.h>
-#include <hoot/core/conflate/matching/MatchClassification.h>
-#include <hoot/core/elements/ElementId.h>
-#include <hoot/core/schema/MetadataTags.h>
-#include <hoot/core/schema/TagComparator.h>
 #include <hoot/core/util/Log.h>
+#include <hoot/core/util/StringUtils.h>
 #include <hoot/core/visitors/AddRef1Visitor.h>
 #include <hoot/core/visitors/CriterionCountVisitor.h>
 #include <hoot/core/visitors/LengthOfWaysVisitor.h>
 #include <hoot/core/visitors/RemoveElementsVisitor.h>
-#include <hoot/core/ops/UnconnectedWaySnapper.h>
-#include <hoot/core/util/StringUtils.h>
-#include <hoot/core/elements/OsmUtils.h>
-#include <hoot/core/conflate/poi-polygon/PoiPolygonMatch.h>
 
 // standard
 #include <algorithm>
@@ -78,14 +78,16 @@ HOOT_FACTORY_REGISTER(OsmMapOperation, DiffConflator)
 
 DiffConflator::DiffConflator() :
   _matchFactory(MatchFactory::getInstance()),
-  _settings(Settings::getInstance())
+  _settings(Settings::getInstance()),
+  _taskStatusUpdateInterval(ConfigOptions().getTaskStatusUpdateInterval())
 {
   _reset();
 }
 
 DiffConflator::DiffConflator(const std::shared_ptr<MatchThreshold>& matchThreshold) :
   _matchFactory(MatchFactory::getInstance()),
-  _settings(Settings::getInstance())
+  _settings(Settings::getInstance()),
+  _taskStatusUpdateInterval(ConfigOptions().getTaskStatusUpdateInterval())
 {
   _matchThreshold = matchThreshold;
   _reset();
@@ -123,11 +125,15 @@ void DiffConflator::apply(OsmMapPtr& map)
 
   _updateProgress(currentStep - 1, "Matching features...");
 
-  LOG_DEBUG("\tDiscarding unconflatable elements...");
-  NonConflatableElementRemover().apply(_pMap);
-  _stats.append(
-    SingleStat("Remove Non-conflatable Elements Time (sec)", timer.getElapsedAndRestart()));
-  OsmMapWriterFactory::writeDebugMap(_pMap, "after-removing non-conflatable");
+  // If we skip this part, then any non-matchable data will simply pass through to output.
+  if (ConfigOptions().getDifferentialRemoveUnconflatableData())
+  {
+    LOG_INFO("Discarding unconflatable elements...");
+    NonConflatableElementRemover().apply(_pMap);
+    _stats.append(
+      SingleStat("Remove Non-conflatable Elements Time (sec)", timer.getElapsedAndRestart()));
+    OsmMapWriterFactory::writeDebugMap(_pMap, "after-removing non-conflatable");
+  }
 
   // will reproject only if necessary
   MapProjector::projectToPlanar(_pMap);
@@ -144,7 +150,7 @@ void DiffConflator::apply(OsmMapPtr& map)
     _matchFactory.createMatches(_pMap, _matches, _bounds);
   }
   LOG_INFO(
-    "\tFound: " << StringUtils::formatLargeNumber(_matches.size()) <<
+    "Found: " << StringUtils::formatLargeNumber(_matches.size()) <<
     " Differential Conflation matches.");
   double findMatchesTime = timer.getElapsedAndRestart();
   _stats.append(SingleStat("Find Matches Time (sec)", findMatchesTime));
@@ -155,9 +161,8 @@ void DiffConflator::apply(OsmMapPtr& map)
 
   currentStep++;
 
-  // Use matches to calculate and store tag diff. We must do this before we
-  // create the map diff, because that operation deletes all of the info needed
-  // for calculating the tag diff.
+  // Use matches to calculate and store tag diff. We must do this before we create the map diff,
+  // because that operation deletes all of the info needed for calculating the tag diff.
   _updateProgress(currentStep - 1, "Storing tag differentials...");
   _calcAndStoreTagChanges();
   currentStep++;
@@ -213,28 +218,37 @@ void DiffConflator::_snapSecondaryRoadsBackToRef()
 void DiffConflator::_removeMatches(const Status& status)
 {
   LOG_DEBUG("\tRemoving match elements with status: " << status.toString() << "...");
-  for (std::vector<const Match*>::iterator mit = _matches.begin(); mit != _matches.end(); ++mit)
+
+  const bool treatReviewsAsMatches = ConfigOptions().getDifferentialTreatReviewsAsMatches();
+  LOG_VARD(treatReviewsAsMatches);
+  for (std::vector<ConstMatchPtr>::iterator mit = _matches.begin(); mit != _matches.end(); ++mit)
   {
-    std::set<std::pair<ElementId, ElementId>> pairs = (*mit)->getMatchPairs();
-    for (std::set<std::pair<ElementId, ElementId>>::iterator pit = pairs.begin();
-         pit != pairs.end(); ++pit)
+    ConstMatchPtr match = *mit;
+    if (treatReviewsAsMatches || match->getType() != MatchType::Review)
     {
-      if (!pit->first.isNull())
+      std::set<std::pair<ElementId, ElementId>> pairs = (*mit)->getMatchPairs();
+      for (std::set<std::pair<ElementId, ElementId>>::iterator pit = pairs.begin();
+           pit != pairs.end(); ++pit)
       {
-        LOG_VART(pit->first);
-        ElementPtr e = _pMap->getElement(pit->first);
-        if (e && e->getStatus() == status)
+        if (!pit->first.isNull())
         {
-          RecursiveElementRemover(pit->first).apply(_pMap);
+          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);
+          }
         }
-      }
-      if (!pit->second.isNull())
-      {
-        LOG_VART(pit->second);
-        ElementPtr e = _pMap->getElement(pit->second);
-        if (e && e->getStatus() == status)
+        if (!pit->second.isNull())
         {
-          RecursiveElementRemover(pit->second).apply(_pMap);
+          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);
+          }
         }
       }
     }
@@ -320,21 +334,18 @@ void DiffConflator::addChangesToMap(OsmMapPtr pMap, ChangesetProviderPtr pChange
     }
     else if (ElementType::Relation == c.getElement()->getElementType().getEnum())
     {
-      // Diff conflation doesn't do relations yet
+      // Diff conflation w/ tags doesn't handle relations. Changed this to silently log that the
+      // relations are being skipped for now. #3449 was created to deal with adding relation support
+      // and then closed since we lack a use case currently that requires it. If we ever get one,
+      // then we can re-open that issue.
 
-      if (logWarnCount < Log::getWarnMessageLimit())
+      LOG_DEBUG("Relation handling not implemented with differential conflation: " << c);
+      if (Log::getInstance().getLevel() <= Log::Trace)
       {
-        LOG_WARN("Relation handling not implemented with differential conflation: " << c);
-        LOG_VART(c);
         ConstRelationPtr relation = std::dynamic_pointer_cast<const Relation>(c.getElement());
         LOG_VART(relation->getElementId());
         LOG_VART(OsmUtils::getRelationDetailedString(relation, _pOriginalMap));
       }
-      else if (logWarnCount == Log::getWarnMessageLimit())
-      {
-        LOG_WARN(className() << ": " << Log::LOG_WARN_LIMIT_REACHED_MESSAGE);
-      }
-      logWarnCount++;
     }
   }
   OsmMapWriterFactory::writeDebugMap(pMap, "after-adding-diff-tag-changes");
@@ -342,7 +353,7 @@ void DiffConflator::addChangesToMap(OsmMapPtr pMap, ChangesetProviderPtr pChange
 
 void DiffConflator::_calcAndStoreTagChanges()
 {
-  LOG_DEBUG("\tStoring tag changes...");
+  LOG_INFO("Storing tag changes...");
 
   MapProjector::projectToWgs84(_pMap);
 
@@ -352,9 +363,10 @@ void DiffConflator::_calcAndStoreTagChanges()
     _pTagChanges.reset(new MemChangesetProvider(_pMap->getProjection()));
   }
 
-  for (std::vector<const Match*>::iterator mit = _matches.begin(); mit != _matches.end(); ++mit)
+  int numMatchesProcessed = 0;
+  for (std::vector<ConstMatchPtr>::iterator mit = _matches.begin(); mit != _matches.end(); ++mit)
   {
-    const Match* match = *mit;
+    ConstMatchPtr match = *mit;
     LOG_VART(match);
     std::set<std::pair<ElementId, ElementId>> pairs = match->getMatchPairs();
 
@@ -387,13 +399,16 @@ void DiffConflator::_calcAndStoreTagChanges()
       }
 
       LOG_VART(pOldElement->getElementId());
+      //LOG_VART(pOldElement->getTags().get("name"));
       LOG_VART(pNewElement->getElementId());
+      //LOG_VART(pNewElement->getTags().get("name"));
 
-      // Apparently a NetworkMatch can be a node/way pair. See note in
+      // Apparently, a NetworkMatch can be a node/way pair. See note in
       // NetworkMatch::_discoverWayPairs as to why its allowed. However, tag changes between
       // node/way match pairs other than poi/poly don't seem to make any sense. Clearly, if we add
-      // other conflation type other than poi/poly which matches differing geometry types then this
-      // will need to be updated.
+      // a conflation type other than poi/poly which matches differing geometry types then this will
+      // need to be updated.
+
       if (match->getMatchName() != PoiPolygonMatch().getMatchName() &&
           pOldElement->getElementType() != pNewElement->getElementType())
       {
@@ -413,6 +428,14 @@ void DiffConflator::_calcAndStoreTagChanges()
         _pTagChanges->addChange(newChange);
       }
     }
+
+    numMatchesProcessed++;
+    if (numMatchesProcessed % (_taskStatusUpdateInterval * 10) == 0)
+    {
+      PROGRESS_INFO(
+        "\tStored " << StringUtils::formatLargeNumber(numMatchesProcessed) << " / " <<
+            StringUtils::formatLargeNumber(_matches.size()) << " match tag changes.");
+    }
   }
 
   OsmMapWriterFactory::writeDebugMap(_pMap, "after-storing-tag-changes");
@@ -457,12 +480,12 @@ Change DiffConflator::_getChange(ConstElementPtr pOldElement, ConstElementPtr pN
 
 void DiffConflator::_reset()
 {
-  _deleteAll(_matches);
+  _matches.clear();
   _pMap.reset();
   _pTagChanges.reset();
 }
 
-void DiffConflator::_printMatches(vector<const Match*> matches)
+void DiffConflator::_printMatches(vector<ConstMatchPtr> matches)
 {
   for (size_t i = 0; i < matches.size(); i++)
   {
@@ -470,11 +493,11 @@ void DiffConflator::_printMatches(vector<const Match*> matches)
   }
 }
 
-void DiffConflator::_printMatches(vector<const Match*> matches, const MatchType& typeFilter)
+void DiffConflator::_printMatches(std::vector<ConstMatchPtr> matches, const MatchType& typeFilter)
 {
   for (size_t i = 0; i < matches.size(); i++)
   {
-    const Match* match = matches[i];
+    ConstMatchPtr match = matches[i];
     if (match->getType() == typeFilter)
     {
       LOG_DEBUG(match);
Clone this wiki locally