Skip to content

Commit

Permalink
Guard against curved inputs, add C API tests
Browse files Browse the repository at this point in the history
  • Loading branch information
dbaston committed Mar 25, 2024
1 parent 4fc18f5 commit ae68dd4
Show file tree
Hide file tree
Showing 127 changed files with 1,207 additions and 84 deletions.
7 changes: 6 additions & 1 deletion capi/geos_c.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,12 @@ enum GEOSGeomTypes {
/** Multipolygon, a homogeneous collection of polygons */
GEOS_MULTIPOLYGON,
/** Geometry collection, a heterogeneous collection of geometry */
GEOS_GEOMETRYCOLLECTION
GEOS_GEOMETRYCOLLECTION,
GEOS_CIRCULARSTRING,
GEOS_COMPOUNDCURVE,
GEOS_CURVEPOLYGON,
GEOS_MULTICURVE,
GEOS_MULTISURFACE,
};

/**
Expand Down
39 changes: 26 additions & 13 deletions capi/geos_ts_c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include <geos/coverage/CoverageUnion.h>
#include <geos/geom/Coordinate.h>
#include <geos/geom/CoordinateSequence.h>
#include <geos/geom/Curve.h>
#include <geos/geom/Envelope.h>
#include <geos/geom/Geometry.h>
#include <geos/geom/GeometryCollection.h>
Expand All @@ -41,12 +42,14 @@
#include <geos/geom/LinearRing.h>
#include <geos/geom/LineSegment.h>
#include <geos/geom/LineString.h>
#include <geos/geom/MultiCurve.h>
#include <geos/geom/MultiLineString.h>
#include <geos/geom/MultiPoint.h>
#include <geos/geom/MultiPolygon.h>
#include <geos/geom/Point.h>
#include <geos/geom/Polygon.h>
#include <geos/geom/PrecisionModel.h>
#include <geos/geom/SimpleCurve.h>
#include <geos/geom/prep/PreparedGeometry.h>
#include <geos/geom/prep/PreparedGeometryFactory.h>
#include <geos/geom/util/Densifier.h>
Expand Down Expand Up @@ -162,17 +165,21 @@ using geos::geom::CoordinateXY;
using geos::geom::CoordinateXYM;
using geos::geom::CoordinateXYZM;
using geos::geom::CoordinateSequence;
using geos::geom::Curve;
using geos::geom::Envelope;
using geos::geom::Geometry;
using geos::geom::GeometryCollection;
using geos::geom::GeometryFactory;
using geos::geom::LineString;
using geos::geom::LinearRing;
using geos::geom::MultiCurve;
using geos::geom::MultiLineString;
using geos::geom::MultiPolygon;
using geos::geom::Point;
using geos::geom::Polygon;
using geos::geom::PrecisionModel;
using geos::geom::SimpleCurve;
using geos::geom::Surface;

using geos::io::WKTReader;
using geos::io::WKTWriter;
Expand Down Expand Up @@ -1048,8 +1055,7 @@ extern "C" {
GEOSisRing_r(GEOSContextHandle_t extHandle, const Geometry* g)
{
return execute(extHandle, 2, [&]() {
// both LineString* and LinearRing* can cast to LineString*
const LineString* ls = dynamic_cast<const LineString*>(g);
const Curve* ls = dynamic_cast<const Curve*>(g);
if(ls) {
return ls->isRing();
}
Expand Down Expand Up @@ -1692,6 +1698,8 @@ extern "C" {
if (g->getGeometryTypeId() == geos::geom::GeometryTypeId::GEOS_POLYGON) {
auto p = geos::detail::down_cast<Polygon*>(g);
p->orientRings(exteriorCW);
} else if (g->getGeometryTypeId() == geos::geom::GeometryTypeId::GEOS_CURVEPOLYGON) {
throw geos::util::UnsupportedOperationException("Curved geometries not supported.");
}
}

Expand All @@ -1710,9 +1718,9 @@ extern "C" {
GEOSGetNumInteriorRings_r(GEOSContextHandle_t extHandle, const Geometry* g1)
{
return execute(extHandle, -1, [&]() {
const Polygon* p = dynamic_cast<const Polygon*>(g1);
const Surface* p = dynamic_cast<const Surface*>(g1);
if(!p) {
throw IllegalArgumentException("Argument is not a Polygon");
throw IllegalArgumentException("Argument is not a Surface");
}
return static_cast<int>(p->getNumInteriorRing());
});
Expand Down Expand Up @@ -1802,7 +1810,7 @@ extern "C" {
GEOSisClosed_r(GEOSContextHandle_t extHandle, const Geometry* g1)
{
return execute(extHandle, 2, [&]() {
const LineString* ls = dynamic_cast<const LineString*>(g1);
const Curve* ls = dynamic_cast<const Curve*>(g1);
if(ls) {
return ls->isClosed();
}
Expand All @@ -1812,7 +1820,12 @@ extern "C" {
return mls->isClosed();
}

throw IllegalArgumentException("Argument is not a LineString or MultiLineString");
const MultiCurve* mc = dynamic_cast<const MultiCurve*>(g1);
if(mc) {
return mc->isClosed();
}

throw IllegalArgumentException("Argument is not a Curve, MultiLineString, or MultiCurve");
});
}

Expand Down Expand Up @@ -1840,9 +1853,9 @@ extern "C" {
GEOSGeomGetNumPoints_r(GEOSContextHandle_t extHandle, const Geometry* g1)
{
return execute(extHandle, -1, [&]() {
const LineString* ls = dynamic_cast<const LineString*>(g1);
const SimpleCurve* ls = dynamic_cast<const SimpleCurve*>(g1);
if(!ls) {
throw IllegalArgumentException("Argument is not a LineString");
throw IllegalArgumentException("Argument is not a SimpleCurve");
}
return static_cast<int>(ls->getNumPoints());
});
Expand Down Expand Up @@ -1926,9 +1939,9 @@ extern "C" {
GEOSGetExteriorRing_r(GEOSContextHandle_t extHandle, const Geometry* g1)
{
return execute(extHandle, [&]() {
const Polygon* p = dynamic_cast<const Polygon*>(g1);
const Surface* p = dynamic_cast<const Surface*>(g1);
if(!p) {
throw IllegalArgumentException("Invalid argument (must be a Polygon)");
throw IllegalArgumentException("Invalid argument (must be a Surface)");
}
return p->getExteriorRing();
});
Expand All @@ -1942,9 +1955,9 @@ extern "C" {
GEOSGetInteriorRingN_r(GEOSContextHandle_t extHandle, const Geometry* g1, int n)
{
return execute(extHandle, [&]() {
const Polygon* p = dynamic_cast<const Polygon*>(g1);
const Surface* p = dynamic_cast<const Surface*>(g1);
if(!p) {
throw IllegalArgumentException("Invalid argument (must be a Polygon)");
throw IllegalArgumentException("Invalid argument (must be a Surface)");
}
if(n < 0) {
throw IllegalArgumentException("Index must be non-negative.");
Expand Down Expand Up @@ -2813,7 +2826,7 @@ extern "C" {
GEOSGeom_getCoordSeq_r(GEOSContextHandle_t extHandle, const Geometry* g)
{
return execute(extHandle, [&]() {
const LineString* ls = dynamic_cast<const LineString*>(g);
const SimpleCurve* ls = dynamic_cast<const SimpleCurve*>(g);
if(ls) {
return ls->getCoordinatesRO();
}
Expand Down
10 changes: 1 addition & 9 deletions include/geos/algorithm/hull/ConcaveHull.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,15 +96,7 @@ class GEOS_DLL ConcaveHull {

public:

ConcaveHull(const Geometry* geom)
: inputGeometry(geom)
, maxEdgeLengthRatio(-1.0)
, alpha(-1)
, isHolesAllowed(false)
, criteriaType(PARAM_EDGE_LENGTH)
, maxSizeInHull(0.0)
, geomFactory(geom->getFactory())
{};
ConcaveHull(const Geometry* geom);

/**
* Computes the approximate edge length of
Expand Down
4 changes: 4 additions & 0 deletions include/geos/geom/CircularString.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ class GEOS_DLL CircularString : public SimpleCurve {
throw util::UnsupportedOperationException("Cannot calculate length of CircularString");
}

bool hasCurvedComponents() const override {
return true;
}

};


Expand Down
1 change: 1 addition & 0 deletions include/geos/geom/CompoundCurve.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ class GEOS_DLL CompoundCurve : public Curve {

int compareToSameClass(const Geometry* geom) const override;

bool hasCurvedComponents() const override;

protected:
CompoundCurve(std::vector<std::unique_ptr<SimpleCurve>>&&,
Expand Down
2 changes: 2 additions & 0 deletions include/geos/geom/Curve.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ class GEOS_DLL Curve : public Geometry {

virtual bool isClosed() const = 0;

bool isRing() const;

using Geometry::apply_ro;
using Geometry::apply_rw;

Expand Down
2 changes: 2 additions & 0 deletions include/geos/geom/CurvePolygon.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ class GEOS_DLL CurvePolygon : public SurfaceImpl<Curve> {

double getArea() const override;

bool hasCurvedComponents() const override;

protected:
using SurfaceImpl::SurfaceImpl;

Expand Down
6 changes: 5 additions & 1 deletion include/geos/geom/Geometry.h
Original file line number Diff line number Diff line change
Expand Up @@ -310,10 +310,14 @@ class GEOS_DLL Geometry {
virtual std::string getGeometryType() const = 0; //Abstract

/// Returns whether the Geometry type _may_ contain curved elements
virtual bool isCurvedType() const;
/// FIXME: this would be true for GeometryCollection ?
bool isCurvedType() const;

static bool isCurvedType(GeometryTypeId);

/// Returns whether the Geometry contains curved components
virtual bool hasCurvedComponents() const;

/// Return an integer representation of this Geometry type
virtual GeometryTypeId getGeometryTypeId() const = 0; //Abstract

Expand Down
2 changes: 2 additions & 0 deletions include/geos/geom/GeometryCollection.h
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,8 @@ class GEOS_DLL GeometryCollection : public Geometry {

int compareToSameClass(const Geometry* gc) const override;

bool hasCurvedComponents() const override;

};

} // namespace geos::geom
Expand Down
5 changes: 5 additions & 0 deletions include/geos/geom/MultiLineString.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,11 @@ class GEOS_DLL MultiLineString: public GeometryCollection {
return SORTINDEX_MULTILINESTRING;
};

bool hasCurvedComponents() const override
{
return false;
}

};


Expand Down
5 changes: 5 additions & 0 deletions include/geos/geom/MultiPoint.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,11 @@ class GEOS_DLL MultiPoint: public GeometryCollection {
return SORTINDEX_MULTIPOINT;
};

bool hasCurvedComponents() const override
{
return false;
}

};

#ifdef _MSC_VER
Expand Down
5 changes: 5 additions & 0 deletions include/geos/geom/MultiPolygon.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,11 @@ class GEOS_DLL MultiPolygon: public GeometryCollection {
return SORTINDEX_MULTIPOLYGON;
};

bool hasCurvedComponents() const override
{
return false;
}

};

#ifdef _MSC_VER
Expand Down
2 changes: 0 additions & 2 deletions include/geos/geom/SimpleCurve.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,6 @@ class GEOS_DLL SimpleCurve : public Curve {

bool isClosed() const override;

bool isRing() const;

virtual bool isCoordinate(CoordinateXY& pt) const;

bool equalsExact(const Geometry* other, double tolerance = 0)
Expand Down
10 changes: 0 additions & 10 deletions include/geos/operation/polygonize/Polygonizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -192,16 +192,6 @@ class GEOS_DLL Polygonizer {
*/
void add(std::vector<const geom::Geometry*>* geomList);

/**
* Add a geometry to the linework to be polygonized.
* May be called multiple times.
* Any dimension of Geometry may be added;
* the constituent linework will be extracted and used
*
* @param g a Geometry with linework to be polygonized
*/
void add(geom::Geometry* g);

/**
* Add a geometry to the linework to be polygonized.
* May be called multiple times.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class GEOS_DLL ConstrainedDelaunayTriangulator {
const Geometry* inputGeom;
const GeometryFactory* geomFact;

std::unique_ptr<Geometry> compute();
std::unique_ptr<Geometry> compute() const;

static std::unique_ptr<Geometry> toGeometry(
const geom::GeometryFactory* geomFact,
Expand Down
4 changes: 2 additions & 2 deletions include/geos/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,15 +66,15 @@ namespace util {
template<typename T>
void ensureNotCurvedType(const T* geom)
{
if (geom->isCurvedType()) {
if (geom->hasCurvedComponents()) {
throw UnsupportedOperationException("Curved geometry types are not supported.");
}
}

template<typename T>
void ensureNotCurvedType(const T& geom)
{
if (geom.isCurvedType()) {
if (geom.hasCurvedComponents()) {
throw UnsupportedOperationException("Curved geometry types are not supported.");
}
}
Expand Down
5 changes: 5 additions & 0 deletions src/algorithm/distance/DiscreteFrechetDistance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
#include <algorithm>
#include <limits>
#include <iostream>

#include "geos/util.h"
using namespace geos::geom;

namespace geos {
Expand Down Expand Up @@ -142,6 +144,9 @@ DiscreteFrechetDistance::compute(
throw util::IllegalArgumentException("DiscreteFrechetDistance called with empty inputs.");
}

util::ensureNotCurvedType(discreteGeom);
util::ensureNotCurvedType(geom);

auto lp = discreteGeom.getCoordinates();
auto lq = geom.getCoordinates();
std::size_t pSize, qSize;
Expand Down
5 changes: 5 additions & 0 deletions src/algorithm/distance/DiscreteHausdorffDistance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
#include <cassert>
#include <limits>

#include "geos/util.h"

using namespace geos::geom;

namespace geos {
Expand Down Expand Up @@ -101,6 +103,9 @@ DiscreteHausdorffDistance::computeOrientedDistance(
const geom::Geometry& geom,
PointPairDistance& p_ptDist)
{
util::ensureNotCurvedType(discreteGeom);
util::ensureNotCurvedType(geom);

// can't calculate distance with empty
if (discreteGeom.isEmpty() || geom.isEmpty()) return;

Expand Down
12 changes: 12 additions & 0 deletions src/algorithm/hull/ConcaveHull.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <geos/util/IllegalArgumentException.h>
#include <geos/util/IllegalStateException.h>
#include <geos/util/Assert.h>
#include <geos/util.h>


using geos::geom::Coordinate;
Expand All @@ -48,6 +49,17 @@ namespace geos {
namespace algorithm { // geos.algorithm
namespace hull { // geos.algorithm.hulll

ConcaveHull::ConcaveHull(const Geometry* geom)
: inputGeometry(geom)
, maxEdgeLengthRatio(-1.0)
, alpha(-1)
, isHolesAllowed(false)
, criteriaType(PARAM_EDGE_LENGTH)
, maxSizeInHull(0.0)
, geomFactory(geom->getFactory())
{
util::ensureNotCurvedType(geom);
};

/* public static */
double
Expand Down
Loading

0 comments on commit ae68dd4

Please sign in to comment.