Skip to content

v0.2.52..v0.2.53 changeset ElementConverter.cpp

Garret Voltz edited this page Feb 12, 2020 · 1 revision
diff --git a/hoot-core/src/main/cpp/hoot/core/elements/ElementConverter.cpp b/hoot-core/src/main/cpp/hoot/core/elements/ElementConverter.cpp
index 9450c8e..2bfbff6 100644
--- a/hoot-core/src/main/cpp/hoot/core/elements/ElementConverter.cpp
+++ b/hoot-core/src/main/cpp/hoot/core/elements/ElementConverter.cpp
@@ -22,7 +22,7 @@
  * This will properly maintain the copyright information. DigitalGlobe
  * copyrights will be updated automatically.
  *
- * @copyright Copyright (C) 2015, 2016, 2017, 2018, 2019 DigitalGlobe (http://www.digitalglobe.com/)
+ * @copyright Copyright (C) 2015, 2016, 2017, 2018, 2019, 2020 DigitalGlobe (http://www.digitalglobe.com/)
  */
 
 #include "ElementConverter.h"
@@ -52,6 +52,7 @@
 #include <hoot/core/util/MapProjector.h>
 #include <hoot/core/util/NotImplementedException.h>
 #include <hoot/core/visitors/MultiLineStringVisitor.h>
+#include <hoot/core/util/GeometryUtils.h>
 
 // Qt
 #include <QString>
@@ -69,8 +70,9 @@ namespace hoot
 int ElementConverter::logWarnCount = 0;
 
 ElementConverter::ElementConverter(const ConstElementProviderPtr& provider) :
-  _constProvider(provider),
-  _spatialReference(provider->getProjection())
+_constProvider(provider),
+_spatialReference(provider->getProjection()),
+_requireAreaForPolygonConversion(true)
 {
 }
 
@@ -132,8 +134,8 @@ std::shared_ptr<Geometry> ElementConverter::convertToGeometry(const ConstWayPtr&
                                                               bool throwError,
                                                               const bool statsFlag) const
 {
-  GeometryTypeId gid = getGeometryType(e, throwError, statsFlag);
-  LOG_VART(gid);
+  GeometryTypeId gid = getGeometryType(e, throwError, statsFlag, _requireAreaForPolygonConversion);
+  LOG_VART(GeometryUtils::geometryTypeIdToString(gid));
   if (gid == GEOS_POLYGON)
   {
     return convertToPolygon(e);
@@ -155,7 +157,8 @@ std::shared_ptr<Geometry> ElementConverter::convertToGeometry(const ConstRelatio
                                                               bool throwError,
                                                               const bool statsFlag) const
 {
-  GeometryTypeId gid = getGeometryType(e, throwError, statsFlag);
+  GeometryTypeId gid = getGeometryType(e, throwError, statsFlag, _requireAreaForPolygonConversion);
+  LOG_VART(GeometryUtils::geometryTypeIdToString(gid));
   if (gid == GEOS_MULTIPOLYGON)
   {
     return MultiPolygonCreator(_constProvider, e).createMultipolygon();
@@ -183,8 +186,6 @@ std::shared_ptr<Geometry> ElementConverter::convertToGeometry(const RelationPtr&
 
 std::shared_ptr<LineString> ElementConverter::convertToLineString(const ConstWayPtr& w) const
 {
-  LOG_TRACE("Converting to line string...");
-
   const std::vector<long>& ids = w->getNodeIds();
   int size = ids.size();
   if (size == 1)
@@ -239,8 +240,6 @@ std::shared_ptr<LineString> ElementConverter::convertToLineString(const ConstWay
 
 std::shared_ptr<Polygon> ElementConverter::convertToPolygon(const ConstWayPtr& w) const
 {
-  LOG_TRACE("Converting to polygon...");
-
   const std::vector<long>& ids = w->getNodeIds();
   LOG_VART(ids);
   size_t size = ids.size();
@@ -268,7 +267,7 @@ std::shared_ptr<Polygon> ElementConverter::convertToPolygon(const ConstWayPtr& w
   {
     LOG_VART(ids[i]);
     ConstNodePtr n = _constProvider->getNode(ids[i]);
-    LOG_VART(n.get());
+    //LOG_VART(n.get());
     if (!n.get())
     {
       if (logWarnCount < Log::getWarnMessageLimit())
@@ -308,7 +307,8 @@ std::shared_ptr<Polygon> ElementConverter::convertToPolygon(const ConstWayPtr& w
 }
 
 geos::geom::GeometryTypeId ElementConverter::getGeometryType(
-  const ConstElementPtr& e, bool throwError, const bool statsFlag)
+  const ConstElementPtr& e, bool throwError, const bool statsFlag,
+  const bool requireAreaForPolygonConversion)
 {
   // This is used to pass the relation type back to the exception handler
   QString relationType = "";
@@ -325,25 +325,34 @@ geos::geom::GeometryTypeId ElementConverter::getGeometryType(
       ConstWayPtr w = std::dynamic_pointer_cast<const Way>(e);
       assert(w);
 
+      LOG_VART(statsFlag);
+      LOG_VART(w->isValidPolygon());
+      LOG_VART(w->isClosedArea());
+      LOG_VART(AreaCriterion().isSatisfied(w));
+      LOG_VART(OsmSchema::getInstance().allowsFor(e, OsmGeometries::Area));
+
+      ElementCriterionPtr areaCrit;
       if (statsFlag)
       {
-        if (w->isValidPolygon() && StatsAreaCriterion().isSatisfied(w))
-          return GEOS_POLYGON;
-        else if (w->isClosedArea() && OsmSchema::getInstance().allowsFor(e, OsmGeometries::Area))
-          return GEOS_POLYGON;
-        else
-          return GEOS_LINESTRING;
+        areaCrit.reset(new StatsAreaCriterion());
       }
       else
       {
-        if (w->isValidPolygon() && AreaCriterion().isSatisfied(w))
-          return GEOS_POLYGON;
-        else if (w->isClosedArea() && OsmSchema::getInstance().allowsFor(e, OsmGeometries::Area))
-          return GEOS_POLYGON;
-        else
-          return GEOS_LINESTRING;
+        areaCrit.reset(new AreaCriterion());
       }
 
+      // Hootenanny by default requires that an polygon element be an area in the schema in order
+      // to be converted to a polygon, it is created as a linestring. There are situations, however,
+      // where we want to relax this requirement (generic geometry matching).
+      if (!requireAreaForPolygonConversion && w->isValidPolygon() && w->isClosedArea())
+        return GEOS_POLYGON;
+      else if (w->isValidPolygon() && areaCrit->isSatisfied(w))
+        return GEOS_POLYGON;
+      else if (w->isClosedArea() && OsmSchema::getInstance().allowsFor(e, OsmGeometries::Area))
+        return GEOS_POLYGON;
+      else
+        return GEOS_LINESTRING;
+
       break;
     }
 
Clone this wiki locally