[geos-commits] [SCM] GEOS branch main updated. 0f150b39c332b89db633e88c83a7e27dc3b13c1b

git at osgeo.org git at osgeo.org
Sat Mar 7 05:50:47 PST 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  0f150b39c332b89db633e88c83a7e27dc3b13c1b (commit)
      from  99494637e83a22284fadb24e527c3eedb1250e1b (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 0f150b39c332b89db633e88c83a7e27dc3b13c1b
Author: Daniel Baston <dbaston at gmail.com>
Date:   Sat Mar 7 08:50:24 2026 -0500

    C API: Add some comments/tests on Z/M handling (#1389)

diff --git a/capi/geos_c.h.in b/capi/geos_c.h.in
index b31a4290a..8c85598e4 100644
--- a/capi/geos_c.h.in
+++ b/capi/geos_c.h.in
@@ -3290,7 +3290,8 @@ extern char GEOS_DLL GEOSisEmpty(const GEOSGeometry* g);
 /**
 * Tests whether the input geometry is a ring. Rings are
 * linestrings, without self-intersections,
-* with start and end point being identical.
+* with start and end point having the same XY values.
+* Z and M values are not considered.
 * \param g The geometry to test
 * \return 1 on true, 0 on false, 2 on exception
 * \since 2.2
@@ -3317,7 +3318,8 @@ extern char GEOS_DLL GEOSHasM(const GEOSGeometry* g);
 /**
 * Tests whether the input geometry is closed.
 * A closed geometry is a linestring or multilinestring
-* with the start and end points being the same.
+* with the start and end points having the same XY values.
+* Z and M values are not considered.
 * \param g The geometry to test
 * \return 1 on true, 0 on false, 2 on exception
 * \since 3.3
@@ -3363,6 +3365,8 @@ extern void GEOS_DLL GEOSGeom_setUserData(GEOSGeometry* g, void* userData);
 * - Polygon shell rings are oriented CW, and holes CCW
 * - Collection elements are sorted by their first coordinate
 *
+* Coordinate Z and M values are not modified during normalization.
+*
 * Use before calling \ref GEOSEqualsExact to avoid false "not equal" results.
 * \param g Input geometry
 * \return 0 on success or -1 on exception
@@ -3373,6 +3377,7 @@ extern int GEOS_DLL GEOSNormalize(GEOSGeometry* g);
 /**
 * Enforce a ring orientation on all polygonal elements in the input geometry.
 * Non-polygonal geometries will not be modified.
+* Coordinate Z and M values are not modified.
 *
 * \param g Input geometry
 * \param exteriorCW if 1, exterior rings will be clockwise and interior rings
@@ -3395,6 +3400,7 @@ and geometric quality.
 /**
 * Tests whether the input geometry is "simple". Mostly relevant for
 * linestrings. A "simple" linestring has no self-intersections.
+* Z and M values are not considered.
 * \param g The geometry to test
 * \return 1 on true, 0 on false, 2 on exception
 * \since 2.2
@@ -3428,6 +3434,8 @@ extern char GEOS_DLL GEOSisSimpleDetail(
 *   contained within exterior rings.
 * - Multi-polygon components may not touch or overlap.
 *
+* Z and M values are not considered.
+*
 * \param g The geometry to test
 * \return 1 on true, 0 on false, 2 on exception
 * \see geos::operation::valid::isValidOp
@@ -3560,7 +3568,7 @@ extern int GEOS_DLL GEOSMakeValidParams_setKeepCollapsed(
 extern int GEOS_DLL GEOSMinimumClearance(const GEOSGeometry* g, double* d);
 
 /**
-* Returns a LineString whose endpoints define the minimum clearance of a geometry.
+* Returns a 2D LineString whose endpoints define the minimum clearance of a geometry.
 * If the geometry has no minimum clearance, an empty LineString will be returned.
 *
 * \param g the input geometry
@@ -3581,6 +3589,9 @@ extern GEOSGeometry GEOS_DLL *GEOSMinimumClearanceLine(const GEOSGeometry* g);
 * result in an invalid geometry being returned. Be sure
 * to check and repair validity.
 *
+* Z and M coordinate values are preserved but are not considered when 
+* determining if a point is repeated.
+*
 * \return A geometry with all points within the tolerance of each other removed.
 * \param g The geometry to filter
 * \param tolerance Remove all points within this distance of each other. Use 0.0 to remove only exactly repeated points.
@@ -3614,6 +3625,7 @@ extern int GEOS_DLL GEOSArea(
 
 /**
 * Calculate the length of a geometry.
+* Length is calculated in the XY plane; Z and M values are ignored.
 * \param[in] g Input geometry
 * \param[out] length Pointer to be filled in with length result
 * \return 1 on success, 0 on exception.
@@ -3626,6 +3638,7 @@ extern int GEOS_DLL GEOSLength(
 /**
 * Calculate the length of a LineString.
 * Only works for LineString inputs, returns exception otherwise.
+* Length is calculated in the XY plane; Z and M values are ignored.
 *
 * \param[in] g Input geometry
 * \param[out] length Pointer to be filled in with length result
@@ -3647,6 +3660,8 @@ extern int GEOS_DLL GEOSGeomGetLength(
 
 /**
 * Calculate the distance between two geometries.
+* Distance is calculated in the XY plane; Z and M values are ignored.
+*
 * \param[in] g1 Input geometry
 * \param[in] g2 Input geometry
 * \param[out] dist Pointer to be filled in with distance result. Positive
@@ -3662,6 +3677,8 @@ extern int GEOS_DLL GEOSDistance(
 /**
 * Test whether the distance between two geometries is
 * within the given dist.
+* Distance is calculated in the XY plane; Z and M values are ignored.
+*
 * \param g1 Input geometry
 * \param g2 Input geometry
 * \param dist The max distance
@@ -3695,6 +3712,7 @@ extern int GEOS_DLL GEOSDistanceIndexed(
 /**
 * The closest points of the two geometries.
 * The first point comes from g1 geometry and the second point comes from g2.
+* Returned points will not have Z or M values.
 *
 * \param[in] g1 Input geometry
 * \param[in] g2 Input geometry
@@ -4301,6 +4319,8 @@ extern void GEOS_DLL GEOSClusterInfo_destroy(GEOSClusterInfo* clusters);
 
 /**
 * Buffer a geometry.
+* The coordinates of the constructed geometry will not have Z or M values.
+* 
 * \param g The input geometry to be buffered.
 * \param width The distance by which to expand the geometry (or contract)
 *        if the value is negative.
@@ -4413,6 +4433,8 @@ extern GEOSGeometry GEOS_DLL *GEOSBufferWithParams(
 
 /**
 * Generate a buffer using the provided style parameters.
+* The coordinates of the constructed geometry will not have Z or M values.
+* 
 * \param g The geometry to buffer
 * \param width Width of the buffer
 * \param quadsegs Number of segments per quadrant
@@ -4434,7 +4456,8 @@ extern GEOSGeometry GEOS_DLL *GEOSBufferWithStyle(
 
 /**
 * Generates offset curve line(s) for a geometry.
-* Handles all geometry types as input.
+* Handles all non-curved geometry types as input.
+* The coordinates of the constructed geometry will not have Z or M values.
 *
 * - For a LineString the result is a LineString.
 * - For a Point the result is an empty LineString.
diff --git a/tests/unit/capi/GEOSBufferTest.cpp b/tests/unit/capi/GEOSBufferTest.cpp
index 702cc8dff..f8a555bf3 100644
--- a/tests/unit/capi/GEOSBufferTest.cpp
+++ b/tests/unit/capi/GEOSBufferTest.cpp
@@ -472,4 +472,19 @@ void object::test<26>()
     ensure(result_ == nullptr);
 }
 
+template<>
+template<>
+void object::test<27>()
+{
+    set_test_name("buffer of XYZM geometry is XY");
+
+    input_ = fromWKT("POINT ZM (1 2 3 4)");
+    ensure(input_ != nullptr);
+
+    result_ = GEOSBuffer(input_, 1, 8);
+    ensure(result_ != nullptr);
+    ensure(!GEOSHasZ(result_));
+    ensure(!GEOSHasM(result_));
+}
+
 } // namespace tut
diff --git a/tests/unit/capi/GEOSDistanceTest.cpp b/tests/unit/capi/GEOSDistanceTest.cpp
index 152aade8b..42a895a62 100644
--- a/tests/unit/capi/GEOSDistanceTest.cpp
+++ b/tests/unit/capi/GEOSDistanceTest.cpp
@@ -182,5 +182,22 @@ void object::test<6>()
     ensure_equals("curved geometry not supported", ret, 0);
 }
 
+template<>
+template<>
+void object::test<7>()
+{
+    set_test_name("distance calculated in 2D only");
+
+    geom1_ = fromWKT("POINT ZM (0 0 1 2)");
+    geom2_ = fromWKT("POINT ZM (3 4 7 9)");
+
+    ensure(geom1_);
+    ensure(geom2_);
+
+    double dist;
+    ensure_equals(GEOSDistance(geom1_, geom2_, &dist), 1);
+    ensure_equals(dist, 5.0);
+}
+
 } // namespace tut
 
diff --git a/tests/unit/capi/GEOSDistanceWithinTest.cpp b/tests/unit/capi/GEOSDistanceWithinTest.cpp
index e64c14b63..074c1b59b 100644
--- a/tests/unit/capi/GEOSDistanceWithinTest.cpp
+++ b/tests/unit/capi/GEOSDistanceWithinTest.cpp
@@ -422,6 +422,20 @@ void object::test<32>()
     ensure_equals("curved geometry not supported", ret, 2);
 }
 
+template<>
+template<>
+void object::test<33>()
+{
+    set_test_name("distance calculated in 2D only");
+
+    geom1_ = fromWKT("POINT ZM (0 0 1 2)");
+    geom2_ = fromWKT("POINT ZM (3 4 7 9)");
+
+    ensure(geom1_);
+    ensure(geom2_);
+
+    ensure_equals(GEOSDistanceWithin(geom1_, geom2_, 5.0000001), 1);
+}
 
 
 } // namespace tut
diff --git a/tests/unit/capi/GEOSLengthTest.cpp b/tests/unit/capi/GEOSLengthTest.cpp
index 7be71de71..5e89a0ede 100644
--- a/tests/unit/capi/GEOSLengthTest.cpp
+++ b/tests/unit/capi/GEOSLengthTest.cpp
@@ -72,5 +72,21 @@ void object::test<4>()
     ensure_equals(length, geos::MATH_PI);
 }
 
+template<>
+template<>
+void object::test<5>()
+{
+    set_test_name("length calculated in 2D only");
+
+    input_ = fromWKT("LINESTRING (0 0 0 0, 1 0 7 9)");
+    ensure(input_ != nullptr);
+
+    double length = -1;
+    int ret = GEOSLength(input_, &length);
+    ensure_equals(ret, 1);
+    ensure_equals(length, 1);
+}
+
+
 } // namespace tut
 
diff --git a/tests/unit/capi/GEOSLineStringTest.cpp b/tests/unit/capi/GEOSLineStringTest.cpp
index ca795de60..4beae5439 100644
--- a/tests/unit/capi/GEOSLineStringTest.cpp
+++ b/tests/unit/capi/GEOSLineStringTest.cpp
@@ -168,4 +168,20 @@ void object::test<5>
     ensure(length > 0.0);
 }
 
+template<>
+template<>
+void object::test<6>
+()
+{
+    set_test_name("length calculated in 2D only");
+
+    input_ = fromWKT("LINESTRING (0 0 0 0, 1 0 7 9)");
+    ensure(input_ != nullptr);
+
+    double length = -1;
+    int ret = GEOSGeomGetLength(input_, &length);
+    ensure_equals(ret, 1);
+    ensure_equals(length, 1);
+}
+
 } // namespace tut
diff --git a/tests/unit/capi/GEOSMakeValidTest.cpp b/tests/unit/capi/GEOSMakeValidTest.cpp
index c6531d5b8..0cad2e552 100644
--- a/tests/unit/capi/GEOSMakeValidTest.cpp
+++ b/tests/unit/capi/GEOSMakeValidTest.cpp
@@ -102,4 +102,31 @@ void object::test<5>()
     ensure("curved geometry not supported", result_ == nullptr);
 }
 
+template<>
+template<>
+void object::test<6>()
+{
+    set_test_name("Z/M values preserved for valid input");
+
+    input_ = fromWKT("POLYGON ZM ((0 0 1 2, 1 0 2 3, 1 1 3 4, 0 0 1 2))");
+    ensure(input_);
+
+    result_ = GEOSMakeValid(input_);
+    ensure_geometry_equals_identical(result_, input_);
+}
+
+template<>
+template<>
+void object::test<7>()
+{
+    set_test_name("Z/M values are preserved/interpolated for self-intersecting input");
+
+    input_ = fromWKT("POLYGON ZM ((0 0 1 2, 1 0 2 3, 0 1 3 4, 1 1 4 5, 0 0 1 2))");
+    ensure(input_);
+
+    result_ = GEOSMakeValid(input_);
+    expected_ = fromWKT("MULTIPOLYGON ZM (((0 0 1 2, 0.5 0.5 2.5 3.5, 1 0 2 3, 0 0 1 2)), ((1 1 4 5, 0.5 0.5 2.5 3.5, 0 1 3 4, 1 1 4 5)))");
+    ensure_geometry_equals_identical(result_, expected_);
+}
+
 } // namespace tut
diff --git a/tests/unit/capi/GEOSMinimumClearanceTest.cpp b/tests/unit/capi/GEOSMinimumClearanceTest.cpp
index 064763986..49fca2637 100644
--- a/tests/unit/capi/GEOSMinimumClearanceTest.cpp
+++ b/tests/unit/capi/GEOSMinimumClearanceTest.cpp
@@ -126,4 +126,21 @@ void object::test<6>
     ensure_equals(GEOSMinimumClearance(input_, &d), 2);
 }
 
+template<>
+template<>
+void object::test<7>()
+{
+    set_test_name("2D LineString returned for 4D inputs");
+
+    input_ = fromWKT("POLYGON ZM ((0 0 1 2, 2 0 2 3, 2 1 3 4, 1 0.1 4 5, 0 1 5 6, 0 0 1 2))");
+    result_ = GEOSMinimumClearanceLine(input_);
+
+    ensure(result_ != nullptr);
+    ensure(!GEOSHasZ(result_));
+    ensure(!GEOSHasM(result_));
+
+    expected_ = fromWKT("LINESTRING (1 0.1, 1 0)");
+    ensure_geometry_equals(result_, expected_);
+}
+
 } // namespace tut
diff --git a/tests/unit/capi/GEOSNearestPointsTest.cpp b/tests/unit/capi/GEOSNearestPointsTest.cpp
index c1caa1887..fb7581751 100644
--- a/tests/unit/capi/GEOSNearestPointsTest.cpp
+++ b/tests/unit/capi/GEOSNearestPointsTest.cpp
@@ -139,5 +139,25 @@ void object::test<6>
     );
 }
 
+template<>
+template<>
+void object::test<7>()
+{
+    set_test_name("2D points returned for 4D inputs");
+
+    geom1_ = fromWKT("POINT ZM (0 0 1 2)");
+    geom2_ = fromWKT("POINT ZM (3 4 7 9)");
+
+    ensure(geom1_);
+    ensure(geom2_);
+
+    GEOSCoordSequence* coords = GEOSNearestPoints(geom1_, geom2_);
+    ensure(coords);
+    ensure(!GEOSCoordSeq_hasM(coords));
+    ensure(!GEOSCoordSeq_hasZ(coords));
+
+    GEOSCoordSeq_destroy(coords);
+}
+
 } // namespace tut
 
diff --git a/tests/unit/capi/GEOSOffsetCurveTest.cpp b/tests/unit/capi/GEOSOffsetCurveTest.cpp
index a979155b8..242d18853 100644
--- a/tests/unit/capi/GEOSOffsetCurveTest.cpp
+++ b/tests/unit/capi/GEOSOffsetCurveTest.cpp
@@ -270,5 +270,24 @@ void object::test<13>()
     ensure("curved geometries not supported", result_ == nullptr);
 }
 
+template<>
+template<>
+void object::test<14>()
+{
+    set_test_name("offset of XYZM geometry is XY");
+
+    input_ = fromWKT("LINESTRING ZM (0 0 3 5, 10 0 7 8)");
+    ensure(input_);
+
+    result_ = GEOSOffsetCurve(input_, 2, 0, GEOSBUF_JOIN_ROUND, 2);
+
+    ensure(result_);
+    ensure(!GEOSHasZ(result_));
+    ensure(!GEOSHasM(result_));
+
+    expected_ = fromWKT("LINESTRING (0 2, 10 2)");
+    ensure_geometry_equals(result_, expected_);
+}
+
 } // namespace tut
 
diff --git a/tests/unit/capi/GEOSOrientPolygonsTest.cpp b/tests/unit/capi/GEOSOrientPolygonsTest.cpp
index a82955911..10cbcdbe8 100644
--- a/tests/unit/capi/GEOSOrientPolygonsTest.cpp
+++ b/tests/unit/capi/GEOSOrientPolygonsTest.cpp
@@ -95,5 +95,20 @@ void object::test<6>()
     ensure_equals("curved geometries not supported", ret, -1);
 }
 
+template<>
+template<>
+void object::test<7>()
+{
+    set_test_name("Z/M values preserved");
+
+    geom1_ = GEOSGeomFromWKT("POLYGON ZM ((0 0 5 7, 10 0 6 8, 10 10 7 9, 0 10 8 10, 0 0 5 7), (1 1 1 3, 2 1 2 4, 2 2 3 5, 1 2 4 6, 1 1 1 3))");
+
+    ensure_equals(GEOSOrientPolygons(geom1_, 0), 0);
+    ensure_equals(toWKT(geom1_), "POLYGON ZM ((0 0 5 7, 10 0 6 8, 10 10 7 9, 0 10 8 10, 0 0 5 7), (1 1 1 3, 1 2 4 6, 2 2 3 5, 2 1 2 4, 1 1 1 3))");
+
+    ensure_equals(GEOSOrientPolygons(geom1_, 1), 0);
+    ensure_equals(toWKT(geom1_), "POLYGON ZM ((0 0 5 7, 0 10 8 10, 10 10 7 9, 10 0 6 8, 0 0 5 7), (1 1 1 3, 2 1 2 4, 2 2 3 5, 1 2 4 6, 1 1 1 3))");
+}
+
 } // namespace tut
 
diff --git a/tests/unit/capi/GEOSRemoveRepeatedPointsTest.cpp b/tests/unit/capi/GEOSRemoveRepeatedPointsTest.cpp
index c1a53bb32..2ce17f6a1 100644
--- a/tests/unit/capi/GEOSRemoveRepeatedPointsTest.cpp
+++ b/tests/unit/capi/GEOSRemoveRepeatedPointsTest.cpp
@@ -60,4 +60,19 @@ void object::test<3>()
     ensure("curved geometry not supported", result_ == nullptr);
 }
 
+template<>
+template<>
+void object::test<4>()
+{
+    set_test_name("Z/M values not considered");
+
+    input_ = fromWKT("LINESTRING ZM (0 0 0 0, 1 3 5 6, 1 3 6 7, 2 6 7 4)");
+    ensure(input_);
+
+    expected_ = fromWKT("LINESTRING ZM (0 0 0 0, 1 3 5 6, 2 6 7 4)");
+
+    result_ = GEOSRemoveRepeatedPoints(input_, 0);
+    ensure_geometry_equals_identical(result_, expected_);
+}
+
 } // namespace tut

-----------------------------------------------------------------------

Summary of changes:
 capi/geos_c.h.in                                 | 31 +++++++++++++++++++++---
 tests/unit/capi/GEOSBufferTest.cpp               | 15 ++++++++++++
 tests/unit/capi/GEOSDistanceTest.cpp             | 17 +++++++++++++
 tests/unit/capi/GEOSDistanceWithinTest.cpp       | 14 +++++++++++
 tests/unit/capi/GEOSLengthTest.cpp               | 16 ++++++++++++
 tests/unit/capi/GEOSLineStringTest.cpp           | 16 ++++++++++++
 tests/unit/capi/GEOSMakeValidTest.cpp            | 27 +++++++++++++++++++++
 tests/unit/capi/GEOSMinimumClearanceTest.cpp     | 17 +++++++++++++
 tests/unit/capi/GEOSNearestPointsTest.cpp        | 20 +++++++++++++++
 tests/unit/capi/GEOSOffsetCurveTest.cpp          | 19 +++++++++++++++
 tests/unit/capi/GEOSOrientPolygonsTest.cpp       | 15 ++++++++++++
 tests/unit/capi/GEOSRemoveRepeatedPointsTest.cpp | 15 ++++++++++++
 12 files changed, 218 insertions(+), 4 deletions(-)


hooks/post-receive
-- 
GEOS


More information about the geos-commits mailing list