Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix overlay heuristic for GeometryCollections with empty elements #1229

Merged
merged 13 commits into from
Jan 17, 2025
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
Loading