-
Notifications
You must be signed in to change notification settings - Fork 74
v0.2.53..v0.2.54 changeset AlphaShape.cpp
Garret Voltz edited this page Mar 31, 2020
·
1 revision
diff --git a/hoot-core/src/main/cpp/hoot/core/algorithms/alpha-shape/AlphaShape.cpp b/hoot-core/src/main/cpp/hoot/core/algorithms/alpha-shape/AlphaShape.cpp
index f413a74..7103d1e 100644
--- a/hoot-core/src/main/cpp/hoot/core/algorithms/alpha-shape/AlphaShape.cpp
+++ b/hoot-core/src/main/cpp/hoot/core/algorithms/alpha-shape/AlphaShape.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 "AlphaShape.h"
@@ -148,47 +148,19 @@ inline double distance(double x1, double x2, double y1, double y2)
return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
}
-AlphaShape::AlphaShape(double alpha)
+AlphaShape::AlphaShape(double alpha) :
+_alpha(alpha),
+_longestFaceEdge(0.0)
{
- _alpha = alpha;
+ LOG_VARD(_alpha);
_pDelauneyTriangles.reset(new Tgs::DelaunayTriangulation);
}
-WayPtr AlphaShape::_addFaceAsWay(const Face* face, const std::shared_ptr<OsmMap>& map)
-{
- Edge e = face->getEdge(0);
- e.getOriginX();
- NodePtr start(new Node(Status::Unknown1, map->createNextNodeId(), e.getOriginX(), e.getOriginY(),
- -1));
- map->addNode(start);
-// WayPtr way(new Way(Unknown1, map->createNextWayId(), -1));
- WayPtr way;
-// way->addNode(start->getId());
-
- for (int i = 2; i < 6; i+=2)
- {
- e = face->getEdge(i);
- NodePtr n(new Node(Status::Unknown1, map->createNextNodeId(), e.getOriginX(),
- e.getOriginY(), -1));
- map->addNode(n);
-// way->addNode(n->getId());
- }
-// way->addNode(start->getId());
-// map->addWay(way);
-
-// if (_isInside(*face))
-// {
-// way->setTag("area", "yes");
-// }
-
- return way;
-}
-
std::shared_ptr<Polygon> AlphaShape::_convertFaceToPolygon(const Face& face) const
{
std::shared_ptr<Polygon> result;
- CoordinateSequence* cs = GeometryFactory::getDefaultInstance()->getCoordinateSequenceFactory()->
- create(4, 2);
+ CoordinateSequence* cs =
+ GeometryFactory::getDefaultInstance()->getCoordinateSequenceFactory()->create(4, 2);
LinearRing* lr;
Coordinate c;
@@ -209,8 +181,7 @@ std::shared_ptr<Polygon> AlphaShape::_convertFaceToPolygon(const Face& face) con
lr = GeometryFactory::getDefaultInstance()->createLinearRing(cs);
std::vector<Geometry*>* holes = new std::vector<Geometry*>();
- result.reset(GeometryFactory::getDefaultInstance()->createPolygon(lr,
- holes));
+ result.reset(GeometryFactory::getDefaultInstance()->createPolygon(lr, holes));
return result;
}
@@ -252,12 +223,13 @@ bool AlphaShape::_isInside(const Face& face) const
bool result = true;
for (int i = 0; i < 6; i++)
{
- if (_isTooLong(face.getEdge(i)))
+ const bool edgeTooLong = _isTooLong(face.getEdge(i));
+ LOG_VART(edgeTooLong);
+ if (edgeTooLong)
{
result = false;
}
}
-
return result;
}
@@ -278,13 +250,19 @@ bool AlphaShape::_isOutsideEdge(const Tgs::Edge& e) const
bool AlphaShape::_isTooLong(const Edge& e) const
{
- return distance(e.getOriginX(), e.getDestinationX(), e.getOriginY(), e.getDestinationY()) >
- _alpha;
+ const double edgeDistance =
+ distance(e.getOriginX(), e.getDestinationX(), e.getOriginY(), e.getDestinationY());
+ LOG_VART(edgeDistance);
+ if (edgeDistance > _longestFaceEdge)
+ {
+ _longestFaceEdge = edgeDistance;
+ }
+ return edgeDistance > _alpha;
}
void AlphaShape::insert(const vector<pair<double, double>>& points)
{
- LOG_DEBUG("Inserting points.");
+ LOG_DEBUG("Inserting points...");
double minX = numeric_limits<double>::max();
double maxX = -minX;
@@ -333,6 +311,7 @@ void AlphaShape::insert(const vector<pair<double, double>>& points)
_pDelauneyTriangles->insert(randomized[i].first, randomized[i].second);
}
LOG_TRACE("Progress: " << randomized.size() - 1 << " of " << randomized.size() - 1 << " ");
+ LOG_VARD(_pDelauneyTriangles->getFaces().size());
}
std::shared_ptr<OsmMap> AlphaShape::toOsmMap()
@@ -353,33 +332,53 @@ std::shared_ptr<OsmMap> AlphaShape::toOsmMap()
std::shared_ptr<Geometry> AlphaShape::toGeometry()
{
- LOG_DEBUG("Traversing faces");
+ LOG_DEBUG("Traversing faces...");
+
// create a vector of all faces
vector<std::shared_ptr<Geometry>> tmp, tmp2;
Envelope e;
double preUnionArea = 0.0;
int i = 0;
- for (FaceIterator fi = _pDelauneyTriangles->getFaceIterator(); fi != _pDelauneyTriangles->getFaceEnd(); fi++)
+ int numPolys = 0;
+ for (FaceIterator fi = _pDelauneyTriangles->getFaceIterator();
+ fi != _pDelauneyTriangles->getFaceEnd(); fi++)
{
const Face& f = *fi;
i++;
if (_isInside(f))
{
std::shared_ptr<Polygon> p = _convertFaceToPolygon(f);
+ LOG_VART(p->getArea());
tmp.push_back(p);
e.expandToInclude(p->getEnvelopeInternal());
preUnionArea += p->getArea();
+ numPolys++;
}
}
+ LOG_VARD(numPolys);
+ LOG_VARD(e);
LOG_DEBUG("Area: " << (long)preUnionArea);
+ LOG_VARD(tmp.size());
// if the result is an empty geometry.
if (tmp.size() == 0)
{
- return std::shared_ptr<Geometry>(GeometryFactory::getDefaultInstance()->createEmptyGeometry());
+ if (_longestFaceEdge > _alpha)
+ {
+ throw IllegalArgumentException(
+ "Longest face edge of size: " + QString::number(_longestFaceEdge) +
+ " larger than alpha value of: " + QString::number(_alpha) + ". Try an alpha value of " +
+ QString::number(_longestFaceEdge) + " or larger.");
+ }
+ else
+ {
+ // don't know how to handle it
+ return std::shared_ptr<Geometry>(GeometryFactory::getDefaultInstance()->createEmptyGeometry());
+ }
}
- LOG_DEBUG("Joining faces");
+ LOG_DEBUG("Joining faces...");
+
// while there is more than one geometry.
while (tmp.size() > 1)
{
@@ -446,7 +445,8 @@ std::shared_ptr<Geometry> AlphaShape::toGeometry()
std::shared_ptr<Geometry> result;
- LOG_DEBUG("Converting geometry to map.");
+ LOG_DEBUG("Converting geometry to map...");
+
if (tmp.size() == 1)
{
result = tmp[0];
@@ -464,7 +464,8 @@ std::shared_ptr<Geometry> AlphaShape::toGeometry()
{
if (logWarnCount < Log::getWarnMessageLimit())
{
- LOG_WARN("Area after union is inconsistent. GEOS error? pre union: " << (long)preUnionArea <<
+ LOG_WARN(
+ "Area after union is inconsistent. GEOS error? pre union: " << (long)preUnionArea <<
" post union: " << result->getArea());
}
else if (logWarnCount == Log::getWarnMessageLimit())