Skip to content

v0.2.54..v0.2.55 changeset AlphaShapeGenerator.cpp

Garret Voltz edited this page Aug 14, 2020 · 1 revision
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 886a428..d4d9ea8 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
@@ -33,6 +33,7 @@
 #include <hoot/core/util/GeometryConverter.h>
 #include <hoot/core/util/Log.h>
 #include <hoot/core/io/OsmMapWriterFactory.h>
+#include <hoot/core/util/StringUtils.h>
 
 // GEOS
 #include <geos/geom/GeometryFactory.h>
@@ -46,10 +47,17 @@ namespace hoot
 AlphaShapeGenerator::AlphaShapeGenerator(const double alpha, const double buffer) :
 _alpha(alpha),
 _buffer(buffer),
-_retryOnTooSmallInitialAlpha(true)
+_retryOnTooSmallInitialAlpha(true),
+_maxTries(1)
 {
-  LOG_VARD(_alpha);
-  LOG_VARD(_buffer);
+  LOG_VART(_alpha);
+  LOG_VART(_buffer);
+  if (_retryOnTooSmallInitialAlpha)
+  {
+    // have not seen an instance yet where more than two tries are needed to complete successfully;
+    // in all other cases, no solution could be found no matter how many tries were attempted
+    _maxTries = 2;
+  }
 }
 
 OsmMapPtr AlphaShapeGenerator::generateMap(OsmMapPtr inputMap)
@@ -60,7 +68,7 @@ OsmMapPtr AlphaShapeGenerator::generateMap(OsmMapPtr inputMap)
 
   if (cutterShape->getArea() == 0.0)
   {
-    // would rather this be thrown than a warning logged, as the warning may go unoticed by web
+    // 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.");
   }
@@ -79,7 +87,7 @@ OsmMapPtr AlphaShapeGenerator::generateMap(OsmMapPtr inputMap)
     r->setTag("area", "yes");
   }
 
-  LOG_VARD(MapProjector::toWkt(result->getProjection()));
+  LOG_VART(MapProjector::toWkt(result->getProjection()));
   OsmMapWriterFactory::writeDebugMap(result, "alpha-shape-result-map");
 
   return result;
@@ -87,12 +95,12 @@ OsmMapPtr AlphaShapeGenerator::generateMap(OsmMapPtr inputMap)
 
 std::shared_ptr<Geometry> AlphaShapeGenerator::generateGeometry(OsmMapPtr inputMap)
 {
-  LOG_INFO("Generating alpha shape geometry...");
+  LOG_TRACE("Generating alpha shape geometry...");
 
   MapProjector::projectToPlanar(inputMap);
-  LOG_VARD(MapProjector::toWkt(inputMap->getProjection()));
+  LOG_VART(MapProjector::toWkt(inputMap->getProjection()));
 
-  // put all the nodes into a vector of points.
+  // put all the nodes into a vector of points
   std::vector<std::pair<double, double>> points;
   points.reserve(inputMap->getNodes().size());
   const NodeMap& nodes = inputMap->getNodes();
@@ -103,34 +111,43 @@ std::shared_ptr<Geometry> AlphaShapeGenerator::generateGeometry(OsmMapPtr inputM
     p.second = (it->second)->getY();
     points.push_back(p);
   }
-  LOG_VARD(points.size());
+  LOG_VART(points.size());
 
   // create a complex geometry representing the alpha shape
+
   std::shared_ptr<Geometry> cutterShape;
-  AlphaShape alphaShape(_alpha);
-  alphaShape.insert(points);
-  try
-  {
-    cutterShape = alphaShape.toGeometry();
-  }
-  catch (const IllegalArgumentException& e)
+
+  int numTries = 0;
+  while (numTries <= _maxTries)
   {
-    if (_retryOnTooSmallInitialAlpha && e.getWhat().startsWith("Longest face edge of size"))
+    AlphaShape alphaShape(_alpha);
+    alphaShape.insert(points);
+    try
     {
-      const double longestFaceEdge = alphaShape.getLongestFaceEdge();
-      LOG_INFO(
-        "Failed to generate alpha shape geometry with alpha value of: " << _alpha <<
-        ". Attempting to generate the shape a second time using the longest face edge size of: " <<
-        longestFaceEdge << " for alpha...");
-      _alpha = longestFaceEdge;
-      AlphaShape alphaShape2(_alpha);
-      alphaShape2.insert(points);
-      cutterShape = alphaShape2.toGeometry();
+      cutterShape = alphaShape.toGeometry();
     }
-    else
+    catch (const IllegalArgumentException& e)
     {
-      cutterShape.reset(GeometryFactory::getDefaultInstance()->createEmptyGeometry());
+      if (_retryOnTooSmallInitialAlpha && e.getWhat().startsWith("Longest face edge of size"))
+      {
+        const double longestFaceEdge = alphaShape.getLongestFaceEdge();
+        LOG_INFO(
+          "Failed to generate alpha shape geometry with alpha value of: " <<
+          StringUtils::formatLargeNumber(_alpha) <<
+          ". Attempting to generate the shape again using the longest face edge size of: " <<
+          StringUtils::formatLargeNumber(longestFaceEdge) << " for alpha...");
+        _alpha = longestFaceEdge;
+      }
+      else
+      {
+        break;
+      }
     }
+    numTries++;
+  }
+  if (!cutterShape)
+  {
+    cutterShape.reset(GeometryFactory::getDefaultInstance()->createEmptyGeometry());
   }
   cutterShape.reset(cutterShape->buffer(_buffer));
 
Clone this wiki locally