[geos-commits] [SCM] GEOS branch main updated. b53afe675cb21b7f2689eae72f6dd3b10bb87d78

git at osgeo.org git at osgeo.org
Mon Apr 17 13:19:25 PDT 2023


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  b53afe675cb21b7f2689eae72f6dd3b10bb87d78 (commit)
       via  3cab6cb2a8c5a5243a3fa1a8775322d6e290c6a4 (commit)
      from  93540f4c27b6eff81e51203f52b585a7872f884b (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 b53afe675cb21b7f2689eae72f6dd3b10bb87d78
Author: Martin Davis <mtnclimb at gmail.com>
Date:   Mon Apr 17 13:18:46 2023 -0700

    Add unit test for GEOSCoverageSimplifyVW for inner

diff --git a/tests/unit/capi/GEOSCoverageSimplifyTest.cpp b/tests/unit/capi/GEOSCoverageSimplifyTest.cpp
index 8a11cd07a..18c65bd9b 100644
--- a/tests/unit/capi/GEOSCoverageSimplifyTest.cpp
+++ b/tests/unit/capi/GEOSCoverageSimplifyTest.cpp
@@ -1,5 +1,5 @@
 //
-// Test Suite for C-API GEOSCoverageUnion
+// Test Suite for C-API GEOSCoverageSimplifyVW
 
 #include <tut/tut.hpp>
 // geos
@@ -38,7 +38,7 @@ group test_capicoveragesimplify_group("capi::GEOSCoverageSimplify");
 // Test Cases
 //
 
-
+// GEOSCoverageSimplifyVW - all
 template<>
 template<> void object::test<1>
 ()
@@ -61,7 +61,25 @@ template<> void object::test<1>
     ensure_geometry_equals(result_, expected_, 0.1);
 }
 
+// GEOSCoverageSimplifyVW - inner
+template<>
+template<> void object::test<2>
+()
+{
+    const char* inputWKT = "GEOMETRYCOLLECTION( POLYGON ((1 9, 5 9.1, 9 9, 9 5, 5 5.1, 1 5, 1 9)), POLYGON ((1 1, 1 5, 5 5.1, 9 5, 9 1, 1 1)))";
 
+    input_ = fromWKT(inputWKT);
+    result_ = GEOSCoverageSimplifyVW(input_, 1.0, 1);
 
-} // namespace tut
+    ensure( result_ != nullptr );
+    ensure( GEOSGeomTypeId(result_) == GEOS_GEOMETRYCOLLECTION );
 
+    const char* expectedWKT = "GEOMETRYCOLLECTION(POLYGON ((9 5, 1 5, 1 9, 5 9.1, 9 9, 9 5)), POLYGON ((9 5, 1 5, 1 1, 9 1, 9 5)))";
+
+    expected_ = fromWKT(expectedWKT);
+    ensure_geometry_equals(result_, expected_, 0.1);
+}
+
+
+
+} // namespace tut

commit 3cab6cb2a8c5a5243a3fa1a8775322d6e290c6a4
Author: Paul Ramsey <pramsey at cleverelephant.ca>
Date:   Wed Apr 12 19:15:03 2023 -0700

    CAPI: GEOSCoverageIsValid, GEOSCoverageSimplifyVW GH-867
    Expose the CoverateSimplifier and CoverageValidator via the CAPI

diff --git a/NEWS.md b/NEWS.md
index 5cdf51ad1..42484dfc8 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -3,7 +3,7 @@ xxxx-xx-xx
 
 - New things:
   - C++14 is now required.
-  - Polygonal coverage operations: CoverageValidator, CoveragePolygonValidator,
+  - Polygonal coverages: CoverageValidator, CoveragePolygonValidator,
     CoverageGapFinder, CoverageUnion (JTS-900, Martin Davis & Paul Ramsey)
   - Support reading and writing M values through WKB and WKT readers/writers
     (GH-721, Dan Baston)
@@ -19,6 +19,8 @@ xxxx-xx-xx
   - CAPI: GEOSConcaveHullByLength (GH-849, Martin Davis)
   - CAPI: GEOSGeomGetM (GH-864, Mike Taves)
   - Voronoi: Add option to create diagram in order consistent with inputs (GH-781, Dan Baston)
+  - Polygonal coverages: CoverageSimplifier (JTS-911, Martin Davis)
+  - CAPI: GEOSCoverageIsValid, GEOSCoverageSimplifyVW (GH-867, Paul Ramsey)
 
 - Fixes/Improvements:
   - WKTReader: Fix parsing of Z and M flags in WKTReader (#676 and GH-669, Dan Baston)
diff --git a/capi/geos_c.cpp b/capi/geos_c.cpp
index f67db11c2..5757a6f0b 100644
--- a/capi/geos_c.cpp
+++ b/capi/geos_c.cpp
@@ -1804,4 +1804,20 @@ extern "C" {
                                          cx, cy);
     }
 
+    int
+    GEOSCoverageIsValid(
+        const Geometry* input,
+        double gapWidth,
+        Geometry** invalidEdges)
+    {
+        return GEOSCoverageIsValid_r(handle, input, gapWidth, invalidEdges);
+    }
+
+    Geometry*
+    GEOSCoverageSimplifyVW(const Geometry* input, double tolerance, int preserveBoundary)
+    {
+        return GEOSCoverageSimplifyVW_r(handle, input, tolerance, preserveBoundary);
+    }
+
+
 } /* extern "C" */
diff --git a/capi/geos_c.h.in b/capi/geos_c.h.in
index bc583020e..faac0e8a1 100644
--- a/capi/geos_c.h.in
+++ b/capi/geos_c.h.in
@@ -757,6 +757,24 @@ extern void GEOS_DLL GEOSGeom_destroy_r(
     GEOSContextHandle_t handle,
     GEOSGeometry* g);
 
+/* ========= Coverages ========= */
+
+/** \see GEOSCoverageIsValid */
+int
+GEOSCoverageIsValid_r(
+    GEOSContextHandle_t extHandle,
+    const GEOSGeometry* input,
+    double gapWidth,
+    GEOSGeometry** output);
+
+/** \see GEOSCoverageSimplify */
+extern GEOSGeometry GEOS_DLL *
+GEOSCoverageSimplifyVW_r(
+    GEOSContextHandle_t extHandle,
+    const GEOSGeometry* input,
+    double tolerance,
+    int preserveBoundary);
+
 /* ========= Topology Operations ========= */
 
 /** \see GEOSEnvelope */
@@ -3719,6 +3737,74 @@ extern GEOSGeometry GEOS_DLL *GEOSOffsetCurve(const GEOSGeometry* g,
 
 ///@}
 
+
+/* ====================================================================== */
+/** @name Coverages
+* Functions to work with coverages represented by lists of polygons
+* that exactly share edge geometry.
+*/
+///@{
+
+/**
+* Analyze a coverage (represented as a collection of polygonal geometry
+* with exactly matching edge geometry) to find places where the
+* assumption of exactly matching edges is not met.
+*
+* \param input The polygonal coverage to access,
+*        stored in a geometry collection. All members must be POLYGON
+*        or MULTIPOLYGON.
+* \param gapWidth The maximum width of gaps to detect.
+* \param invalidEdges When there are invalidities in the coverage,
+*        this pointer
+*        will be set with a geometry collection of the same length as
+*        the input, with a MULTILINESTRING of the error edges for each
+*        invalid polygon, or an EMPTY where the polygon is a valid
+*        participant in the coverage. Pass NULL if you do not want
+*        the invalid edges returned.
+* \return A value of 1 for a valid coverage, 0 for invalid and 2 for
+*         an exception or error. Invalidity includes polygons that overlap,
+*         that have gaps smaller than the gapWidth, or non-polygonal
+*         entries in the input collection.
+*
+* \since 3.12
+*/
+extern int GEOSCoverageIsValid(
+    const GEOSGeometry* input,
+    double gapWidth,
+    GEOSGeometry** invalidEdges);
+
+/**
+* Operates on a coverage (represented as a list of polygonal geometry
+* with exactly matching edge geometry) to apply a Visvalingam–Whyatt
+* simplification to the edges, reducing complexity in proportion with
+* the provided tolerance, while retaining a valid coverage (no edges
+* will cross or touch after the simplification).
+* Geometries never disappear, but they may be simplified down to just
+* a triangle. Also, some invalid geoms (such as Polygons which have too
+* few non-repeated points) will be returned unchanged.
+* If the input dataset is not a valid coverage due to overlaps,
+* it will still be simplified, but invalid topology such as crossing
+* edges will still be invalid.
+*
+* \param input The polygonal coverage to access,
+*        stored in a geometry collection. All members must be POLYGON
+*        or MULTIPOLYGON.
+* \param tolerance A tolerance parameter in linear units.
+* \param preserveBoundary Use 1 to preserve the outside edges
+*        of the coverage without simplification,
+*        0 to allow them to be simplified.
+* \return A collection containing the simplified geometries, or null
+*         on error.
+*
+* \since 3.12
+*/
+extern GEOSGeometry GEOS_DLL * GEOSCoverageSimplifyVW(
+    const GEOSGeometry* input,
+    double tolerance,
+    int preserveBoundary);
+
+///@}
+
 /* ========== Construction Operations ========== */
 /** @name Geometric Constructions
 * Functions for computing geometric constructions.
diff --git a/capi/geos_ts_c.cpp b/capi/geos_ts_c.cpp
index facefb9e3..fdf987f2f 100644
--- a/capi/geos_ts_c.cpp
+++ b/capi/geos_ts_c.cpp
@@ -27,6 +27,8 @@
 #include <geos/algorithm/distance/DiscreteFrechetDistance.h>
 #include <geos/algorithm/hull/ConcaveHull.h>
 #include <geos/algorithm/hull/ConcaveHullOfPolygons.h>
+#include <geos/coverage/CoverageValidator.h>
+#include <geos/coverage/CoverageSimplifier.h>
 #include <geos/geom/Coordinate.h>
 #include <geos/geom/CoordinateSequence.h>
 #include <geos/geom/Envelope.h>
@@ -4063,4 +4065,83 @@ extern "C" {
         });
     }
 
+    int
+    GEOSCoverageIsValid_r(GEOSContextHandle_t extHandle,
+        const Geometry* input,
+        double gapWidth,
+        Geometry** invalidEdges)
+    {
+        using geos::coverage::CoverageValidator;
+
+        return execute(extHandle, 2, [&]() {
+            const GeometryCollection* col = dynamic_cast<const GeometryCollection*>(input);
+            if (!col)
+                throw geos::util::IllegalArgumentException("input is not a collection");
+
+            // Initialize to nullptr
+            if (invalidEdges) *invalidEdges = nullptr;
+
+            std::vector<const Geometry*> coverage;
+            for (const auto& g : *col) {
+                coverage.push_back(g.get());
+            }
+
+            CoverageValidator cov(coverage);
+            cov.setGapWidth(gapWidth);
+            std::vector<std::unique_ptr<Geometry>> invalid = cov.validate();
+            bool hasInvalid = CoverageValidator::hasInvalidResult(invalid);
+
+            if (invalidEdges && hasInvalid) {
+                const GeometryFactory* gf = input->getFactory();
+                for (auto& g : invalid) {
+                    // Replace nullptr with 'MULTILINESTRING EMPTY'
+                    if (g == nullptr) {
+                        auto empty = gf->createEmpty(GEOS_MULTILINESTRING);
+                        g.reset(empty.release());
+                    }
+                }
+                auto r = gf->createGeometryCollection(std::move(invalid));
+                *invalidEdges = r.release();
+            }
+
+            return hasInvalid ? 0 : 1;
+        });
+    }
+
+    Geometry*
+    GEOSCoverageSimplifyVW_r(GEOSContextHandle_t extHandle,
+        const Geometry* input,
+        double tolerance,
+        int preserveBoundary)
+    {
+        using geos::coverage::CoverageSimplifier;
+
+        return execute(extHandle, [&]() -> Geometry* {
+            const GeometryCollection* col = dynamic_cast<const GeometryCollection*>(input);
+            if (!col)
+                return nullptr;
+
+            std::vector<const Geometry*> coverage;
+            for (const auto& g : *col) {
+                coverage.push_back(g.get());
+            }
+            CoverageSimplifier cov(coverage);
+            std::vector<std::unique_ptr<Geometry>> simple;
+            if (preserveBoundary == 1) {
+                simple = cov.simplifyInner(tolerance);
+            }
+            else if (preserveBoundary == 0) {
+                simple = cov.simplify(tolerance);
+            }
+            else return nullptr;
+
+            const GeometryFactory* gf = input->getFactory();
+            std::unique_ptr<Geometry> r = gf->createGeometryCollection(std::move(simple));
+            return r.release();
+        });
+    }
+
+
+
+
 } /* extern "C" */
diff --git a/tests/unit/capi/GEOSCoverageSimplifyTest.cpp b/tests/unit/capi/GEOSCoverageSimplifyTest.cpp
new file mode 100644
index 000000000..8a11cd07a
--- /dev/null
+++ b/tests/unit/capi/GEOSCoverageSimplifyTest.cpp
@@ -0,0 +1,67 @@
+//
+// Test Suite for C-API GEOSCoverageUnion
+
+#include <tut/tut.hpp>
+// geos
+#include <geos_c.h>
+// std
+#include <cstdarg>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+#include "capi_test_utils.h"
+
+namespace tut {
+//
+// Test Group
+//
+
+// Common data used in test cases.
+struct test_capicoveragesimplify_data : public capitest::utility {
+
+    test_capicoveragesimplify_data() {
+    }
+
+    ~test_capicoveragesimplify_data() {
+    }
+
+};
+
+
+typedef test_group<test_capicoveragesimplify_data> group;
+typedef group::object object;
+
+group test_capicoveragesimplify_group("capi::GEOSCoverageSimplify");
+
+//
+// Test Cases
+//
+
+
+template<>
+template<> void object::test<1>
+()
+{
+    const char* inputWKT = "GEOMETRYCOLLECTION(POLYGON ((100 100, 200 200, 300 100, 200 101, 100 100)), POLYGON ((150 0, 100 100, 200 101, 300 100, 250 0, 150 0)))";
+
+    input_ = fromWKT(inputWKT);
+    result_ = GEOSCoverageSimplifyVW(input_, 10.0, 0);
+
+    ensure( result_ != nullptr );
+    ensure( GEOSGeomTypeId(result_) == GEOS_GEOMETRYCOLLECTION );
+
+    const char* expectedWKT = "GEOMETRYCOLLECTION(POLYGON ((100 100, 200 200, 300 100, 100 100)), POLYGON ((150 0, 100 100, 300 100, 250 0, 150 0)))";
+
+    expected_ = fromWKT(expectedWKT);
+
+    // std::cout << toWKT(result_) << std::endl;
+    // std::cout << toWKT(expected_) << std::endl;
+
+    ensure_geometry_equals(result_, expected_, 0.1);
+}
+
+
+
+} // namespace tut
+

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

Summary of changes:
 NEWS.md                                      |  4 +-
 capi/geos_c.cpp                              | 16 ++++++
 capi/geos_c.h.in                             | 86 ++++++++++++++++++++++++++++
 capi/geos_ts_c.cpp                           | 81 ++++++++++++++++++++++++++
 tests/unit/capi/GEOSCoverageSimplifyTest.cpp | 85 +++++++++++++++++++++++++++
 5 files changed, 271 insertions(+), 1 deletion(-)
 create mode 100644 tests/unit/capi/GEOSCoverageSimplifyTest.cpp


hooks/post-receive
-- 
GEOS


More information about the geos-commits mailing list