Skip to content

Commit

Permalink
DistanceOp: Avoid heap allocation of GeometryLocations
Browse files Browse the repository at this point in the history
  • Loading branch information
dbaston committed Apr 16, 2024
1 parent 629c2f6 commit 60e0ae2
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 48 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ namespace distance { // geos::operation::distance
class GEOS_DLL ConnectedElementLocationFilter: public geom::GeometryFilter {
private:

std::vector<std::unique_ptr<GeometryLocation>> locations;
std::vector<GeometryLocation> locations;
ConnectedElementLocationFilter() = default;
ConnectedElementLocationFilter(const ConnectedElementLocationFilter&) = delete;
ConnectedElementLocationFilter& operator=(const ConnectedElementLocationFilter&) = delete;
Expand All @@ -63,7 +63,7 @@ class GEOS_DLL ConnectedElementLocationFilter: public geom::GeometryFilter {
* an empty list will be returned. The elements of the list
* are [GeometryLocations](@ref operation::distance::GeometryLocation).
*/
static std::vector<std::unique_ptr<GeometryLocation>> getLocations(const geom::Geometry* geom);
static std::vector<GeometryLocation> getLocations(const geom::Geometry* geom);

void filter_ro(const geom::Geometry* geom) override;
void filter_rw(geom::Geometry* geom) override;
Expand Down
18 changes: 9 additions & 9 deletions include/geos/operation/distance/DistanceOp.h
Original file line number Diff line number Diff line change
Expand Up @@ -172,19 +172,19 @@ class GEOS_DLL DistanceOp {

// working
algorithm::PointLocator ptLocator;
std::array<std::unique_ptr<GeometryLocation>, 2> minDistanceLocation;
std::array<GeometryLocation, 2> minDistanceLocation;
double minDistance;
bool computed = false;

void updateMinDistance(std::array<std::unique_ptr<GeometryLocation>, 2> & locGeom, bool flip);
void updateMinDistance(std::array<GeometryLocation, 2> & locGeom, bool flip);

void computeMinDistance();

void computeContainmentDistance();

void computeInside(std::vector<std::unique_ptr<GeometryLocation>> & locs,
void computeInside(std::vector<GeometryLocation> & locs,
const std::vector<const geom::Polygon*>& polys,
std::array<std::unique_ptr<GeometryLocation>, 2> & locPtPoly);
std::array<GeometryLocation, 2> & locPtPoly);


/**
Expand All @@ -196,25 +196,25 @@ class GEOS_DLL DistanceOp {
void computeMinDistanceLines(
const std::vector<const geom::LineString*>& lines0,
const std::vector<const geom::LineString*>& lines1,
std::array<std::unique_ptr<GeometryLocation>, 2> & locGeom);
std::array<GeometryLocation, 2> & locGeom);

void computeMinDistancePoints(
const std::vector<const geom::Point*>& points0,
const std::vector<const geom::Point*>& points1,
std::array<std::unique_ptr<GeometryLocation>, 2> & locGeom);
std::array<GeometryLocation, 2> & locGeom);

void computeMinDistanceLinesPoints(
const std::vector<const geom::LineString*>& lines0,
const std::vector<const geom::Point*>& points1,
std::array<std::unique_ptr<GeometryLocation>, 2> & locGeom);
std::array<GeometryLocation, 2> & locGeom);

void computeMinDistance(const geom::LineString* line0,
const geom::LineString* line1,
std::array<std::unique_ptr<GeometryLocation>, 2> & locGeom);
std::array<GeometryLocation, 2> & locGeom);

void computeMinDistance(const geom::LineString* line,
const geom::Point* pt,
std::array<std::unique_ptr<GeometryLocation>, 2> & locGeom);
std::array<GeometryLocation, 2> & locGeom);
};


Expand Down
7 changes: 7 additions & 0 deletions include/geos/operation/distance/GeometryLocation.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,13 @@ class GEOS_DLL GeometryLocation {
*/
static const int INSIDE_AREA = -1;

GeometryLocation() :
component(nullptr),
segIndex(0),
inside_area(false),
pt()
{}

/** \brief
* Constructs a GeometryLocation specifying a point on a geometry,
* as well as the segment that the point is on (or INSIDE_AREA if
Expand Down
6 changes: 3 additions & 3 deletions src/operation/distance/ConnectedElementLocationFilter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ namespace operation { // geos.operation
namespace distance { // geos.operation.distance

/*public*/
std::vector<std::unique_ptr<GeometryLocation>>
std::vector<GeometryLocation>
ConnectedElementLocationFilter::getLocations(const Geometry* geom)
{
ConnectedElementLocationFilter c;
Expand All @@ -51,7 +51,7 @@ ConnectedElementLocationFilter::filter_ro(const Geometry* geom)
(typeid(*geom) == typeid(LineString)) ||
(typeid(*geom) == typeid(LinearRing)) ||
(typeid(*geom) == typeid(Polygon))) {
locations.emplace_back(new GeometryLocation(geom, 0, *(geom->getCoordinate())));
locations.emplace_back(geom, 0, *(geom->getCoordinate()));
}
}

Expand All @@ -64,7 +64,7 @@ ConnectedElementLocationFilter::filter_rw(Geometry* geom)
(typeid(*geom) == typeid(LineString)) ||
(typeid(*geom) == typeid(LinearRing)) ||
(typeid(*geom) == typeid(Polygon))) {
locations.emplace_back(new GeometryLocation(geom, 0, *(geom->getCoordinate())));
locations.emplace_back(geom, 0, *(geom->getCoordinate()));
}
}

Expand Down
68 changes: 34 additions & 34 deletions src/operation/distance/DistanceOp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,26 +128,26 @@ DistanceOp::nearestPoints()
auto& locs = minDistanceLocation;

// Empty input geometries result in this behaviour
if(locs[0] == nullptr || locs[1] == nullptr) {
if(locs[0].getGeometryComponent() == nullptr || locs[1].getGeometryComponent() == nullptr) {
// either both or none are set..
assert(locs[0] == nullptr && locs[1] == nullptr);
assert(locs[0].getGeometryComponent() == nullptr && locs[1].getGeometryComponent() == nullptr);

return nullptr;
}

auto nearestPts = detail::make_unique<CoordinateSequence>(2u);
nearestPts->setAt(locs[0]->getCoordinate(), 0);
nearestPts->setAt(locs[1]->getCoordinate(), 1);
nearestPts->setAt(locs[0].getCoordinate(), 0);
nearestPts->setAt(locs[1].getCoordinate(), 1);

return nearestPts;
}

void
DistanceOp::updateMinDistance(std::array<std::unique_ptr<GeometryLocation>, 2> & locGeom, bool flip)
DistanceOp::updateMinDistance(std::array<GeometryLocation, 2> & locGeom, bool flip)
{
// if not set then don't update
if(locGeom[0] == nullptr) {
assert(locGeom[1] == nullptr);
if(locGeom[0].getGeometryComponent() == nullptr) {
assert(locGeom[1].getGeometryComponent() == nullptr);
#if GEOS_DEBUG
std::cerr << "updateMinDistance called with loc[0] == null and loc[1] == null" << std::endl;
#endif
Expand Down Expand Up @@ -210,15 +210,15 @@ DistanceOp::computeContainmentDistance()
// Expected to fill minDistanceLocation items
// if minDistance <= terminateDistance

std::array<std::unique_ptr<GeometryLocation>, 2> locPtPoly;
std::array<GeometryLocation, 2> locPtPoly;
// test if either geometry has a vertex inside the other
if(! polys1.empty()) {
auto insideLocs0 = ConnectedElementLocationFilter::getLocations(geom[0]);
computeInside(insideLocs0, polys1, locPtPoly);

if(minDistance <= terminateDistance) {
assert(locPtPoly[0]);
assert(locPtPoly[1]);
assert(locPtPoly[0].getGeometryComponent());
assert(locPtPoly[1].getGeometryComponent());

minDistanceLocation[0] = std::move(locPtPoly[0]);
minDistanceLocation[1] = std::move(locPtPoly[1]);
Expand All @@ -240,8 +240,8 @@ DistanceOp::computeContainmentDistance()
computeInside(insideLocs1, polys0, locPtPoly);
if(minDistance <= terminateDistance) {
// flip locations, since we are testing geom 1 VS geom 0
assert(locPtPoly[0]);
assert(locPtPoly[1]);
assert(locPtPoly[0].getGeometryComponent());
assert(locPtPoly[1].getGeometryComponent());

minDistanceLocation[0] = std::move(locPtPoly[1]);
minDistanceLocation[1] = std::move(locPtPoly[0]);
Expand All @@ -254,18 +254,18 @@ DistanceOp::computeContainmentDistance()

/*private*/
void
DistanceOp::computeInside(std::vector<std::unique_ptr<GeometryLocation>> & locs,
DistanceOp::computeInside(std::vector<GeometryLocation> & locs,
const Polygon::ConstVect& polys,
std::array<std::unique_ptr<GeometryLocation>, 2> & locPtPoly)
std::array<GeometryLocation, 2> & locPtPoly)
{
for(auto& loc : locs) {
for(const auto& poly : polys) {
const auto& pt = loc->getCoordinate();
const auto& pt = loc.getCoordinate();

if (Location::EXTERIOR != ptLocator.locate(pt, static_cast<const Geometry*>(poly))) {
minDistance = 0.0;
locPtPoly[0] = std::move(loc);
locPtPoly[1].reset(new GeometryLocation(poly, pt));
locPtPoly[1] = GeometryLocation(poly, pt);
return;
}
}
Expand All @@ -279,7 +279,7 @@ DistanceOp::computeFacetDistance()
using geom::util::LinearComponentExtracter;
using geom::util::PointExtracter;

std::array<std::unique_ptr<GeometryLocation>, 2> locGeom;
std::array<GeometryLocation, 2> locGeom;

/*
* Geometries are not wholly inside, so compute distance from lines
Expand Down Expand Up @@ -314,8 +314,8 @@ DistanceOp::computeFacetDistance()
std::cerr << "PointExtracter found " << pts1.size() << " points in geometry 2" << std::endl;
#endif

locGeom[0] = nullptr;
locGeom[1] = nullptr;
locGeom[0] = GeometryLocation();
locGeom[1] = GeometryLocation();
computeMinDistanceLinesPoints(lines0, pts1, locGeom);
updateMinDistance(locGeom, false);
if(minDistance <= terminateDistance) {
Expand All @@ -332,8 +332,8 @@ DistanceOp::computeFacetDistance()
std::cerr << "PointExtracter found " << pts0.size() << " points in geometry 1" << std::endl;
#endif

locGeom[0] = nullptr;
locGeom[1] = nullptr;
locGeom[0] = GeometryLocation();
locGeom[1] = GeometryLocation();
computeMinDistanceLinesPoints(lines1, pts0, locGeom);
updateMinDistance(locGeom, true);
if(minDistance <= terminateDistance) {
Expand All @@ -343,8 +343,8 @@ DistanceOp::computeFacetDistance()
return;
}

locGeom[0] = nullptr;
locGeom[1] = nullptr;
locGeom[0] = GeometryLocation();
locGeom[1] = GeometryLocation();
computeMinDistancePoints(pts0, pts1, locGeom);
updateMinDistance(locGeom, false);

Expand All @@ -358,7 +358,7 @@ void
DistanceOp::computeMinDistanceLines(
const LineString::ConstVect& lines0,
const LineString::ConstVect& lines1,
std::array<std::unique_ptr<GeometryLocation>, 2> & locGeom)
std::array<GeometryLocation, 2> & locGeom)
{
for(const LineString* line0 : lines0) {
for(const LineString* line1 : lines1) {
Expand All @@ -379,7 +379,7 @@ void
DistanceOp::computeMinDistancePoints(
const Point::ConstVect& points0,
const Point::ConstVect& points1,
std::array<std::unique_ptr<GeometryLocation>, 2> & locGeom)
std::array<GeometryLocation, 2> & locGeom)
{
for(const Point* pt0 : points0) {
for(const Point* pt1 : points1) {
Expand All @@ -400,8 +400,8 @@ DistanceOp::computeMinDistancePoints(
if(dist < minDistance) {
minDistance = dist;
// this is wrong - need to determine closest points on both segments!!!
locGeom[0].reset(new GeometryLocation(pt0, 0, *(pt0->getCoordinate())));
locGeom[1].reset(new GeometryLocation(pt1, 0, *(pt1->getCoordinate())));
locGeom[0] = GeometryLocation(pt0, 0, *(pt0->getCoordinate()));
locGeom[1] = GeometryLocation(pt1, 0, *(pt1->getCoordinate()));
}

if(minDistance <= terminateDistance) {
Expand All @@ -416,7 +416,7 @@ void
DistanceOp::computeMinDistanceLinesPoints(
const LineString::ConstVect& lines,
const Point::ConstVect& points,
std::array<std::unique_ptr<GeometryLocation>, 2> & locGeom)
std::array<GeometryLocation, 2> & locGeom)
{
for(const LineString* line : lines) {
for(const Point* pt : points) {
Expand All @@ -437,7 +437,7 @@ void
DistanceOp::computeMinDistance(
const LineString* line0,
const LineString* line1,
std::array<std::unique_ptr<GeometryLocation>, 2> & locGeom)
std::array<GeometryLocation, 2> & locGeom)
{
using geos::algorithm::Distance;

Expand Down Expand Up @@ -484,8 +484,8 @@ DistanceOp::computeMinDistance(
LineSegment seg1{Coordinate(p10), Coordinate(p11)};
auto closestPt = seg0.closestPoints(seg1);

locGeom[0].reset(new GeometryLocation(line0, i, closestPt[0]));
locGeom[1].reset(new GeometryLocation(line1, j, closestPt[1]));
locGeom[0] = GeometryLocation(line0, i, closestPt[0]);
locGeom[1] = GeometryLocation(line1, j, closestPt[1]);
}
if(minDistance <= terminateDistance) {
return;
Expand All @@ -498,7 +498,7 @@ DistanceOp::computeMinDistance(
void
DistanceOp::computeMinDistance(const LineString* line,
const Point* pt,
std::array<std::unique_ptr<GeometryLocation>, 2> & locGeom)
std::array<GeometryLocation, 2> & locGeom)
{
using geos::algorithm::Distance;

Expand All @@ -524,8 +524,8 @@ DistanceOp::computeMinDistance(const LineString* line,
Coordinate segClosestPoint;
seg.closestPoint(*coord, segClosestPoint);

locGeom[0].reset(new GeometryLocation(line, i, segClosestPoint));
locGeom[1].reset(new GeometryLocation(pt, 0, *coord));
locGeom[0] = GeometryLocation(line, i, segClosestPoint);
locGeom[1] = GeometryLocation(pt, 0, *coord);
}
if(minDistance <= terminateDistance) {
return;
Expand Down

0 comments on commit 60e0ae2

Please sign in to comment.