Skip to content

Commit

Permalink
Fix overlay heuristic for GeometryCollections with empty elements (#1229
Browse files Browse the repository at this point in the history
)
  • Loading branch information
dr-jts authored Jan 17, 2025
1 parent 26292ce commit b6c1b59
Show file tree
Hide file tree
Showing 9 changed files with 273 additions and 134 deletions.
38 changes: 25 additions & 13 deletions include/geos/geom/HeuristicOverlay.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,25 @@ class StructuredCollection {

public:

static std::unique_ptr<Geometry> overlay(const Geometry* g0, const Geometry* g1, int opCode);

private:

const GeometryFactory* factory;
std::vector<const Geometry*> pts;
std::vector<const Geometry*> lines;
std::vector<const Geometry*> polys;
std::unique_ptr<Geometry> pt_union;
std::unique_ptr<Geometry> line_union;
std::unique_ptr<Geometry> poly_union;
Dimension::DimensionType dimension;

StructuredCollection(const Geometry* g)
: factory(g->getFactory())
, pt_union(nullptr)
, line_union(nullptr)
, poly_union(nullptr)
, dimension(Dimension::DONTCARE)
{
readCollection(g);
unionByDimension();
Expand All @@ -61,8 +75,19 @@ class StructuredCollection {
, pt_union(nullptr)
, line_union(nullptr)
, poly_union(nullptr)
, dimension(Dimension::DONTCARE)
{};

Dimension::DimensionType getDimension() const
{
return dimension;
};

void addDimension(Dimension::DimensionType dim);
std::unique_ptr<Geometry> doUnaryUnion(int resultDim) const;
std::unique_ptr<Geometry> computeResult(StructuredCollection& coll, int opCode,
Dimension::DimensionType dimA, Dimension::DimensionType dimB) const;

void readCollection(const Geometry* g);
const Geometry* getPolyUnion() const { return poly_union.get(); }
const Geometry* getLineUnion() const { return line_union.get(); }
Expand All @@ -72,22 +97,9 @@ class StructuredCollection {
std::unique_ptr<Geometry> doIntersection(const StructuredCollection& a) const;
std::unique_ptr<Geometry> doSymDifference(const StructuredCollection& a) const;
std::unique_ptr<Geometry> doDifference(const StructuredCollection& a) const;
std::unique_ptr<Geometry> doUnaryUnion() const;

static void toVector(const Geometry* g, std::vector<const Geometry*>& v);
void unionByDimension(void);


private:

const GeometryFactory* factory;
std::vector<const Geometry*> pts;
std::vector<const Geometry*> lines;
std::vector<const Geometry*> polys;
std::unique_ptr<Geometry> pt_union;
std::unique_ptr<Geometry> line_union;
std::unique_ptr<Geometry> poly_union;

};


Expand Down
71 changes: 0 additions & 71 deletions src/geom/Geometry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -619,43 +619,6 @@ Geometry::intersection(const Geometry* other) const
std::unique_ptr<Geometry>
Geometry::Union(const Geometry* other) const
{
#ifdef SHORTCIRCUIT_PREDICATES
// if envelopes are disjoint return a MULTI geom or
// a geometrycollection
if(! getEnvelopeInternal()->intersects(other->getEnvelopeInternal())) {
//cerr<<"SHORTCIRCUITED-UNION engaged"<<endl;
const GeometryCollection* coll;

std::size_t ngeomsThis = getNumGeometries();
std::size_t ngeomsOther = other->getNumGeometries();

// Allocated for ownership transfer
std::vector<std::unique_ptr<Geometry>> v;
v.reserve(ngeomsThis + ngeomsOther);


if(nullptr != (coll = dynamic_cast<const GeometryCollection*>(this))) {
for(std::size_t i = 0; i < ngeomsThis; ++i) {
v.push_back(coll->getGeometryN(i)->clone());
}
}
else {
v.push_back(this->clone());
}

if(nullptr != (coll = dynamic_cast<const GeometryCollection*>(other))) {
for(std::size_t i = 0; i < ngeomsOther; ++i) {
v.push_back(coll->getGeometryN(i)->clone());
}
}
else {
v.push_back(other->clone());
}

return _factory->buildGeometry(std::move(v));
}
#endif

return HeuristicOverlay(this, other, OverlayNG::UNION);
}

Expand All @@ -676,40 +639,6 @@ Geometry::difference(const Geometry* other) const
std::unique_ptr<Geometry>
Geometry::symDifference(const Geometry* other) const
{
// if envelopes are disjoint return a MULTI geom or
// a geometrycollection
if(! getEnvelopeInternal()->intersects(other->getEnvelopeInternal()) && !(isEmpty() && other->isEmpty())) {
const GeometryCollection* coll;

std::size_t ngeomsThis = getNumGeometries();
std::size_t ngeomsOther = other->getNumGeometries();

// Allocated for ownership transfer
std::vector<std::unique_ptr<Geometry>> v;
v.reserve(ngeomsThis + ngeomsOther);


if(nullptr != (coll = dynamic_cast<const GeometryCollection*>(this))) {
for(std::size_t i = 0; i < ngeomsThis; ++i) {
v.push_back(coll->getGeometryN(i)->clone());
}
}
else {
v.push_back(this->clone());
}

if(nullptr != (coll = dynamic_cast<const GeometryCollection*>(other))) {
for(std::size_t i = 0; i < ngeomsOther; ++i) {
v.push_back(coll->getGeometryN(i)->clone());
}
}
else {
v.push_back(other->clone());
}

return _factory->buildGeometry(std::move(v));
}

return HeuristicOverlay(this, other, OverlayNG::SYMDIFFERENCE);
}

Expand Down
Loading

0 comments on commit b6c1b59

Please sign in to comment.