[geos-commits] [SCM] GEOS branch main updated. 7e7c2689257fa53ee3252c44264a776bc74c9c9f
git at osgeo.org
git at osgeo.org
Thu Oct 1 07:11:19 PDT 2026
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GEOS".
The branch, main has been updated
via 7e7c2689257fa53ee3252c44264a776bc74c9c9f (commit)
from cd6b251809cc60f1d05684b324eaac1635ab04d9 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 7e7c2689257fa53ee3252c44264a776bc74c9c9f
Author: Sandro Santilli <strk at kbt.io>
Date: Wed Sep 30 16:45:35 2026 +0200
Add IsSimpleWithParams with params create/destroy/setters
Closes GH-1543
Includes unit test for the new CAPI signatures
diff --git a/NEWS.md b/NEWS.md
index 10451996e..ccf7bf58a 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -9,6 +9,7 @@
- New things:
- Expose code revision: GEOS_REVISION, GEOSrevision, geos-config --revision
(GH-1446 Sandro Santilli)
+ - GEOSisSimpleWithParams (GH-1543 Sandro Santilli)
## Changes in 3.15.0
2026-09-01
diff --git a/capi/geos_c.cpp b/capi/geos_c.cpp
index 568f1c0b4..b2918e466 100644
--- a/capi/geos_c.cpp
+++ b/capi/geos_c.cpp
@@ -69,6 +69,11 @@ typedef struct {
int keepCollapsed;
} GEOSMakeValidParams;
+// Implementation struct for the GEOSisSimpleParams object
+typedef struct {
+ bool findAllLocations;
+ int boundaryNodeRule;
+} GEOSisSimpleParams;
#include "geos_c.h"
@@ -546,6 +551,36 @@ extern "C" {
return GEOSisSimpleDetail_r(handle, g, returnAllPoints, result);
}
+ GEOSisSimpleParams*
+ GEOSisSimpleParams_create(void)
+ {
+ return GEOSisSimpleParams_create_r(handle);
+ }
+
+ void
+ GEOSisSimpleParams_destroy(GEOSisSimpleParams* parms)
+ {
+ return GEOSisSimpleParams_destroy_r(handle, parms);
+ }
+
+ void
+ GEOSisSimpleParams_setFindAllLocations(GEOSisSimpleParams* params, int val)
+ {
+ return GEOSisSimpleParams_setFindAllLocations_r(handle, params, val);
+ }
+
+ void
+ GEOSisSimpleParams_setBoundaryNodeRule(GEOSisSimpleParams* params, int bnr)
+ {
+ return GEOSisSimpleParams_setBoundaryNodeRule_r(handle, params, bnr);
+ }
+
+ char
+ GEOSisSimpleWithParams(const Geometry *g, const GEOSisSimpleParams* params, Geometry** result)
+ {
+ return GEOSisSimpleWithParams_r(handle, g, params, result);
+ }
+
char
GEOSisRing(const Geometry* g)
{
diff --git a/capi/geos_c.h.in b/capi/geos_c.h.in
index 19ec83cd0..ae9d7c384 100644
--- a/capi/geos_c.h.in
+++ b/capi/geos_c.h.in
@@ -220,7 +220,15 @@ typedef struct GEOSCurveToLineParams_t GEOSCurveToLineParams;
*/
typedef struct GEOSLineToCurveParams_t GEOSLineToCurveParams;
-#endif
+/**
+* Parameter object for simplicity check.
+* \see GEOSisSimpleParams_create()
+* \see GEOSisSimpleParams_destroy()
+*/
+typedef struct GEOSisSimpleParams_t GEOSisSimpleParams;
+
+#endif /* ndef GEOSGeometry */
+
/** \cond */
@@ -1678,6 +1686,36 @@ extern char GEOS_DLL GEOSisSimple_r(
GEOSContextHandle_t handle,
const GEOSGeometry* g);
+/** \see GEOSIsSimpleParams_create */
+extern GEOSisSimpleParams GEOS_DLL *
+GEOSisSimpleParams_create_r(
+ GEOSContextHandle_t handle);
+
+/** \see GEOSIsSimpleParams_destroy */
+extern void GEOS_DLL
+GEOSisSimpleParams_destroy_r(
+ GEOSContextHandle_t handle,
+ GEOSisSimpleParams* params);
+
+/** \see GEOSisSimpleParams_setFindAllLocations */
+extern void GEOS_DLL GEOSisSimpleParams_setFindAllLocations_r(
+ GEOSContextHandle_t handle,
+ GEOSisSimpleParams* params,
+ int findAllLocations);
+
+/** \see GEOSisSimpleParams_setBoundaryNodeRule */
+extern void GEOS_DLL GEOSisSimpleParams_setBoundaryNodeRule_r(
+ GEOSContextHandle_t handle,
+ GEOSisSimpleParams* params,
+ int bnr);
+
+/** \see GEOSisSimpleWithParams */
+extern char GEOS_DLL GEOSisSimpleWithParams_r(
+ GEOSContextHandle_t handle,
+ const GEOSGeometry* g,
+ const GEOSisSimpleParams* params,
+ GEOSGeometry** location);
+
/** \see GEOSisRing */
extern char GEOS_DLL GEOSisRing_r(
GEOSContextHandle_t handle,
@@ -3680,6 +3718,71 @@ extern char GEOS_DLL GEOSisSimpleDetail(
int findAllLocations,
GEOSGeometry** locations);
+/**
+* Create a GEOSisSimpleParams to hold the desired parameters
+* to control the algorithm and behavior of the simplicity check process.
+* \return a parameter object configured to find all intersection
+* and use Mod2 boundary node rule
+* \see GEOSisSimpleWithParams
+*
+* \since 3.16
+*/
+extern GEOSisSimpleParams GEOS_DLL *GEOSisSimpleParams_create(void);
+
+/**
+* Destroy a GEOSisSimpleParams.
+* \param params the object to destroy
+* \see GEOSisSimpleWithParams
+*
+* \since 3.16
+*/
+extern void GEOS_DLL GEOSisSimpleParams_destroy(GEOSisSimpleParams* params);
+
+/**
+* Set whether to return all self-intersection locations or just one
+* \param params the object to modify
+* \param findAllLocations Whether to return all self-intersection locations, or just one
+* \see GEOSisSimpleWithParams
+*
+* \since 3.16
+*/
+extern void GEOS_DLL GEOSisSimpleParams_setFindAllLocations(
+ GEOSisSimpleParams* params,
+ int findAllLocations);
+
+/**
+* Set BoundaryNodeRule to use with the simplicity check
+* \param params the object to modify
+* \param bnr A member of the \ref GEOSRelateBoundaryNodeRules enum
+* \see GEOSisSimpleWithParams
+*
+* \since 3.16
+*/
+extern void GEOS_DLL GEOSisSimpleParams_setBoundaryNodeRule(
+ GEOSisSimpleParams* params,
+ int bnr);
+
+/**
+* In one step, calculate and return whether a geometry is simple
+* and one more more points at which the geometry self-intersects
+* at interior points.
+* Caller has the responsibility to destroy 'location' with
+* GEOSGeom_destroy()
+*
+* @INPUT_CURVES_CONVERTED_TO_LINES@
+*
+* \param g The geometry to test
+* \param params various parameters for the operation
+* \param locations A pointer in which the location GEOSGeometry will be placed
+* \return 1 when simple, 0 when non-simple, 2 on exception
+*
+* \since 3.16
+*/
+extern char GEOS_DLL GEOSisSimpleWithParams(
+ const GEOSGeometry* g,
+ const GEOSisSimpleParams* params,
+ GEOSGeometry** locations);
+
/**
* Check the validity of the provided geometry.
* - All points are valid.
diff --git a/capi/geos_ts_c.cpp b/capi/geos_ts_c.cpp
index e118726e7..1f05db1ff 100644
--- a/capi/geos_ts_c.cpp
+++ b/capi/geos_ts_c.cpp
@@ -177,6 +177,12 @@ typedef struct {
int keepCollapsed;
} GEOSMakeValidParams;
+// Implementation struct for the GEOSisSimpleParams object
+typedef struct {
+ bool findAllLocations;
+ int boundaryNodeRule;
+} GEOSisSimpleParams;
+
#include "geos_c.h"
// Intentional, to allow non-standard C elements like C99 functions to be
@@ -1550,6 +1556,10 @@ extern "C" {
});
}
+/************************************************************************
+ * IsSimpleOp {
+ */
+
char
GEOSisSimple_r(GEOSContextHandle_t extHandle, const Geometry* g1)
{
@@ -1583,6 +1593,92 @@ extern "C" {
});
}
+ GEOSisSimpleParams*
+ GEOSisSimpleParams_create_r(GEOSContextHandle_t extHandle)
+ {
+ using geos::algorithm::BoundaryNodeRule;
+
+ return execute(extHandle, [&]() {
+ GEOSisSimpleParams* p = new GEOSisSimpleParams();
+ p->findAllLocations = false;
+ p->boundaryNodeRule = GEOSRELATE_BNR_MOD2;
+ return p;
+ });
+ }
+
+ void
+ GEOSisSimpleParams_destroy_r(GEOSContextHandle_t extHandle, GEOSisSimpleParams* parms)
+ {
+ (void)extHandle;
+ delete parms;
+ }
+
+ void
+ GEOSisSimpleParams_setFindAllLocations_r(GEOSContextHandle_t extHandle, GEOSisSimpleParams* params, int val)
+ {
+ (void)extHandle;
+ params->findAllLocations = val;
+ }
+
+ void
+ GEOSisSimpleParams_setBoundaryNodeRule_r(GEOSContextHandle_t extHandle, GEOSisSimpleParams* params, int bnr)
+ {
+ (void)extHandle;
+ params->boundaryNodeRule = bnr;
+ }
+
+
+ char
+ GEOSisSimpleWithParams_r(GEOSContextHandle_t extHandle, const Geometry* g1, const GEOSisSimpleParams* params, Geometry** result)
+ {
+ using geos::algorithm::BoundaryNodeRule;
+ using geos::operation::valid::IsSimpleOp;
+
+ return execute(extHandle, 2, [&]() {
+ const auto inputGeom = convertToLineIfNeeded(extHandle, g1);
+ std::unique_ptr<IsSimpleOp> op;
+
+ switch ( params->boundaryNodeRule ) {
+ case GEOSRELATE_BNR_MOD2: /* same as OGC */
+ op = std::make_unique<IsSimpleOp>(*inputGeom, BoundaryNodeRule::getBoundaryRuleMod2());
+ break;
+ case GEOSRELATE_BNR_ENDPOINT:
+ op = std::make_unique<IsSimpleOp>(*inputGeom, BoundaryNodeRule::getBoundaryEndPoint());
+ break;
+ case GEOSRELATE_BNR_MULTIVALENT_ENDPOINT:
+ op = std::make_unique<IsSimpleOp>(*inputGeom, BoundaryNodeRule::getBoundaryMultivalentEndPoint());
+ break;
+ case GEOSRELATE_BNR_MONOVALENT_ENDPOINT:
+ op = std::make_unique<IsSimpleOp>(*inputGeom, BoundaryNodeRule::getBoundaryMonovalentEndPoint());
+ break;
+ default:
+ std::ostringstream ss;
+ ss << "Invalid boundary node rule " << params->boundaryNodeRule;
+ throw std::runtime_error(ss.str());
+ }
+
+ op->setFindAllLocations( params->findAllLocations );
+
+ *result = nullptr;
+
+ bool simple = op->isSimple();
+ if (!simple) {
+ auto locations = op->getNonSimpleLocations();
+ if (locations.size() == 1 || ! params->findAllLocations ) {
+ *result = extHandle->geomFactory->createPoint(locations.front()).release();
+ } else {
+ *result = extHandle->geomFactory->createMultiPoint(locations).release();
+ }
+ }
+
+ return simple;
+ });
+ }
+
+/*
+ * IsSimpleOp }
+ ************************************************************************/
+
char
GEOSisRing_r(GEOSContextHandle_t extHandle, const Geometry* g)
{
diff --git a/tests/unit/capi/GEOSisSimpleWithParamsTest.cpp b/tests/unit/capi/GEOSisSimpleWithParamsTest.cpp
new file mode 100644
index 000000000..f469fea99
--- /dev/null
+++ b/tests/unit/capi/GEOSisSimpleWithParamsTest.cpp
@@ -0,0 +1,83 @@
+#include <tut/tut.hpp>
+// geos
+#include <geos_c.h>
+
+#include "capi_test_utils.h"
+
+namespace tut {
+//
+// Test Group
+//
+
+struct test_geosissimplewithparams_data : public capitest::utility {
+ GEOSisSimpleParams* _params;
+ test_geosissimplewithparams_data()
+ {
+ _params = GEOSisSimpleParams_create();
+ }
+ ~test_geosissimplewithparams_data()
+ {
+ GEOSisSimpleParams_destroy( _params );
+ }
+};
+
+typedef test_group<test_geosissimplewithparams_data> group;
+typedef group::object object;
+
+group test_geosissimplewithparams("capi::GEOSisSimpleWithParams");
+
+template<>
+template<>
+void object::test<1>()
+{
+ input_ = GEOSGeomFromWKT("MULTILINESTRING( (0 0, -10 10,-10 -10, 0 0), (0 0,20 -10,20 10,0 0) )");
+ ensure(nullptr != input_);
+ ensure_equals((int)GEOSisSimpleWithParams(input_, _params, &result_), 0);
+ ensure_geometry_equals(result_, "POINT (0 0)");
+}
+
+template<>
+template<>
+void object::test<2>()
+{
+ input_ = GEOSGeomFromWKT("MULTILINESTRING( (0 0, -10 10,-10 -10, 0 0), (0 0,20 -10,20 10,0 0) )");
+ ensure(nullptr != input_);
+ GEOSisSimpleParams_setBoundaryNodeRule(_params, GEOSRELATE_BNR_ENDPOINT);
+ ensure_equals((int)GEOSisSimpleWithParams(input_, _params, &result_), 1);
+ ensure(result_ == nullptr);
+}
+
+template<>
+template<>
+void object::test<3>()
+{
+ input_ = GEOSGeomFromWKT("MULTILINESTRING( (0 0, -10 10,-10 -10, 0 0), (0 0,20 -10,20 10,0 0) )");
+ ensure(nullptr != input_);
+ GEOSisSimpleParams_setBoundaryNodeRule(_params, GEOSRELATE_BNR_MULTIVALENT_ENDPOINT);
+ ensure_equals((int)GEOSisSimpleWithParams(input_, _params, &result_), 1);
+ ensure(result_ == nullptr);
+}
+
+template<>
+template<>
+void object::test<4>()
+{
+ input_ = GEOSGeomFromWKT("MULTILINESTRING( (0 0, -10 10,-10 -10, 0 0), (0 0,20 -10,20 10,0 0) )");
+ ensure(nullptr != input_);
+ GEOSisSimpleParams_setBoundaryNodeRule(_params, GEOSRELATE_BNR_MONOVALENT_ENDPOINT);
+ ensure_equals((int)GEOSisSimpleWithParams(input_, _params, &result_), 0);
+ ensure_geometry_equals(result_, "POINT (0 0)");
+}
+
+template<>
+template<>
+void object::test<5>()
+{
+ input_ = GEOSGeomFromWKT("MULTILINESTRING( (0 0,10 0),(2 -5,2 5),(4 -5, 4 5) )");
+ ensure(nullptr != input_);
+ GEOSisSimpleParams_setFindAllLocations(_params, 1);
+ ensure_equals((int)GEOSisSimpleWithParams(input_, _params, &result_), 0);
+ ensure_equals(GEOSGetNumGeometries(result_), 2);
+}
+
+} // namespace tut
-----------------------------------------------------------------------
Summary of changes:
NEWS.md | 1 +
capi/geos_c.cpp | 35 +++++++++
capi/geos_c.h.in | 105 ++++++++++++++++++++++++-
capi/geos_ts_c.cpp | 96 ++++++++++++++++++++++
tests/unit/capi/GEOSisSimpleWithParamsTest.cpp | 83 +++++++++++++++++++
5 files changed, 319 insertions(+), 1 deletion(-)
create mode 100644 tests/unit/capi/GEOSisSimpleWithParamsTest.cpp
hooks/post-receive
--
GEOS
More information about the geos-commits
mailing list