[geos-commits] [SCM] GEOS branch main updated. 39629616d518dfa3f5c48365b4baf7017aa1625c
git at osgeo.org
git at osgeo.org
Mon Jun 17 19:33:51 PDT 2024
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 39629616d518dfa3f5c48365b4baf7017aa1625c (commit)
from 5dc668b7f2ca3beb9d188b9dfc6f8f3e4935894a (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 39629616d518dfa3f5c48365b4baf7017aa1625c
Author: Dan Baston <dbaston at gmail.com>
Date: Mon Jun 17 22:33:34 2024 -0400
C API: Add functions to create curved types (#1108)
diff --git a/capi/geos_c.cpp b/capi/geos_c.cpp
index 12cabdfe0..0794c1801 100644
--- a/capi/geos_c.cpp
+++ b/capi/geos_c.cpp
@@ -1204,6 +1204,24 @@ extern "C" {
return GEOSGeom_createPolygon_r(handle, shell, holes, nholes);
}
+ Geometry*
+ GEOSGeom_createCircularString(CoordinateSequence* cs)
+ {
+ return GEOSGeom_createCircularString_r(handle, cs);
+ }
+
+ Geometry*
+ GEOSGeom_createCompoundCurve(Geometry** curves, unsigned int ngeoms)
+ {
+ return GEOSGeom_createCompoundCurve_r(handle, curves, ngeoms);
+ }
+
+ Geometry*
+ GEOSGeom_createCurvePolygon(Geometry* shell, Geometry** holes, unsigned int nholes)
+ {
+ return GEOSGeom_createCurvePolygon_r(handle, shell, holes, nholes);
+ }
+
Geometry*
GEOSGeom_clone(const Geometry* g)
{
@@ -1728,6 +1746,24 @@ extern "C" {
return GEOSGeom_createEmptyPolygon_r(handle);
}
+ geos::geom::Geometry*
+ GEOSGeom_createEmptyCircularString()
+ {
+ return GEOSGeom_createEmptyCircularString_r(handle);
+ }
+
+ geos::geom::Geometry*
+ GEOSGeom_createEmptyCompoundCurve()
+ {
+ return GEOSGeom_createEmptyCompoundCurve_r(handle);
+ }
+
+ geos::geom::Geometry*
+ GEOSGeom_createEmptyCurvePolygon()
+ {
+ return GEOSGeom_createEmptyCurvePolygon_r(handle);
+ }
+
geos::geom::Geometry*
GEOSGeom_createRectangle(double xmin, double ymin, double xmax,
double ymax)
diff --git a/capi/geos_c.h.in b/capi/geos_c.h.in
index 5db388b24..3327da757 100644
--- a/capi/geos_c.h.in
+++ b/capi/geos_c.h.in
@@ -763,6 +763,36 @@ extern GEOSGeometry GEOS_DLL *GEOSGeom_clone_r(
GEOSContextHandle_t handle,
const GEOSGeometry* g);
+/** \see GEOSGeom_createCircularString */
+extern GEOSGeometry GEOS_DLL *GEOSGeom_createCircularString_r(
+ GEOSContextHandle_t handle,
+ GEOSCoordSequence* s);
+
+/** \see GEOSGeom_createEmptyCircularString */
+extern GEOSGeometry GEOS_DLL *GEOSGeom_createEmptyCircularString_r(
+ GEOSContextHandle_t handle);
+
+/** \see GEOSGeom_createCompoundCurve */
+extern GEOSGeometry GEOS_DLL *GEOSGeom_createCompoundCurve_r(
+ GEOSContextHandle_t handle,
+ GEOSGeometry** curves,
+ unsigned int ncurves);
+
+/** \see GEOSGeom_createEmptyCompoundCurve */
+extern GEOSGeometry GEOS_DLL *GEOSGeom_createEmptyCompoundCurve_r(
+ GEOSContextHandle_t handle);
+
+/** \see GEOSGeom_createCurvePolygon */
+extern GEOSGeometry GEOS_DLL *GEOSGeom_createCurvePolygon_r(
+ GEOSContextHandle_t handle,
+ GEOSGeometry* shell,
+ GEOSGeometry** holes,
+ unsigned int nholes);
+
+/** \see GEOSGeom_createEmptyCurvePolygon */
+extern GEOSGeometry GEOS_DLL *GEOSGeom_createEmptyCurvePolygon_r(
+ GEOSContextHandle_t handle);
+
/* ========= Memory management ========= */
/** \see GEOSGeom_destroy */
@@ -2458,6 +2488,68 @@ extern GEOSGeometry GEOS_DLL *GEOSGeom_createPolygon(
GEOSGeometry** holes,
unsigned int nholes);
+/**
+* Creates a CircularString geometry.
+* \param s Input coordinate sequence, ownership passes to the geometry
+* \return A newly allocated CircularString geometry. NULL on exception.
+* Caller is responsible for freeing with GEOSGeom_destroy().
+* \since 3.13
+*/
+extern GEOSGeometry GEOS_DLL *GEOSGeom_createCircularString(GEOSCoordSequence* s);
+
+/**
+* Creates an empty CircularString geometry.
+* \return A newly allocated CircularString geometry. NULL on exception.
+* Caller is responsible for freeing with GEOSGeom_destroy().
+* \since 3.13
+*/
+extern GEOSGeometry GEOS_DLL *GEOSGeom_createEmptyCircularString();
+
+/**
+* Creates a CompoundCurve geometry.
+* \param curves A list of geometries that will form the CompoundCurve
+* \param ncurves The number of geometries in the curves list
+* \return A newly allocated CompoundCurve geometry. NULL on exception.
+* Caller is responsible for freeing with GEOSGeom_destroy().
+* \since 3.13
+*/
+extern GEOSGeometry GEOS_DLL *GEOSGeom_createCompoundCurve(GEOSGeometry** curves,
+ unsigned int ncurves);
+
+/**
+* Creates an empty CompoundCurve geometry.
+* \return A newly allocated CompoundCurve geometry. NULL on exception.
+* Caller is responsible for freeing with GEOSGeom_destroy().
+* \since 3.13
+*/
+extern GEOSGeometry GEOS_DLL *GEOSGeom_createEmptyCompoundCurve();
+
+/**
+* Creates a CurvePolygon geometry from ring geometries.
+* \param shell A ring that is the exterior ring of the polygon.
+* \param holes An array of rings that are the holes.
+* \param nholes The number of rings in the holes array.
+* \return A newly allocated geometry. NULL on exception.
+* Caller is responsible for freeing with GEOSGeom_destroy().
+* \note The holes argument is an array of GEOSGeometry* objects.
+* The caller **retains ownership** of the containing array,
+* but the ownership of the pointed-to objects is transferred
+* to the returned \ref GEOSGeometry.
+* \since 3.13
+*/
+extern GEOSGeometry GEOS_DLL *GEOSGeom_createCurvePolygon(
+ GEOSGeometry* shell,
+ GEOSGeometry** holes,
+ unsigned int nholes);
+
+/**
+* Creates an empty CurvePolygon geometry.
+* \return A newly allocated CurvePolygon geometry. NULL on exception.
+* Caller is responsible for freeing with GEOSGeom_destroy().
+* \since 3.13
+*/
+extern GEOSGeometry GEOS_DLL *GEOSGeom_createEmptyCurvePolygon();
+
/**
* Create a geometry collection.
* \param type The geometry type, enumerated by \ref GEOSGeomTypes
diff --git a/capi/geos_ts_c.cpp b/capi/geos_ts_c.cpp
index 2c18d8489..4581860b6 100644
--- a/capi/geos_ts_c.cpp
+++ b/capi/geos_ts_c.cpp
@@ -31,9 +31,12 @@
#include <geos/coverage/CoverageValidator.h>
#include <geos/coverage/CoverageSimplifier.h>
#include <geos/coverage/CoverageUnion.h>
+#include <geos/geom/CircularString.h>
+#include <geos/geom/CompoundCurve.h>
#include <geos/geom/Coordinate.h>
#include <geos/geom/CoordinateSequence.h>
#include <geos/geom/Curve.h>
+#include <geos/geom/CurvePolygon.h>
#include <geos/geom/Envelope.h>
#include <geos/geom/Geometry.h>
#include <geos/geom/GeometryCollection.h>
@@ -46,6 +49,7 @@
#include <geos/geom/MultiLineString.h>
#include <geos/geom/MultiPoint.h>
#include <geos/geom/MultiPolygon.h>
+#include <geos/geom/MultiSurface.h>
#include <geos/geom/Point.h>
#include <geos/geom/Polygon.h>
#include <geos/geom/PrecisionModel.h>
@@ -2078,6 +2082,12 @@ extern "C" {
case GEOS_MULTIPOLYGON:
g = gf->createMultiPolygon(std::move(vgeoms));
break;
+ case GEOS_MULTICURVE:
+ g = gf->createMultiCurve(std::move(vgeoms));
+ break;
+ case GEOS_MULTISURFACE:
+ g = gf->createMultiSurface(std::move(vgeoms));
+ break;
default:
handle->ERROR_MESSAGE("Unsupported type request for GEOSGeom_createCollection_r");
}
@@ -2991,6 +3001,113 @@ extern "C" {
});
}
+ Geometry*
+ GEOSGeom_createCircularString_r(GEOSContextHandle_t extHandle, CoordinateSequence* cs)
+ {
+ return execute(extHandle, [&]() {
+ GEOSContextHandleInternal_t* handle = reinterpret_cast<GEOSContextHandleInternal_t*>(extHandle);
+ const GeometryFactory* gf = handle->geomFactory;
+
+ return gf->createCircularString(std::unique_ptr<CoordinateSequence>(cs)).release();
+ });
+ }
+
+ Geometry*
+ GEOSGeom_createEmptyCircularString_r(GEOSContextHandle_t extHandle)
+ {
+ return execute(extHandle, [&]() {
+ GEOSContextHandleInternal_t* handle = reinterpret_cast<GEOSContextHandleInternal_t*>(extHandle);
+ const GeometryFactory* gf = handle->geomFactory;
+
+ return gf->createCircularString(false, false).release();
+ });
+ }
+
+ Geometry*
+ GEOSGeom_createCompoundCurve_r(GEOSContextHandle_t extHandle, Geometry** geoms, unsigned int ngeoms)
+ {
+ return execute(extHandle, [&]() -> Geometry* {
+ GEOSContextHandleInternal_t* handle = reinterpret_cast<GEOSContextHandleInternal_t*>(extHandle);
+ const GeometryFactory* gf = handle->geomFactory;
+
+ bool invalid_input = false;
+ std::vector<std::unique_ptr<SimpleCurve>> geom_vec(ngeoms);
+ for (std::size_t i = 0; i < ngeoms; i++) {
+ if (SimpleCurve* c = dynamic_cast<SimpleCurve*>(geoms[i])) {
+ geom_vec[i].reset(c);
+ } else {
+ delete geoms[i];
+ invalid_input = true;
+ }
+ }
+
+ if (invalid_input) {
+ throw IllegalArgumentException("Input is not a SimpleCurve");
+ }
+
+ return gf->createCompoundCurve(std::move(geom_vec)).release();
+ });
+ }
+
+ Geometry*
+ GEOSGeom_createEmptyCompoundCurve_r(GEOSContextHandle_t extHandle)
+ {
+ return execute(extHandle, [&]() {
+ GEOSContextHandleInternal_t* handle = reinterpret_cast<GEOSContextHandleInternal_t*>(extHandle);
+ const GeometryFactory* gf = handle->geomFactory;
+
+ return gf->createCompoundCurve().release();
+ });
+ }
+
+ Geometry*
+ GEOSGeom_createCurvePolygon_r(GEOSContextHandle_t extHandle, Geometry* p_shell, Geometry** p_holes, unsigned int nholes)
+ {
+ return execute(extHandle, [&]() {
+ GEOSContextHandleInternal_t* handle = reinterpret_cast<GEOSContextHandleInternal_t*>(extHandle);
+ const GeometryFactory* gf = handle->geomFactory;
+ bool good_holes = true, good_shell = true;
+
+ std::unique_ptr<Curve> shell;
+ std::vector<std::unique_ptr<Curve>> holes(nholes);
+
+ if (Curve* c = dynamic_cast<Curve*>(p_shell)) {
+ shell.reset(c);
+ } else {
+ good_shell = false;
+ delete p_shell;
+ }
+
+ for (std::size_t i = 0; i < nholes; i++) {
+ if (Curve* c = dynamic_cast<Curve*>(p_holes[i])) {
+ holes[i].reset(c);
+ } else {
+ good_shell = false;
+ delete p_holes[i];
+ }
+ }
+
+ if (good_shell && good_holes) {
+ return gf->createCurvePolygon(std::move(shell), std::move(holes)).release();
+ } else if (!good_shell) {
+ throw IllegalArgumentException("Shell is not a Curve");
+ } else {
+ throw IllegalArgumentException("Hole is not a Curve");
+ }
+ });
+ }
+
+
+ Geometry*
+ GEOSGeom_createEmptyCurvePolygon_r(GEOSContextHandle_t extHandle)
+ {
+ return execute(extHandle, [&]() {
+ GEOSContextHandleInternal_t* handle = reinterpret_cast<GEOSContextHandleInternal_t*>(extHandle);
+ const GeometryFactory* gf = handle->geomFactory;
+ return gf->createCurvePolygon(false, false).release();
+ });
+ }
+
Geometry*
GEOSGeom_clone_r(GEOSContextHandle_t extHandle, const Geometry* g)
{
diff --git a/tests/unit/capi/GEOSGeom_createCircularStringTest.cpp b/tests/unit/capi/GEOSGeom_createCircularStringTest.cpp
new file mode 100644
index 000000000..c4b29f901
--- /dev/null
+++ b/tests/unit/capi/GEOSGeom_createCircularStringTest.cpp
@@ -0,0 +1,44 @@
+#include <tut/tut.hpp>
+#include "capi_test_utils.h"
+
+namespace tut {
+//
+// Test Group
+//
+
+struct test_geosgeom_createcircularstring_data : public capitest::utility {};
+
+typedef test_group<test_geosgeom_createcircularstring_data> group;
+typedef group::object object;
+
+group test_geosgeom_createcircularstring("capi::GEOSGeom_createCircularString");
+
+template<>
+template<>
+void object::test<1>
+()
+{
+ GEOSCoordSequence* seq = GEOSCoordSeq_create(3, 2);
+ GEOSCoordSeq_setXY(seq, 0, 1, 2);
+ GEOSCoordSeq_setXY(seq, 1, 4, 5);
+ GEOSCoordSeq_setXY(seq, 2, 9, -2);
+
+ result_ = GEOSGeom_createCircularString(seq);
+ expected_ = fromWKT("CIRCULARSTRING (1 2, 4 5, 9 -2)");
+
+ ensure_geometry_equals_identical(result_, expected_);
+}
+
+template<>
+template<>
+void object::test<2>
+()
+{
+ result_ = GEOSGeom_createEmptyCircularString();
+ ensure(GEOSisEmpty(result_));
+ ensure(!GEOSHasZ(result_));
+ ensure(!GEOSHasM(result_));
+}
+
+} // namespace tut
+
diff --git a/tests/unit/capi/GEOSGeom_createCollectionTest.cpp b/tests/unit/capi/GEOSGeom_createCollectionTest.cpp
index c0ac20ce7..93474d8cb 100644
--- a/tests/unit/capi/GEOSGeom_createCollectionTest.cpp
+++ b/tests/unit/capi/GEOSGeom_createCollectionTest.cpp
@@ -172,5 +172,38 @@ void object::test<7>
}
}
+// Create MultiCurve
+template<>
+template<>
+void object::test<8>
+()
+{
+ GEOSGeometry* geoms[2];
+ geoms[0] = fromWKT("CIRCULARSTRING (0 0, 1 1, 2 0)");
+ geoms[1] = fromWKT("LINESTRING (2 0, 3 3)");
+
+ result_ = GEOSGeom_createCollection(GEOS_MULTICURVE, geoms, 2);
+ expected_ = fromWKT("MULTICURVE (CIRCULARSTRING (0 0, 1 1, 2 0), (2 0, 3 3))");
+
+ ensure_geometry_equals_identical(result_, expected_);
+}
+
+// Create MultiSurface
+template<>
+template<>
+void object::test<9>
+()
+{
+ GEOSGeometry* geoms[2];
+ geoms[0] = fromWKT("POLYGON ((0 0, 1 0, 1 1, 0 0))");
+ geoms[1] = fromWKT("CURVEPOLYGON (CIRCULARSTRING (10 10, 20 10, 15 15, 10 10))");
+
+ result_ = GEOSGeom_createCollection(GEOS_MULTISURFACE, geoms, 2);
+ expected_ = fromWKT("MULTISURFACE (((0 0, 1 0, 1 1, 0 0)), CURVEPOLYGON (CIRCULARSTRING (10 10, 20 10, 15 15, 10 10)))");
+
+ ensure_geometry_equals_identical(result_, expected_);
+}
+
+
} // namespace tut
diff --git a/tests/unit/capi/GEOSGeom_createCompoundCurveTest.cpp b/tests/unit/capi/GEOSGeom_createCompoundCurveTest.cpp
new file mode 100644
index 000000000..ee3536f32
--- /dev/null
+++ b/tests/unit/capi/GEOSGeom_createCompoundCurveTest.cpp
@@ -0,0 +1,57 @@
+#include <tut/tut.hpp>
+#include "capi_test_utils.h"
+
+namespace tut {
+//
+// Test Group
+//
+
+struct test_geosgeom_createcompoundcurve_data : public capitest::utility {};
+
+typedef test_group<test_geosgeom_createcompoundcurve_data> group;
+typedef group::object object;
+
+group test_geosgeom_createcompoundcurve("capi::GEOSGeom_createCompoundCurve");
+
+template<>
+template<>
+void object::test<1>
+()
+{
+ GEOSGeometry* c1 = fromWKT("LINESTRING (0 0, 1 1)");
+ GEOSGeometry* c2 = fromWKT("CIRCULARSTRING (1 1, 2 0, 3 1)");
+ GEOSGeometry* curves[] = {c1, c2};
+
+ result_ = GEOSGeom_createCompoundCurve(curves, 2);
+ expected_ = fromWKT("COMPOUNDCURVE((0 0, 1 1), CIRCULARSTRING (1 1, 2 0, 3 1))");
+
+ ensure_geometry_equals_identical(result_, expected_);
+}
+
+// Make sure we take ownership of inputs even in case of failure
+template<>
+template<>
+void object::test<2>
+()
+{
+ GEOSGeometry* c1 = fromWKT("LINESTRING (0 0, 1 1)");
+ GEOSGeometry* c2 = fromWKT("POINT (13 2)");
+ GEOSGeometry* curves[] = {c1, c2};
+
+ result_ = GEOSGeom_createCompoundCurve(curves, 2);
+ ensure(result_ == nullptr);
+}
+
+template<>
+template<>
+void object::test<3>
+()
+{
+ result_ = GEOSGeom_createEmptyCompoundCurve();
+ ensure(GEOSisEmpty(result_));
+ ensure(!GEOSHasZ(result_));
+ ensure(!GEOSHasM(result_));
+}
+
+} // namespace tut
+
diff --git a/tests/unit/capi/GEOSGeom_createCurvePolygonTest.cpp b/tests/unit/capi/GEOSGeom_createCurvePolygonTest.cpp
new file mode 100644
index 000000000..5b9a8ff5a
--- /dev/null
+++ b/tests/unit/capi/GEOSGeom_createCurvePolygonTest.cpp
@@ -0,0 +1,58 @@
+#include <tut/tut.hpp>
+#include "capi_test_utils.h"
+
+namespace tut {
+//
+// Test Group
+//
+
+struct test_geosgeom_createcurvepolygon_data : public capitest::utility {};
+
+typedef test_group<test_geosgeom_createcurvepolygon_data> group;
+typedef group::object object;
+
+group test_geosgeom_createcurvepolygon("capi::GEOSGeom_createCurvePolygon");
+
+template<>
+template<>
+void object::test<1>
+()
+{
+ GEOSGeometry* shell = fromWKT("CIRCULARSTRING(0 0, 4 0, 4 4, 0 4, 0 0)");
+ GEOSGeometry* hole = fromWKT("LINESTRING (1 1, 3 3, 3 1, 1 1)");
+ GEOSGeometry* holes[] = {hole};
+
+ result_ = GEOSGeom_createCurvePolygon(shell, holes, 1);
+ expected_ = fromWKT("CURVEPOLYGON( CIRCULARSTRING(0 0, 4 0, 4 4, 0 4, 0 0), (1 1, 3 3, 3 1, 1 1) )");
+
+ ensure_geometry_equals_identical(result_, expected_);
+}
+
+// Ownership transferred on error
+template<>
+template<>
+void object::test<2>
+()
+{
+ GEOSGeometry* shell = fromWKT("CIRCULARSTRING(0 0, 4 0, 4 4, 0 4, 0 0)");
+ GEOSGeometry* hole1 = fromWKT("POINT (3 3)");
+ GEOSGeometry* hole2 = fromWKT("LINESTRING (1 1, 3 3, 3 1, 1 1)");
+ GEOSGeometry* holes[] = {hole1, hole2};
+
+ result_ = GEOSGeom_createCurvePolygon(shell, holes, 2);
+ ensure(result_ == nullptr);
+}
+
+template<>
+template<>
+void object::test<3>
+()
+{
+ result_ = GEOSGeom_createEmptyCurvePolygon();
+ ensure(GEOSisEmpty(result_));
+ ensure(!GEOSHasZ(result_));
+ ensure(!GEOSHasM(result_));
+}
+
+} // namespace tut
+
-----------------------------------------------------------------------
Summary of changes:
capi/geos_c.cpp | 36 +++++++
capi/geos_c.h.in | 92 ++++++++++++++++
capi/geos_ts_c.cpp | 117 +++++++++++++++++++++
.../capi/GEOSGeom_createCircularStringTest.cpp | 44 ++++++++
tests/unit/capi/GEOSGeom_createCollectionTest.cpp | 33 ++++++
.../unit/capi/GEOSGeom_createCompoundCurveTest.cpp | 57 ++++++++++
.../unit/capi/GEOSGeom_createCurvePolygonTest.cpp | 58 ++++++++++
7 files changed, 437 insertions(+)
create mode 100644 tests/unit/capi/GEOSGeom_createCircularStringTest.cpp
create mode 100644 tests/unit/capi/GEOSGeom_createCompoundCurveTest.cpp
create mode 100644 tests/unit/capi/GEOSGeom_createCurvePolygonTest.cpp
hooks/post-receive
--
GEOS
More information about the geos-commits
mailing list