Skip to content

v0.2.54..v0.2.55 changeset PoiPolygonMerger.cpp

Garret Voltz edited this page Aug 14, 2020 · 1 revision
diff --git a/hoot-core/src/main/cpp/hoot/core/conflate/poi-polygon/PoiPolygonMerger.cpp b/hoot-core/src/main/cpp/hoot/core/conflate/poi-polygon/PoiPolygonMerger.cpp
index 92581a9..2d4b8de 100644
--- a/hoot-core/src/main/cpp/hoot/core/conflate/poi-polygon/PoiPolygonMerger.cpp
+++ b/hoot-core/src/main/cpp/hoot/core/conflate/poi-polygon/PoiPolygonMerger.cpp
@@ -42,6 +42,7 @@
 #include <hoot/core/util/ConfigOptions.h>
 #include <hoot/core/util/Factory.h>
 #include <hoot/core/conflate/poi-polygon/PoiPolygonMatch.h>
+#include <hoot/core/io/OsmMapWriterFactory.h>
 
 using namespace std;
 
@@ -67,40 +68,54 @@ _tagMergerClass("")
   assert(_pairs.size() >= 1);
 }
 
-std::shared_ptr<const TagMerger> PoiPolygonMerger::_getTagMerger()
+std::shared_ptr<TagMerger> PoiPolygonMerger::_getTagMerger()
 {
-  std::shared_ptr<const TagMerger> tagMerger;
-
-  std::string tagMergerClass;
-  // Always preserve types when merging many POIs in. This can go away if we stay with defaulting
-  // poi/poly merging to use PreserveTypesTagMerger.
-  if (_autoMergeManyPoiToOnePolyMatches)
-  {
-    tagMergerClass = PreserveTypesTagMerger::className();
-  }
-  // Otherwise, allow for calling class to specify the tag merger outside of Configurable.
-  else if (!_tagMergerClass.trimmed().isEmpty())
-  {
-    tagMergerClass = _tagMergerClass.toStdString();
-  }
-  // Otherwise, let's see if the tag merger was set specifically for poi/poly.
-  else if (!ConfigOptions().getPoiPolygonTagMerger().trimmed().isEmpty())
-  {
-    tagMergerClass = ConfigOptions().getPoiPolygonTagMerger().trimmed().toStdString();
-  }
-  // Otherwise, let's try the global tag merger.
-  else if (!ConfigOptions().getTagMergerDefault().trimmed().isEmpty())
-  {
-    tagMergerClass = ConfigOptions().getTagMergerDefault().trimmed().toStdString();
-  }
-  else
+  if (!_tagMerger)
   {
-    throw IllegalArgumentException("No tag merger specified for POI/Polygon conflation.");
-  }
-  LOG_VART(tagMergerClass);
+    LOG_VART(ConfigOptions().getHighwayMergeTagsOnly());
+    LOG_VART(_autoMergeManyPoiToOnePolyMatches);
+    LOG_VART(_tagMergerClass);
+    LOG_VART(ConfigOptions().getPoiPolygonTagMerger());
+    LOG_VART(ConfigOptions().getTagMergerDefault());
+
+    std::string tagMergerClass;
+    // We force this setting always preserve types when merging many POIs in. It works with
+    // Attribute Conflation as well, via tag.merger.overwrite.exclude.
+    if (_autoMergeManyPoiToOnePolyMatches)
+    {
+      tagMergerClass = PreserveTypesTagMerger::className();
+    }
+    // Otherwise, allow for calling class to specify the tag merger outside of Configurable.
+    else if (!_tagMergerClass.trimmed().isEmpty())
+    {
+      tagMergerClass = _tagMergerClass.toStdString();
+    }
+    // Otherwise, let's see if the tag merger was set specifically for poi/poly.
+    else if (!ConfigOptions().getPoiPolygonTagMerger().trimmed().isEmpty())
+    {
+      tagMergerClass = ConfigOptions().getPoiPolygonTagMerger().trimmed().toStdString();
+    }
+    // Otherwise, let's try the default configured tag merger.
+    else if (!ConfigOptions().getTagMergerDefault().trimmed().isEmpty())
+    {
+      tagMergerClass = ConfigOptions().getTagMergerDefault().trimmed().toStdString();
+    }
+    else
+    {
+      throw IllegalArgumentException("No tag merger specified for POI/Polygon conflation.");
+    }
+    LOG_VART(tagMergerClass);
 
-  tagMerger.reset(Factory::getInstance().constructObject<TagMerger>(tagMergerClass));
-  return tagMerger;
+    _tagMerger.reset(Factory::getInstance().constructObject<TagMerger>(tagMergerClass));
+
+    std::shared_ptr<Configurable> critConfig = std::dynamic_pointer_cast<Configurable>(_tagMerger);
+    if (critConfig.get())
+    {
+      critConfig->setConfiguration(conf());
+    }
+  }
+  LOG_VART(_tagMerger->getClassName());
+  return _tagMerger;
 }
 
 void PoiPolygonMerger::apply(const OsmMapPtr& map, vector<pair<ElementId, ElementId>>& replaced)
@@ -112,7 +127,10 @@ void PoiPolygonMerger::apply(const OsmMapPtr& map, vector<pair<ElementId, Elemen
   // merge all POI tags first, but keep Unknown1 and Unknown2 separate. It is implicitly assumed
   // that since they're in a single group they all represent the same entity.
   Tags poiTags1 = _mergePoiTags(map, Status::Unknown1);
+  // This debug map writing is very expensive, so just turn it on when debugging small datasets.
+  //OsmMapWriterFactory::writeDebugMap(map, "PoiPolygonMerger-after-poi-tags-merge-1");
   Tags poiTags2 = _mergePoiTags(map, Status::Unknown2);
+  //OsmMapWriterFactory::writeDebugMap(map, "PoiPolygonMerger-after-poi-tags-merge-2");
 
   // Get all the building parts for each status
   vector<ElementId> buildings1 = _getBuildingParts(map, Status::Unknown1);
@@ -122,6 +140,7 @@ void PoiPolygonMerger::apply(const OsmMapPtr& map, vector<pair<ElementId, Elemen
   // merge process.
   ElementId finalBuildingEid = _mergeBuildings(map, buildings1, buildings2, replaced);
   LOG_VART(finalBuildingEid);
+  //OsmMapWriterFactory::writeDebugMap(map, "PoiPolygonMerger-after-building-merge");
 
   ElementPtr finalBuilding = map->getElement(finalBuildingEid);
   if (!finalBuilding.get())
@@ -145,22 +164,30 @@ void PoiPolygonMerger::apply(const OsmMapPtr& map, vector<pair<ElementId, Elemen
   }
   assert(finalBuilding.get());
 
-  // select a tag merging strategy
-  std::shared_ptr<const TagMerger> tagMerger = _getTagMerger();
-
   // merge the tags
+
+  // We're always keeping the building geometry, but the tags kept depends on the source status
+  // of the features or the conflation workflow chosen.
   Tags finalBuildingTags = finalBuilding->getTags();
-  if (poiTags1.size())
+  LOG_VART(finalBuildingTags);
+ // Tags poiBuildingMergedTags;
+  if (poiTags1.size() > 0)
   {
+    // If this is a ref POI, we'll keep its tags and replace the building tags.
     LOG_TRACE("Merging POI tags with building tags for POI status Unknown1...");
     finalBuildingTags =
-      tagMerger->mergeTags(poiTags1, finalBuildingTags, finalBuilding->getElementType());
+      _getTagMerger()->mergeTags(poiTags1, finalBuildingTags, finalBuilding->getElementType());
+    LOG_VART(finalBuildingTags);
+    //OsmMapWriterFactory::writeDebugMap(map, "PoiPolygonMerger-after-building-tags-merge-1");
   }
-  if (poiTags2.size())
+  if (poiTags2.size() > 0)
   {
     LOG_TRACE("Merging POI tags with building tags for POI status Unknown2...");
+    // If this is a sec POI, we'll keep the buildings tags and replace its tags.
     finalBuildingTags =
-      tagMerger->mergeTags(finalBuildingTags, poiTags2, finalBuilding->getElementType());
+      _getTagMerger()->mergeTags(finalBuildingTags, poiTags2, finalBuilding->getElementType());
+    LOG_VART(finalBuildingTags);
+    //OsmMapWriterFactory::writeDebugMap(map, "PoiPolygonMerger-after-building-tags-merge-2");
   }
 
   // do some book keeping to remove the POIs and mark them as replaced.
@@ -194,6 +221,7 @@ void PoiPolygonMerger::apply(const OsmMapPtr& map, vector<pair<ElementId, Elemen
     }
   }
   LOG_VART(poisMerged);
+  OsmMapWriterFactory::writeDebugMap(map, "PoiPolygonMerger-after-poi-removal");
 
   if (poisMerged > 0)
   {
@@ -217,23 +245,13 @@ void PoiPolygonMerger::apply(const OsmMapPtr& map, vector<pair<ElementId, Elemen
   LOG_VART(finalBuilding);
 }
 
-Tags PoiPolygonMerger::_mergePoiTags(const OsmMapPtr& map, Status s) const
+Tags PoiPolygonMerger::_mergePoiTags(const OsmMapPtr& map, Status s)
 {
   LOG_TRACE("Merging POI tags for status: " << s << "...");
 
   Tags result;
 
   LOG_VART(_autoMergeManyPoiToOnePolyMatches);
-  std::shared_ptr<const TagMerger> tagMerger;
-  if (_autoMergeManyPoiToOnePolyMatches)
-  {
-    tagMerger.reset(new PreserveTypesTagMerger());
-  }
-  else
-  {
-    tagMerger = TagMergerFactory::getInstance().getDefaultPtr();
-  }
-
   for (set<pair<ElementId, ElementId>>::const_iterator it = _pairs.begin(); it != _pairs.end();
        ++it)
   {
@@ -245,13 +263,13 @@ Tags PoiPolygonMerger::_mergePoiTags(const OsmMapPtr& map, Status s) const
     {
       LOG_VART(e1->getElementId());
       //LOG_VART(e1);
-      result = tagMerger->mergeTags(result, e1->getTags(), e1->getElementType());
+      result = _getTagMerger()->mergeTags(result, e1->getTags(), e1->getElementType());
     }
     if (e2->getStatus() == s && e2->getElementType() == ElementType::Node)
     {
       LOG_VART(e2->getElementId());
       //LOG_VART(e2);
-      result = tagMerger->mergeTags(result, e2->getTags(), e2->getElementType());
+      result = _getTagMerger()->mergeTags(result, e2->getTags(), e2->getElementType());
     }
   }
 
@@ -286,7 +304,7 @@ vector<ElementId> PoiPolygonMerger::_getBuildingParts(const OsmMapPtr& map, Stat
 
 ElementId PoiPolygonMerger::_mergeBuildings(const OsmMapPtr& map,
   vector<ElementId>& buildings1, vector<ElementId>& buildings2,
-  vector<pair<ElementId, ElementId>>& replaced) const
+  vector<pair<ElementId, ElementId>>& replaced)
 {
   LOG_TRACE("Merging buildings...");
 
@@ -297,8 +315,8 @@ ElementId PoiPolygonMerger::_mergeBuildings(const OsmMapPtr& map,
   set<pair<ElementId, ElementId>> pairs;
 
   assert(buildings1.size() != 0 || buildings2.size() != 0);
-  // if there is only one set of buildings then there is no need to merge.  group all the building
-  //parts into a single building
+  // If there is only one set of buildings, then there is no need to merge. Group all the building
+  // parts into a single building.
   if (buildings1.size() == 0)
   {
     set<ElementId> eids;
Clone this wiki locally