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;
}