[geos-commits] [SCM] GEOS branch main updated. 4e3fbef9f32588e54157568b07bb840a94a415eb

git at osgeo.org git at osgeo.org
Fri Apr 28 08:49:51 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  4e3fbef9f32588e54157568b07bb840a94a415eb (commit)
       via  d69e17a7922014a68460a721598273c30bea56bc (commit)
       via  d7ca8d16155bc4f15c5c25b086b331732a5af520 (commit)
      from  6e6afa8c95f6f82bf704a8e11da9e7b25ca3b072 (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 4e3fbef9f32588e54157568b07bb840a94a415eb
Author: Martin Davis <mtnclimb at gmail.com>
Date:   Fri Apr 28 08:49:21 2023 -0700

    Fix doxygen link

diff --git a/capi/geos_c.h.in b/capi/geos_c.h.in
index c701dc163..6a25e4e4f 100644
--- a/capi/geos_c.h.in
+++ b/capi/geos_c.h.in
@@ -774,7 +774,7 @@ GEOSCoverageIsValid_r(
     double gapWidth,
     GEOSGeometry** output);
 
-/** \see GEOSCoverageSimplify */
+/** \see GEOSCoverageSimplifyVW */
 extern GEOSGeometry GEOS_DLL *
 GEOSCoverageSimplifyVW_r(
     GEOSContextHandle_t extHandle,

commit d69e17a7922014a68460a721598273c30bea56bc
Author: Paul Ramsey <pramsey at cleverelephant.ca>
Date:   Wed Apr 26 13:19:35 2023 -0700

    Add an interrupt check to that in interactive use a user can cancel a long-running MaximumInscribedCircle operation, GH-875

diff --git a/src/algorithm/construct/MaximumInscribedCircle.cpp b/src/algorithm/construct/MaximumInscribedCircle.cpp
index d8eba69c4..0175788d9 100644
--- a/src/algorithm/construct/MaximumInscribedCircle.cpp
+++ b/src/algorithm/construct/MaximumInscribedCircle.cpp
@@ -28,6 +28,7 @@
 #include <geos/geom/MultiPolygon.h>
 #include <geos/algorithm/locate/IndexedPointInAreaLocator.h>
 #include <geos/operation/distance/IndexedFacetDistance.h>
+#include <geos/util/Interrupt.h>
 
 #include <typeinfo> // for dynamic_cast
 #include <cassert>
@@ -184,12 +185,15 @@ MaximumInscribedCircle::compute()
      * Carry out the branch-and-bound search
      * of the cell space
      */
+    std::size_t iterationCount = 0;
     while (!cellQueue.empty()) {
         // pick the most promising cell from the queue
         Cell cell = cellQueue.top();
         cellQueue.pop();
 
-        // std::cout << i << ": (" << cell.getX() << ", " << cell.getY() << ") " << cell.getHSize() << " dist = " << cell.getDistance() << std::endl;
+        if ((iterationCount++ % 1000) == 0) {
+            GEOS_CHECK_FOR_INTERRUPTS();
+        }
 
         // update the center cell if the candidate is further from the boundary
         if (cell.getDistance() > farthestCell.getDistance()) {
@@ -212,7 +216,6 @@ MaximumInscribedCircle::compute()
             cellQueue.emplace(cell.getX()+h2, cell.getY()+h2, h2, distanceToBoundary(cell.getX()+h2, cell.getY()+h2));
         }
     }
-    // std::cout << "number of iterations: " << i << std::endl;
 
     // the farthest cell is the best approximation to the MIC center
     Cell centerCell = farthestCell;

commit d7ca8d16155bc4f15c5c25b086b331732a5af520
Author: Martin Davis <mtnclimb at gmail.com>
Date:   Wed Apr 26 12:56:44 2023 -0700

    Fix Coverage ops to handle empty and collapsed cases (#879)

diff --git a/include/geos/coverage/CoverageEdge.h b/include/geos/coverage/CoverageEdge.h
index a75c3ecf8..6404b653f 100644
--- a/include/geos/coverage/CoverageEdge.h
+++ b/include/geos/coverage/CoverageEdge.h
@@ -63,12 +63,12 @@ private:
     // Methods
 
     static std::unique_ptr<CoordinateSequence>
-    extractEdgePoints(const LinearRing* ring,
+    extractEdgePoints(const CoordinateSequence& ring,
         std::size_t start, std::size_t end);
 
     static const Coordinate&
     findDistinctPoint(
-        const CoordinateSequence* pts,
+        const CoordinateSequence& pts,
         std::size_t index,
         bool isForward,
         const Coordinate& pt);
@@ -91,7 +91,7 @@ public:
     * @return a LineSegment representing the key
     */
     static LineSegment key(
-        const LinearRing* ring);
+        const CoordinateSequence& ring);
 
     /**
     * Computes a distinct key for a section of a linear ring.
@@ -102,15 +102,15 @@ public:
     * @return a LineSegment representing the key
     */
     static LineSegment key(
-        const LinearRing* ring,
+        const CoordinateSequence& ring,
         std::size_t start,
         std::size_t end);
 
     static std::unique_ptr<CoverageEdge> createEdge(
-        const LinearRing* ring);
+        const CoordinateSequence& ring);
 
     static std::unique_ptr<CoverageEdge> createEdge(
-        const LinearRing* ring,
+        const CoordinateSequence& ring,
         std::size_t start,
         std::size_t end);
 
@@ -169,8 +169,3 @@ public:
 
 } // namespace geos.coverage
 } // namespace geos
-
-
-
-
-
diff --git a/include/geos/coverage/CoveragePolygonValidator.h b/include/geos/coverage/CoveragePolygonValidator.h
index efa739e1f..c0150c895 100644
--- a/include/geos/coverage/CoveragePolygonValidator.h
+++ b/include/geos/coverage/CoveragePolygonValidator.h
@@ -372,6 +372,11 @@ private:
 
     void createRings(const Polygon* poly, std::vector<CoverageRing*>& rings);
 
+    void addRing(
+        const LinearRing* ring,
+        bool isShell,
+        std::vector<CoverageRing*>& rings);
+
     CoverageRing* createRing(const LinearRing* ring, bool isShell);
 
 
@@ -380,11 +385,3 @@ private:
 
 } // namespace geos::coverage
 } // namespace geos
-
-
-
-
-
-
-
-
diff --git a/include/geos/coverage/CoverageRingEdges.h b/include/geos/coverage/CoverageRingEdges.h
index f57473bcd..a6c82561a 100644
--- a/include/geos/coverage/CoverageRingEdges.h
+++ b/include/geos/coverage/CoverageRingEdges.h
@@ -121,7 +121,7 @@ private:
         LineSegment::UnorderedSet& boundarySegs,
         std::map<LineSegment, CoverageEdge*>& uniqueEdgeMap);
 
-    void addBoundaryNodes(
+    void addBoundaryInnerNodes(
         const LinearRing* ring,
         LineSegment::UnorderedSet& boundarySegs,
         Coordinate::UnorderedSet& nodes);
@@ -132,24 +132,24 @@ private:
         Coordinate::UnorderedSet& nodes);
 
     CoverageEdge* createEdge(
-        const LinearRing* ring,
+        const CoordinateSequence& ring,
         std::map<LineSegment, CoverageEdge*>& uniqueEdgeMap);
 
     CoverageEdge* createEdge(
-        const LinearRing* ring,
+        const CoordinateSequence& ring,
         std::size_t start, std::size_t end,
         std::map<LineSegment, CoverageEdge*>& uniqueEdgeMap);
 
     std::size_t findNextNodeIndex(
-        const LinearRing* ring,
+        const CoordinateSequence& ring,
         std::size_t start,
         Coordinate::UnorderedSet& nodes) const;
 
     static std::size_t next(
         std::size_t index,
-        const LinearRing* ring);
+        const CoordinateSequence& ring);
 
-    Coordinate::UnorderedSet findNodes(
+    Coordinate::UnorderedSet findMultiRingNodes(
         std::vector<const Geometry*>& coverage);
 
     Coordinate::UnorderedSet findBoundaryNodes(
@@ -177,8 +177,3 @@ private:
 
 } // namespace geos.coverage
 } // namespace geos
-
-
-
-
-
diff --git a/include/geos/coverage/VertexCounter.h b/include/geos/coverage/VertexRingCounter.h
similarity index 90%
rename from include/geos/coverage/VertexCounter.h
rename to include/geos/coverage/VertexRingCounter.h
index bf10ea3c0..3d1151cd4 100644
--- a/include/geos/coverage/VertexCounter.h
+++ b/include/geos/coverage/VertexRingCounter.h
@@ -36,12 +36,12 @@ using geos::geom::Geometry;
 namespace geos {
 namespace coverage { // geos::coverage
 
-class VertexCounter : public CoordinateSequenceFilter
+class VertexRingCounter : public CoordinateSequenceFilter
 {
 
 public:
 
-    VertexCounter(std::map<Coordinate, std::size_t>& counts)
+    VertexRingCounter(std::map<Coordinate, std::size_t>& counts)
         : vertexCounts(counts)
         {};
 
@@ -63,7 +63,7 @@ private:
 
     std::map<Coordinate, std::size_t>& vertexCounts;
 
-}; // VertexCounter
+}; // VertexRingCounter
 
 
 
diff --git a/src/coverage/CoverageBoundarySegmentFinder.cpp b/src/coverage/CoverageBoundarySegmentFinder.cpp
index 582188613..9744f630b 100644
--- a/src/coverage/CoverageBoundarySegmentFinder.cpp
+++ b/src/coverage/CoverageBoundarySegmentFinder.cpp
@@ -85,5 +85,3 @@ CoverageBoundarySegmentFinder::isBoundarySegment(
 
 } // namespace geos.coverage
 } // namespace geos
-
-
diff --git a/src/coverage/CoverageEdge.cpp b/src/coverage/CoverageEdge.cpp
index f98ec5111..a2114b992 100644
--- a/src/coverage/CoverageEdge.cpp
+++ b/src/coverage/CoverageEdge.cpp
@@ -33,15 +33,15 @@ namespace coverage { // geos.coverage
 
 /* public static */
 std::unique_ptr<CoverageEdge>
-CoverageEdge::createEdge(const LinearRing* ring)
+CoverageEdge::createEdge(const CoordinateSequence& ring)
 {
-    auto pts = extractEdgePoints(ring, 0, ring->getNumPoints() - 1);
+    auto pts = extractEdgePoints(ring, 0, ring.getSize() - 1);
     return detail::make_unique<CoverageEdge>(std::move(pts), true);
 }
 
 /* public static */
 std::unique_ptr<CoverageEdge>
-CoverageEdge::createEdge(const LinearRing* ring,
+CoverageEdge::createEdge(const CoordinateSequence& ring,
     std::size_t start, std::size_t end)
 {
     auto pts = extractEdgePoints(ring, start, end);
@@ -73,19 +73,18 @@ CoverageEdge::toLineString(const GeometryFactory* geomFactory)
 
 /* private static */
 std::unique_ptr<CoordinateSequence>
-CoverageEdge::extractEdgePoints(const LinearRing* ring,
+CoverageEdge::extractEdgePoints(const CoordinateSequence& ring,
     std::size_t start, std::size_t end)
 {
     auto pts = detail::make_unique<CoordinateSequence>();
     std::size_t size = start < end
                   ? end - start + 1
-                  : ring->getNumPoints() - start + end;
+                  : ring.getSize() - start + end;
     std::size_t iring = start;
-    auto cs = ring->getCoordinatesRO();
     for (std::size_t i = 0; i < size; i++) {
-        pts->add(cs->getAt(iring));
+        pts->add(ring.getAt(iring));
         iring += 1;
-        if (iring >= ring->getNumPoints())
+        if (iring >= ring.getSize())
             iring = 1;
     }
     return pts;
@@ -94,19 +93,18 @@ CoverageEdge::extractEdgePoints(const LinearRing* ring,
 
 /* public static */
 LineSegment
-CoverageEdge::key(const LinearRing* ring)
+CoverageEdge::key(const CoordinateSequence& ring)
 {
-    const CoordinateSequence* pts = ring->getCoordinatesRO();
     // find lowest vertex index
     std::size_t indexLow = 0;
-    for (std::size_t i = 1; i < pts->size() - 1; i++) {
-        if (pts->getAt(indexLow).compareTo(pts->getAt(i)) < 0)
+    for (std::size_t i = 1; i < ring.size() - 1; i++) {
+        if (ring.getAt(indexLow).compareTo(ring.getAt(i)) < 0)
             indexLow = i;
     }
-    const Coordinate& key0 = pts->getAt(indexLow);
+    const Coordinate& key0 = ring.getAt(indexLow);
     // find distinct adjacent vertices
-    const Coordinate& adj0 = findDistinctPoint(pts, indexLow, true, key0);
-    const Coordinate& adj1 = findDistinctPoint(pts, indexLow, false, key0);
+    const Coordinate& adj0 = findDistinctPoint(ring, indexLow, true, key0);
+    const Coordinate& adj1 = findDistinctPoint(ring, indexLow, false, key0);
     const Coordinate& key1 = adj0.compareTo(adj1) < 0 ? adj0 : adj1;
     return LineSegment(key0, key1);
 }
@@ -114,23 +112,22 @@ CoverageEdge::key(const LinearRing* ring)
 
 /* public static */
 LineSegment
-CoverageEdge::key(const LinearRing* ring,
+CoverageEdge::key(const CoordinateSequence& ring,
     std::size_t start, std::size_t end)
 {
-    const CoordinateSequence* pts = ring->getCoordinatesRO();
     //-- endpoints are distinct in a line edge
-    const Coordinate& end0 = pts->getAt(start);
-    const Coordinate& end1 = pts->getAt(end);
+    const Coordinate& end0 = ring.getAt(start);
+    const Coordinate& end1 = ring.getAt(end);
     bool isForward = 0 > end0.compareTo(end1);
     const Coordinate* key0;
     const Coordinate* key1;
     if (isForward) {
         key0 = &end0;
-        key1 = &findDistinctPoint(pts, start, true, *key0);
+        key1 = &findDistinctPoint(ring, start, true, *key0);
     }
     else {
         key0 = &end1;
-        key1 = &findDistinctPoint(pts, end, false, *key0);
+        key1 = &findDistinctPoint(ring, end, false, *key0);
     }
     return LineSegment(*key0, *key1);
 }
@@ -138,16 +135,16 @@ CoverageEdge::key(const LinearRing* ring,
 /* private static */
 const Coordinate&
 CoverageEdge::findDistinctPoint(
-    const CoordinateSequence* pts,
+    const CoordinateSequence& pts,
     std::size_t index,
     bool isForward,
     const Coordinate& pt)
 {
     std::size_t i = index;
-    std::size_t endIndex = pts->size()-1;
+    std::size_t endIndex = pts.size()-1;
     do {
-        if (! pts->getAt(i).equals2D(pt)) {
-            return pts->getAt(i);
+        if (! pts.getAt(i).equals2D(pt)) {
+            return pts.getAt(i);
         }
         // increment index with wrapping
         if (isForward) {
@@ -173,5 +170,3 @@ CoverageEdge::findDistinctPoint(
 
 } // namespace geos.coverage
 } // namespace geos
-
-
diff --git a/src/coverage/CoveragePolygonValidator.cpp b/src/coverage/CoveragePolygonValidator.cpp
index 73af48da6..a99643903 100644
--- a/src/coverage/CoveragePolygonValidator.cpp
+++ b/src/coverage/CoveragePolygonValidator.cpp
@@ -373,14 +373,26 @@ CoveragePolygonValidator::createRings(
     std::vector<CoverageRing*>& rings)
 {
     // Create exterior shell ring
-    rings.push_back(createRing(poly->getExteriorRing(), true));
+    addRing( poly->getExteriorRing(), true, rings);
 
     // Create hole rings
     for (std::size_t i = 0; i < poly->getNumInteriorRing(); i++) {
-        rings.push_back(createRing(poly->getInteriorRingN(i), false));
+        addRing( poly->getInteriorRingN(i), false, rings);
     }
 }
 
+/* private */
+void
+CoveragePolygonValidator::addRing(
+    const LinearRing* ring,
+    bool isShell,
+    std::vector<CoverageRing*>& rings)
+{
+    if (ring->isEmpty())
+        return;
+    rings.push_back(createRing(ring, isShell));
+}
+
 /* private */
 CoverageRing*
 CoveragePolygonValidator::createRing(const LinearRing* ring, bool isShell)
@@ -403,5 +415,3 @@ CoveragePolygonValidator::createRing(const LinearRing* ring, bool isShell)
 
 } // namespace geos.coverage
 } // namespace geos
-
-
diff --git a/src/coverage/CoverageRingEdges.cpp b/src/coverage/CoverageRingEdges.cpp
index dea6f350e..c334e47f5 100644
--- a/src/coverage/CoverageRingEdges.cpp
+++ b/src/coverage/CoverageRingEdges.cpp
@@ -18,7 +18,7 @@
 #include <geos/coverage/CoverageBoundarySegmentFinder.h>
 #include <geos/coverage/CoverageEdge.h>
 #include <geos/coverage/CoverageRingEdges.h>
-#include <geos/coverage/VertexCounter.h>
+#include <geos/coverage/VertexRingCounter.h>
 #include <geos/geom/Coordinate.h>
 #include <geos/geom/CoordinateSequence.h>
 #include <geos/geom/Geometry.h>
@@ -27,10 +27,10 @@
 #include <geos/geom/LinearRing.h>
 #include <geos/geom/Polygon.h>
 #include <geos/geom/MultiPolygon.h>
+#include <geos/operation/valid/RepeatedPointRemover.h>
 #include <geos/util/IllegalStateException.h>
 #include <geos/constants.h>
 
-
 using geos::geom::Coordinate;
 using geos::geom::CoordinateSequence;
 using geos::geom::Geometry;
@@ -39,7 +39,7 @@ using geos::geom::LineSegment;
 using geos::geom::LinearRing;
 using geos::geom::Polygon;
 using geos::geom::MultiPolygon;
-
+using geos::operation::valid::RepeatedPointRemover;
 
 namespace geos {     // geos
 namespace coverage { // geos.coverage
@@ -63,7 +63,7 @@ CoverageRingEdges::selectEdges(std::size_t ringCount) const
 void
 CoverageRingEdges::build()
 {
-    Coordinate::UnorderedSet nodes = findNodes(m_coverage);
+    Coordinate::UnorderedSet nodes = findMultiRingNodes(m_coverage);
     LineSegment::UnorderedSet boundarySegs = CoverageBoundarySegmentFinder::findBoundarySegments(m_coverage);
     Coordinate::UnorderedSet boundaryNodes = findBoundaryNodes(boundarySegs);
     nodes.insert(boundaryNodes.begin(), boundaryNodes.end());
@@ -72,12 +72,20 @@ CoverageRingEdges::build()
     for (const Geometry* geom : m_coverage) {
         for (std::size_t ipoly = 0; ipoly < geom->getNumGeometries(); ipoly++) {
             const Polygon* poly = static_cast<const Polygon*>(geom->getGeometryN(ipoly));
+
+            //-- skip empty elements. Missing elements are copied in result
+            if (poly->isEmpty())
+                continue;
+
             //-- extract shell
             const LinearRing* shell = poly->getExteriorRing();
             addRingEdges(shell, nodes, boundarySegs, uniqueEdgeMap);
             //-- extract holes
             for (std::size_t ihole = 0; ihole < poly->getNumInteriorRing(); ihole++) {
                 const LinearRing* hole = poly->getInteriorRingN(ihole);
+                //-- skip empty rings. Missing rings are copied in result
+                if (hole->isEmpty())
+                    continue;
                 addRingEdges(hole, nodes, boundarySegs, uniqueEdgeMap);
             }
         }
@@ -92,14 +100,16 @@ CoverageRingEdges::addRingEdges(
     LineSegment::UnorderedSet& boundarySegs,
     std::map<LineSegment, CoverageEdge*>& uniqueEdgeMap)
 {
-    addBoundaryNodes(ring, boundarySegs, nodes);
+    addBoundaryInnerNodes(ring, boundarySegs, nodes);
     std::vector<CoverageEdge*> ringEdges = extractRingEdges(ring, uniqueEdgeMap, nodes);
-    m_ringEdgesMap[ring] = ringEdges;
+    if (ringEdges.size() > 0) {
+        m_ringEdgesMap[ring] = ringEdges;
+    }
 }
 
 /* private */
 void
-CoverageRingEdges::addBoundaryNodes(
+CoverageRingEdges::addBoundaryInnerNodes(
     const LinearRing* ring,
     LineSegment::UnorderedSet& boundarySegs,
     Coordinate::UnorderedSet& nodes)
@@ -124,19 +134,25 @@ CoverageRingEdges::extractRingEdges(
     std::map<LineSegment, CoverageEdge*>& uniqueEdgeMap,
     Coordinate::UnorderedSet& nodes)
 {
+    std::unique_ptr<CoordinateSequence> pts
+        = RepeatedPointRemover::removeRepeatedPoints( ring->getCoordinatesRO() );
     std::vector<CoverageEdge*> ringEdges;
-    std::size_t first = findNextNodeIndex(ring, NO_COORD_INDEX, nodes);
+    //-- if compacted ring is too short, don't process it
+    if (pts->getSize() < 3)
+      return ringEdges;
+
+    std::size_t first = findNextNodeIndex(*pts, NO_COORD_INDEX, nodes);
     if (first == NO_COORD_INDEX) {
         //-- ring does not contain a node, so edge is entire ring
-        CoverageEdge* edge = createEdge(ring, uniqueEdgeMap);
+        CoverageEdge* edge = createEdge(*pts, uniqueEdgeMap);
         ringEdges.push_back(edge);
     }
     else {
         std::size_t start = first;
         std::size_t end = start;
         do {
-            end = findNextNodeIndex(ring, start, nodes);
-            CoverageEdge* edge = createEdge(ring, start, end, uniqueEdgeMap);
+            end = findNextNodeIndex(*pts, start, nodes);
+            CoverageEdge* edge = createEdge(*pts, start, end, uniqueEdgeMap);
             ringEdges.push_back(edge);
             start = end;
         } while (end != first);
@@ -147,7 +163,7 @@ CoverageRingEdges::extractRingEdges(
 /* private */
 CoverageEdge*
 CoverageRingEdges::createEdge(
-    const LinearRing* ring,
+    const CoordinateSequence& ring,
     std::map<LineSegment, CoverageEdge*>& uniqueEdgeMap)
 {
     CoverageEdge* edge;
@@ -173,7 +189,7 @@ CoverageRingEdges::createEdge(
 /* private */
 CoverageEdge*
 CoverageRingEdges::createEdge(
-    const LinearRing* ring,
+    const CoordinateSequence& ring,
     std::size_t start, std::size_t end,
     std::map<LineSegment, CoverageEdge*>& uniqueEdgeMap)
 {
@@ -200,7 +216,7 @@ CoverageRingEdges::createEdge(
 /* private */
 std::size_t
 CoverageRingEdges::findNextNodeIndex(
-    const LinearRing* ring,
+    const CoordinateSequence& ring,
     std::size_t start,
     Coordinate::UnorderedSet& nodes) const
 {
@@ -214,7 +230,7 @@ CoverageRingEdges::findNextNodeIndex(
             }
             isScanned0 = true;
         }
-        const Coordinate& pt = ring->getCoordinatesRO()->getAt(index);
+        const Coordinate& pt = ring.getAt(index);
         if (nodes.find(pt) != nodes.end()) {
             return index;
         }
@@ -224,11 +240,11 @@ CoverageRingEdges::findNextNodeIndex(
 
 /* private static */
 std::size_t
-CoverageRingEdges::next(std::size_t index, const LinearRing* ring)
+CoverageRingEdges::next(std::size_t index, const CoordinateSequence& ring)
 {
     if (index == NO_COORD_INDEX) return 0;
     index = index + 1;
-    if (index >= ring->getNumPoints() - 1)
+    if (index >= ring.getSize() - 1)
         index = 0;
     return index;
 }
@@ -236,17 +252,17 @@ CoverageRingEdges::next(std::size_t index, const LinearRing* ring)
 
 /* private */
 Coordinate::UnorderedSet
-CoverageRingEdges::findNodes(std::vector<const Geometry*>& coverage)
+CoverageRingEdges::findMultiRingNodes(std::vector<const Geometry*>& coverage)
 {
-    std::map<Coordinate, std::size_t> vertexCount;
-    VertexCounter::count(coverage, vertexCount);
+    std::map<Coordinate, std::size_t> vertexRingCount;
+    VertexRingCounter::count(coverage, vertexRingCount);
     Coordinate::UnorderedSet nodes;
     // for (Coordinate v : vertexCount.keySet()) {
     //     if (vertexCount.get(v) > 2) {
     //         nodes.add(v);
     //     }
     // }
-    for (const auto &mapPair : vertexCount) {
+    for (const auto &mapPair : vertexRingCount) {
         const Coordinate& v = mapPair.first;
         std::size_t count = mapPair.second;
         if (count > 2)
@@ -258,26 +274,26 @@ CoverageRingEdges::findNodes(std::vector<const Geometry*>& coverage)
 
 /* private */
 Coordinate::UnorderedSet
-CoverageRingEdges::findBoundaryNodes(LineSegment::UnorderedSet& lineSegments)
+CoverageRingEdges::findBoundaryNodes(LineSegment::UnorderedSet& boundarySegments)
 {
     std::map<Coordinate, std::size_t> counter;
-    for (const LineSegment& line : lineSegments) {
+    for (const LineSegment& seg : boundarySegments) {
         // counter.put(line.p0, counter.getOrDefault(line.p0, 0) + 1);
         // counter.put(line.p1, counter.getOrDefault(line.p1, 0) + 1);
-        auto search0 = counter.find(line.p0);
+        auto search0 = counter.find(seg.p0);
         if (search0 != counter.end()) {
-            counter[line.p0] = search0->second + 1;
+            counter[seg.p0] = search0->second + 1;
         }
         else {
-            counter[line.p0] = 0;
+            counter[seg.p0] = 0;
         }
 
-        auto search1 = counter.find(line.p1);
+        auto search1 = counter.find(seg.p1);
         if (search1 != counter.end()) {
-            counter[line.p1] = search1->second + 1;
+            counter[seg.p1] = search1->second + 1;
         }
         else {
-            counter[line.p1] = 0;
+            counter[seg.p1] = 0;
         }
     }
 
@@ -360,8 +376,8 @@ CoverageRingEdges::buildRing(const LinearRing* ring) const
     // List<CoverageEdge> ringEdges = m_ringEdgesMap.get(ring);
     auto result = m_ringEdgesMap.find(ring);
     if (result == m_ringEdgesMap.end()) {
-        // return nullptr;
-        throw util::IllegalStateException("buildRing");
+        //-- if ring is not in map, must have been invalid.  Just copy original
+        return ring->clone();
     }
     else {
         ringEdges = &(result->second);
@@ -404,5 +420,3 @@ CoverageRingEdges::isEdgeDirForward(
 
 } // namespace geos.coverage
 } // namespace geos
-
-
diff --git a/src/coverage/CoverageSimplifier.cpp b/src/coverage/CoverageSimplifier.cpp
index cd4b7d164..73b5a5e44 100644
--- a/src/coverage/CoverageSimplifier.cpp
+++ b/src/coverage/CoverageSimplifier.cpp
@@ -17,7 +17,6 @@
 #include <geos/coverage/CoverageEdge.h>
 #include <geos/coverage/CoverageRingEdges.h>
 #include <geos/coverage/TPVWSimplifier.h>
-#include <geos/coverage/VertexCounter.h>
 #include <geos/geom/Geometry.h>
 #include <geos/geom/GeometryFactory.h>
 #include <geos/geom/MultiLineString.h>
diff --git a/src/coverage/VertexCounter.cpp b/src/coverage/VertexRingCounter.cpp
similarity index 88%
rename from src/coverage/VertexCounter.cpp
rename to src/coverage/VertexRingCounter.cpp
index 6415b9138..c0d79cab9 100644
--- a/src/coverage/VertexCounter.cpp
+++ b/src/coverage/VertexRingCounter.cpp
@@ -13,7 +13,7 @@
  *
  **********************************************************************/
 
-#include <geos/coverage/VertexCounter.h>
+#include <geos/coverage/VertexRingCounter.h>
 
 #include <geos/geom/Coordinate.h>
 #include <geos/geom/CoordinateSequence.h>
@@ -32,11 +32,11 @@ namespace coverage { // geos.coverage
 
 /* public static  */
 void
-VertexCounter::count(
+VertexRingCounter::count(
     std::vector<const Geometry*>& geoms,
     std::map<Coordinate, std::size_t>& counts)
 {
-    VertexCounter vertextCounter(counts);
+    VertexRingCounter vertextCounter(counts);
     for (const Geometry* geom : geoms) {
         geom->apply_ro(vertextCounter);
     }
@@ -45,7 +45,7 @@ VertexCounter::count(
 
 /* public */
 void
-VertexCounter::filter_ro(const CoordinateSequence& seq, std::size_t i)
+VertexRingCounter::filter_ro(const CoordinateSequence& seq, std::size_t i)
 {
     //-- for rings don't double-count duplicate endpoint
     if (seq.isRing() && i == 0)
diff --git a/tests/unit/coverage/CoverageRingEdgesTest.cpp b/tests/unit/coverage/CoverageRingEdgesTest.cpp
index 9c8b17648..43c25140e 100644
--- a/tests/unit/coverage/CoverageRingEdgesTest.cpp
+++ b/tests/unit/coverage/CoverageRingEdgesTest.cpp
@@ -137,5 +137,15 @@ void object::test<5> ()
         "MULTILINESTRING ((1 2, 2 2), (2 1, 2 2), (2 2, 2 3), (2 2, 3 2))");
 }
 
+// testMultiPolygons
+template<>
+template<>
+void object::test<6> ()
+{
+    checkEdges(
+        "GEOMETRYCOLLECTION (MULTIPOLYGON (((5 9, 2.5 7.5, 1 5, 5 5, 5 9)), ((5 5, 9 5, 7.5 2.5, 5 1, 5 5))), MULTIPOLYGON (((5 9, 6.5 6.5, 9 5, 5 5, 5 9)), ((1 5, 5 5, 5 1, 3.5 3.5, 1 5))))",
+        "MULTILINESTRING ((1 5, 2.5 7.5, 5 9), (1 5, 3.5 3.5, 5 1), (1 5, 5 5), (5 1, 5 5), (5 1, 7.5 2.5, 9 5), (5 5, 5 9), (5 5, 9 5), (5 9, 6.5 6.5, 9 5))"
+    );
+}
 
 } // namespace tut
diff --git a/tests/unit/coverage/CoverageSimplifierTest.cpp b/tests/unit/coverage/CoverageSimplifierTest.cpp
index 64e4a1a01..04bd69c33 100644
--- a/tests/unit/coverage/CoverageSimplifierTest.cpp
+++ b/tests/unit/coverage/CoverageSimplifierTest.cpp
@@ -367,21 +367,101 @@ void object::test<19> ()
 
 }
 
-//---------------------------------
-// all inputs empty
-// template<>
-// template<>
-// void object::test<20> ()
-// {
-//     checkResult(readArray({
-//             "POLYGON EMPTY",
-//             "POLYGON EMPTY" }),
-//         1.5,
-//         readArray({
-//             "POLYGON EMPTY",
-//             "POLYGON EMPTY" })
-//     );
-// }
+// testRepeatedPointRemoved
+template<>
+template<>
+void object::test<20> ()
+{
+    checkResult(readArray({
+        "POLYGON ((5 9, 6.5 6.5, 9 5, 5 5, 5 5, 5 9))" }),
+        2,
+        readArray({
+            "POLYGON ((5 5, 5 9, 9 5, 5 5))" })
+    );
+}
+
+// testRepeatedPointCollapseToLine
+template<>
+template<>
+void object::test<21> ()
+{
+checkResult(readArray({
+    "MULTIPOLYGON (((10 10, 10 20, 20 19, 30 20, 30 10, 10 10)), ((10 30, 20 29, 30 30, 30 20, 20 19, 10 20, 10 30)), ((10 20, 20 19, 20 19, 10 20)))" }),
+    5,
+    readArray({
+        "MULTIPOLYGON (((10 20, 20 19, 30 20, 30 10, 10 10, 10 20)), ((30 20, 20 19, 10 20, 10 30, 30 30, 30 20)), ((10 20, 20 19, 10 20)))" })
+);
+}
+
+// testRepeatedPointCollapseToPoint()
+template<>
+template<>
+void object::test<22> ()
+{
+    checkResult(readArray({
+        "MULTIPOLYGON (((10 10, 10 20, 20 19, 30 20, 30 10, 10 10)), ((10 30, 20 29, 30 30, 30 20, 20 19, 10 20, 10 30)), ((20 19, 20 19, 20 19)))" }),
+        5,
+        readArray({
+            "MULTIPOLYGON (((10 10, 10 20, 20 19, 30 20, 30 10, 10 10)), ((10 20, 10 30, 30 30, 30 20, 20 19, 10 20)), ((20 19, 20 19, 20 19)))" })
+    );
+}
+
+// testRepeatedPointCollapseToPoint2
+template<>
+template<>
+void object::test<23> ()
+{
+    checkResult(readArray({
+        "MULTIPOLYGON (((100 200, 150 195, 200 200, 200 100, 100 100, 100 200)), ((150 195, 150 195, 150 195, 150 195)))" }),
+        40,
+        readArray({
+            "MULTIPOLYGON (((150 195, 200 200, 200 100, 100 100, 100 200, 150 195)), ((150 195, 150 195, 150 195, 150 195)))" })
+    );
+}
 
+// testAllEmpty()
+template<>
+template<>
+void object::test<24> ()
+{
+    checkResult(readArray({
+        "POLYGON EMPTY",
+        "POLYGON EMPTY" }),
+        1,
+        readArray({
+            "POLYGON EMPTY",
+            "POLYGON EMPTY" })
+    );
+  }
+
+// testOneEmpty
+template<>
+template<>
+void object::test<25> ()
+{
+    checkResult(readArray({
+        "POLYGON ((1 9, 5 9.1, 9 9, 9 1, 1 1, 1 9))",
+        "POLYGON EMPTY" }),
+        1,
+        readArray({
+            "POLYGON ((1 9, 9 9, 9 1, 1 1, 1 9))",
+            "POLYGON EMPTY" })
+    );
+  }
+
+// testEmptyHole()
+template<>
+template<>
+void object::test<26> ()
+{
+    checkResult(readArray({
+        "POLYGON ((1 9, 5 9.1, 9 9, 9 1, 1 1, 1 9), EMPTY)",
+        "POLYGON EMPTY"  }),
+        1,
+        readArray({
+            "POLYGON ((1 9, 9 9, 9 1, 1 1, 1 9), EMPTY)",
+            "POLYGON EMPTY" })
+    );
+  }
 
 } // namespace tut
diff --git a/tests/unit/coverage/CoverageValidatorTest.cpp b/tests/unit/coverage/CoverageValidatorTest.cpp
index fd8bc6cd6..1f7259e5b 100644
--- a/tests/unit/coverage/CoverageValidatorTest.cpp
+++ b/tests/unit/coverage/CoverageValidatorTest.cpp
@@ -282,6 +282,73 @@ void object::test<10> ()
     checkValid(coverage);
 }
 
+// testMultiPolygon
+template<>
+template<>
+void object::test<11> ()
+{
+    std::vector<std::string> coverage{
+        "MULTIPOLYGON (((1 9, 5 9, 5 5, 1 5, 1 9)), ((9 1, 5 1, 5 5, 9 5, 9 1)))",
+        "MULTIPOLYGON (((1 1, 1 5, 5 5, 5 1, 1 1)), ((9 9, 9 5, 5 5, 5 9, 9 9)))"
+    };
+    checkValid(coverage);
+}
+
+// testValidDuplicatePoints
+template<>
+template<>
+void object::test<12> ()
+{
+    std::vector<std::string> coverage{
+        "POLYGON ((1 9, 5 9, 5 5, 1 5, 1 5, 1 5, 1 9))",
+        "POLYGON ((9 9, 9 5, 5 5, 5 9, 9 9))",
+        "POLYGON ((1 1, 1 5, 5 5, 5 1, 1 1))",
+        "POLYGON ((9 1, 5 1, 5 5, 9 5, 9 1))"
+    };
+    checkValid(coverage);
+}
+
+// testRingCollapse
+template<>
+template<>
+void object::test<13> ()
+{
+    std::vector<std::string> coverage{
+        "POLYGON ((1 9, 5 9, 1 9))",
+        "POLYGON ((9 9, 9 5, 5 5, 5 9, 9 9))",
+        "POLYGON ((1 1, 1 5, 5 5, 5 1, 1 1))",
+        "POLYGON ((9 1, 5 1, 5 5, 9 5, 9 1))"
+    };
+    checkValid(coverage);
+}
+
+  //========  Valid cases with EMPTY  =============================
+
+// testPolygonEmpty
+template<>
+template<>
+void object::test<14> ()
+{
+    std::vector<std::string> coverage{
+        "POLYGON ((1 9, 5 9, 5 5, 1 5, 1 9))",
+        "POLYGON ((9 9, 9 5, 5 5, 5 9, 9 9))",
+        "POLYGON ((1 1, 1 5, 5 5, 5 1, 1 1))",
+        "POLYGON EMPTY"
+    };
+    checkValid(coverage);
+}
+
+// testMultiPolygonWithEmptyRing
+template<>
+template<>
+void object::test<15> ()
+{
+    std::vector<std::string> coverage{
+        "MULTIPOLYGON (((9 9, 9 1, 1 1, 2 4, 7 7, 9 9)), EMPTY)"
+    };
+    checkValid(coverage);
+}
+
 
 
 

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

Summary of changes:
 capi/geos_c.h.in                                   |   2 +-
 include/geos/coverage/CoverageEdge.h               |  17 ++--
 include/geos/coverage/CoveragePolygonValidator.h   |  13 +--
 include/geos/coverage/CoverageRingEdges.h          |  17 ++--
 .../{VertexCounter.h => VertexRingCounter.h}       |   6 +-
 src/algorithm/construct/MaximumInscribedCircle.cpp |   7 +-
 src/coverage/CoverageBoundarySegmentFinder.cpp     |   2 -
 src/coverage/CoverageEdge.cpp                      |  49 +++++----
 src/coverage/CoveragePolygonValidator.cpp          |  18 +++-
 src/coverage/CoverageRingEdges.cpp                 |  80 ++++++++-------
 src/coverage/CoverageSimplifier.cpp                |   1 -
 .../{VertexCounter.cpp => VertexRingCounter.cpp}   |   8 +-
 tests/unit/coverage/CoverageRingEdgesTest.cpp      |  10 ++
 tests/unit/coverage/CoverageSimplifierTest.cpp     | 110 ++++++++++++++++++---
 tests/unit/coverage/CoverageValidatorTest.cpp      |  67 +++++++++++++
 15 files changed, 285 insertions(+), 122 deletions(-)
 rename include/geos/coverage/{VertexCounter.h => VertexRingCounter.h} (90%)
 rename src/coverage/{VertexCounter.cpp => VertexRingCounter.cpp} (88%)


hooks/post-receive
-- 
GEOS


More information about the geos-commits mailing list