v0.2.53..v0.2.54 changeset RemoveEmptyAreasVisitor.cpp
Garret Voltz edited this page Mar 31, 2020
·
1 revision
diff --git a/hoot-core/src/main/cpp/hoot/core/visitors/RemoveEmptyAreasVisitor.cpp b/hoot-core/src/main/cpp/hoot/core/visitors/RemoveEmptyAreasVisitor.cpp
index 9ca0347..1e68e1b 100644
--- a/hoot-core/src/main/cpp/hoot/core/visitors/RemoveEmptyAreasVisitor.cpp
+++ b/hoot-core/src/main/cpp/hoot/core/visitors/RemoveEmptyAreasVisitor.cpp
@@ -34,7 +34,9 @@
#include <hoot/core/elements/ElementConverter.h>
#include <hoot/core/util/Factory.h>
#include <hoot/core/criterion/AreaCriterion.h>
+#include <hoot/core/criterion/BuildingCriterion.h>
#include <hoot/core/util/StringUtils.h>
+#include <hoot/core/util/GeometryUtils.h>
using namespace geos::geom;
namespace hoot
@@ -42,13 +44,20 @@ namespace hoot
HOOT_FACTORY_REGISTER(ElementVisitor, RemoveEmptyAreasVisitor)
-RemoveEmptyAreasVisitor::RemoveEmptyAreasVisitor()
+RemoveEmptyAreasVisitor::RemoveEmptyAreasVisitor() :
+_requireAreaForPolygonConversion(true)
{
}
+void RemoveEmptyAreasVisitor::setConfiguration(const Settings& conf)
+{
+ _requireAreaForPolygonConversion = ConfigOptions(conf).getConvertRequireAreaForPolygon();
+ LOG_VARD(_requireAreaForPolygonConversion);
+}
+
void RemoveEmptyAreasVisitor::visit(const ConstElementPtr& e)
{
- // no need to visit nodes.
+ // no need to visit nodes
if (e->getElementType() != ElementType::Node)
{
std::shared_ptr<Element> ee = _map->getElement(e->getElementId());
@@ -61,8 +70,15 @@ void RemoveEmptyAreasVisitor::visit(const std::shared_ptr<Element>& e)
if (!_ec.get())
{
_ec.reset(new ElementConverter(_map->shared_from_this()));
+ LOG_VARD(_requireAreaForPolygonConversion);
+ // TODO: This is directly related to the relation change commented out below. If this logic
+ // isn't needed, then we can remove implementation of the Configurable interface.
+ _ec->setRequireAreaForPolygonConversion(_requireAreaForPolygonConversion);
}
+ LOG_VART(e->getElementId());
+ //LOG_VART(e);
+
LOG_VART(AreaCriterion().isSatisfied(e));
if (AreaCriterion().isSatisfied(e))
{
@@ -70,10 +86,50 @@ void RemoveEmptyAreasVisitor::visit(const std::shared_ptr<Element>& e)
LOG_VART(g.get());
if (g.get())
{
+ LOG_VART(GeometryUtils::geometryTypeIdToString(g->getGeometryTypeId()));
LOG_VART(g->getArea());
}
+ bool removeArea = false;
if (g.get() && g->getArea() == 0.0)
{
+ if (e->getElementType() == ElementType::Relation)
+ {
+ // require that all way children of this relation have empty areas in order to remove it
+ ConstRelationPtr relation = std::dynamic_pointer_cast<const Relation>(e);
+ const std::vector<RelationData::Entry>& members = relation->getMembers();
+ bool anyMemberHasPositiveArea = false;
+ for (size_t i = 0; i < members.size(); i++)
+ {
+ const RelationData::Entry& member = members[i];
+ // not going down more than one relation level here, but that may eventually need to be
+ // done; Also, should we also require that each child way also satisfy AreaCriterion?
+ if (member.getElementId().getType() == ElementType::Way)
+ {
+ ConstWayPtr memberWay =
+ std::dynamic_pointer_cast<const Way>(_map->getElement(member.getElementId()));
+ if (memberWay)
+ {
+ std::shared_ptr<Geometry> wayGeom = _ec->convertToGeometry(memberWay);
+ if (wayGeom && wayGeom->getArea() > 0.0)
+ {
+ LOG_TRACE(memberWay->getElementId() << " has positive area.");
+ anyMemberHasPositiveArea = true;
+ break;
+ }
+ }
+ }
+ }
+ removeArea = !anyMemberHasPositiveArea;
+ }
+ else
+ {
+ removeArea = true;
+ }
+ }
+
+ if (removeArea)
+ {
+ LOG_TRACE("Recursively removing empty area: " << e->getElementId() << "...");
RecursiveElementRemover(e->getElementId()).apply(_map->shared_from_this());
_numAffected++;
}
@@ -88,5 +144,14 @@ void RemoveEmptyAreasVisitor::visit(const std::shared_ptr<Element>& e)
}
}
+QStringList RemoveEmptyAreasVisitor::getCriteria() const
+{
+ QStringList criteria;
+ // need to also add building here for unecessary conflation op removal purposes, since
+ // AreaCriterion includes buildings in some instances
+ criteria.append(QString::fromStdString(BuildingCriterion::className()));
+ criteria.append(QString::fromStdString(AreaCriterion::className()));
+ return criteria;
+}
}