-
Notifications
You must be signed in to change notification settings - Fork 74
v0.2.55..v0.2.56 changeset AlphaShapeGenerator.cpp
Garret Voltz edited this page Aug 14, 2020
·
3 revisions
diff --git a/hoot-core/src/main/cpp/hoot/core/algorithms/alpha-shape/AlphaShapeGenerator.cpp b/hoot-core/src/main/cpp/hoot/core/algorithms/alpha-shape/AlphaShapeGenerator.cpp
index d4d9ea8..f4b0149 100644
--- a/hoot-core/src/main/cpp/hoot/core/algorithms/alpha-shape/AlphaShapeGenerator.cpp
+++ b/hoot-core/src/main/cpp/hoot/core/algorithms/alpha-shape/AlphaShapeGenerator.cpp
@@ -47,6 +47,7 @@ namespace hoot
AlphaShapeGenerator::AlphaShapeGenerator(const double alpha, const double buffer) :
_alpha(alpha),
_buffer(buffer),
+_manuallyCoverSmallPointClusters(true),
_retryOnTooSmallInitialAlpha(true),
_maxTries(1)
{
@@ -65,20 +66,20 @@ OsmMapPtr AlphaShapeGenerator::generateMap(OsmMapPtr inputMap)
OsmMapWriterFactory::writeDebugMap(inputMap, "alpha-shape-input-map");
std::shared_ptr<Geometry> cutterShape = generateGeometry(inputMap);
-
if (cutterShape->getArea() == 0.0)
{
// would rather this be thrown than a warning logged, as the warning may go unoticed by
// clients who are expecting the alpha shape to be generated
throw HootException("Alpha Shape area is zero. Try increasing the buffer size and/or alpha.");
}
+ OsmMapWriterFactory::writeDebugMap(cutterShape, inputMap->getProjection(), "cutter-shape-map");
OsmMapPtr result;
-
result.reset(new OsmMap(inputMap->getProjection()));
result->appendSource(inputMap->getSource());
// add the resulting alpha shape for debugging.
GeometryConverter(result).convertGeometryToElement(cutterShape.get(), Status::Invalid, -1);
+ OsmMapWriterFactory::writeDebugMap(result, "alpha-shape-result-map");
const RelationMap& rm = result->getRelations();
for (RelationMap::const_iterator it = rm.begin(); it != rm.end(); ++it)
@@ -95,8 +96,6 @@ OsmMapPtr AlphaShapeGenerator::generateMap(OsmMapPtr inputMap)
std::shared_ptr<Geometry> AlphaShapeGenerator::generateGeometry(OsmMapPtr inputMap)
{
- LOG_TRACE("Generating alpha shape geometry...");
-
MapProjector::projectToPlanar(inputMap);
LOG_VART(MapProjector::toWkt(inputMap->getProjection()));
@@ -118,8 +117,12 @@ std::shared_ptr<Geometry> AlphaShapeGenerator::generateGeometry(OsmMapPtr inputM
std::shared_ptr<Geometry> cutterShape;
int numTries = 0;
- while (numTries <= _maxTries)
+ while (numTries < _maxTries)
{
+ LOG_DEBUG(
+ "Generating alpha shape geometry with alpha: " << _alpha << "; attempt " << (numTries + 1) <<
+ " / " << _maxTries << "...");
+
AlphaShape alphaShape(_alpha);
alphaShape.insert(points);
try
@@ -150,8 +153,47 @@ std::shared_ptr<Geometry> AlphaShapeGenerator::generateGeometry(OsmMapPtr inputM
cutterShape.reset(GeometryFactory::getDefaultInstance()->createEmptyGeometry());
}
cutterShape.reset(cutterShape->buffer(_buffer));
+ //OsmMapWriterFactory::writeDebugMap(cutterShape, inputMap->getProjection(), "cutter-shape-map");
+
+ // See _coverStragglers description. This is an add-on behavior that is separate from the Alpha
+ // Shape algorithm itself.
+ if (_manuallyCoverSmallPointClusters)
+ {
+ _coverStragglers(cutterShape, inputMap);
+ //OsmMapWriterFactory::writeDebugMap(geometry, spatRef, "alpha-shape-after-covering-stragglers");
+ }
return cutterShape;
}
+void AlphaShapeGenerator::_coverStragglers(std::shared_ptr<Geometry>& geometry,
+ const ConstOsmMapPtr& map)
+{
+ LOG_DEBUG("Covering stragglers...");
+
+ // Pretty simple...go through and find any point that wasn't covered by the Alpha Shape and draw
+ // a buffer around it.
+
+ int addedPointCtr = 0;
+ const NodeMap& nodes = map->getNodes();
+ for (NodeMap::const_iterator it = nodes.begin(); it != nodes.end(); ++it)
+ {
+ NodePtr node = it->second;
+ std::shared_ptr<geos::geom::Geometry> point(
+ GeometryFactory::getDefaultInstance()->createPoint(
+ geos::geom::Coordinate(node->getX(), node->getY())));
+ if (!geometry->contains(point.get()))
+ {
+ LOG_TRACE(
+ "Point " << point->toString() << " not covered by alpha shape. Buffering and adding it...");
+ point.reset(point->buffer(_buffer));
+ geometry.reset(geometry->Union(point.get()));
+ addedPointCtr++;
+ LOG_VART(geometry->getArea());
+ }
+ }
+
+ LOG_DEBUG("Added " << addedPointCtr << " point stragglers to alpha shape.");
+}
+
}