Skip to content

Commit

Permalink
Overlay with mixed dimension (#923)
Browse files Browse the repository at this point in the history
For overlay operations (union/difference/intersection/symdifference) support for GeometryCollection has been missing, at least for those cases of GeometryCollection that contain a mixture of types (point/line/polygon).

This fix tests inputs to HeuristicOverlay (formerly a wide-ranging set of shims to work around issues with the old overlay code) and for those that are mixed-type collections, processes the component dimensions separately, with appropriate logic for the overlay operation being run. Fixes GH-797.
  • Loading branch information
pramsey authored Jun 14, 2023
1 parent 5611d6b commit c37391c
Show file tree
Hide file tree
Showing 6 changed files with 672 additions and 38 deletions.
3 changes: 3 additions & 0 deletions include/geos/geom/Geometry.h
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,9 @@ class GEOS_DLL Geometry {
return isDimensionStrict(Dimension::A);
}

bool isMixedDimension() const;
bool isMixedDimension(Dimension::DimensionType* baseDim) const;

bool isCollection() const {
int t = getGeometryTypeId();
return t == GEOS_GEOMETRYCOLLECTION ||
Expand Down
68 changes: 66 additions & 2 deletions include/geos/geom/HeuristicOverlay.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,80 @@
#pragma once

#include <geos/export.h>
#include <geos/geom/Geometry.h>
#include <geos/geom/Dimension.h>


#include <memory> // for unique_ptr
#include <vector>

namespace geos {
namespace geom { // geos::geom

namespace geos {
namespace geom {
class Geometry;
class GeometryFactory;
}
}


namespace geos {
namespace geom { // geos::geom

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

class StructuredCollection {

public:

StructuredCollection(const Geometry* g)
: factory(g->getFactory())
, pt_union(nullptr)
, line_union(nullptr)
, poly_union(nullptr)
{
readCollection(g);
unionByDimension();
};

StructuredCollection()
: factory(nullptr)
, pt_union(nullptr)
, line_union(nullptr)
, poly_union(nullptr)
{};

void readCollection(const Geometry* g);
const Geometry* getPolyUnion() const { return poly_union.get(); }
const Geometry* getLineUnion() const { return line_union.get(); }
const Geometry* getPointUnion() const { return pt_union.get(); }

std::unique_ptr<Geometry> doUnion(const StructuredCollection& a) const;
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;

};





} // namespace geos::geom
} // namespace geos

28 changes: 28 additions & 0 deletions src/geom/Geometry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,34 @@ Geometry::getCentroid() const
return std::unique_ptr<Point>(getFactory()->createPoint(centPt));
}

/* public */
bool
Geometry::isMixedDimension() const
{
Dimension::DimensionType baseDim = Dimension::DONTCARE;
return isMixedDimension(&baseDim);
}

/* public */
bool
Geometry::isMixedDimension(Dimension::DimensionType* baseDim) const
{
if (isCollection()) {
for (std::size_t i = 0; i < getNumGeometries(); i++) {
if (getGeometryN(i)->isMixedDimension(baseDim))
return true;
}
return false;
}
else {
if (*baseDim == Dimension::DONTCARE) {
*baseDim = getDimension();
return false;
}
return *baseDim != getDimension();
}
}

/*public*/
bool
Geometry::getCentroid(CoordinateXY& ret) const
Expand Down
Loading

0 comments on commit c37391c

Please sign in to comment.