[geos-commits] [SCM] GEOS branch master updated. 2522fba2d8851500a8d9f39337e07bbf5c0a5653

git at osgeo.org git at osgeo.org
Mon Nov 30 17:34:23 PST 2020


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, master has been updated
       via  2522fba2d8851500a8d9f39337e07bbf5c0a5653 (commit)
      from  401aee7981dafba8ef82cdd83d59d3d56ddfef03 (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 2522fba2d8851500a8d9f39337e07bbf5c0a5653
Author: Paul Ramsey <pramsey at cleverelephant.ca>
Date:   Mon Nov 30 17:34:06 2020 -0800

    Use SnapRoundingNoder in BufferOp
    This avoids doing a precision reduction on the input geometry.
    It maps more closely to the implementation in JTS.
    It still does an increasing loop of larger tolerance,
    in the event of a failure.
    This is to address the regression reported by GEOSwift
    downstream on 3.9.0beta1

diff --git a/src/operation/buffer/BufferOp.cpp b/src/operation/buffer/BufferOp.cpp
index 3e815fd..d0f1b9a 100644
--- a/src/operation/buffer/BufferOp.cpp
+++ b/src/operation/buffer/BufferOp.cpp
@@ -34,6 +34,7 @@
 
 #include <geos/noding/snapround/MCIndexSnapRounder.h>
 #include <geos/noding/snapround/MCIndexPointSnapper.h>
+#include <geos/noding/snapround/SnapRoundingNoder.h>
 
 //FIXME: for temporary use, see other FIXME in file
 #include <geos/algorithm/LineIntersector.h>
@@ -222,26 +223,37 @@ BufferOp::bufferReducedPrecision(int precisionDigits)
 void
 BufferOp::bufferFixedPrecision(const PrecisionModel& fixedPM)
 {
+    PrecisionModel pm(1.0); // fixed as well
 
+#define SNAP_WITH_NODER
+#ifdef SNAP_WITH_NODER
+    // Reduce precision using SnapRoundingNoder
+    //
+    // This more closely aligns with JTS implementation,
+    // and avoids reducing the precision of the input
+    // geometry.
+    //
+    // TODO: Add a finer fallback sequence. Full
+    //       precision, then SnappingNoder, then
+    //       SnapRoundingNoder.
 
-    PrecisionModel pm(1.0); // fixed as well
+    snapround::SnapRoundingNoder inoder(&pm);
+    ScaledNoder noder(inoder, fixedPM.getScale());
+    BufferBuilder bufBuilder(bufParams);
+    bufBuilder.setWorkingPrecisionModel(&fixedPM);
+    bufBuilder.setNoder(&noder);
+    resultGeometry = bufBuilder.buffer(argGeom, distance);
 
-#if 0 /* FIXME: MCIndexSnapRounder seems to be still bogus */
-    snapround::MCIndexSnapRounder inoder(pm);
 #else
     algorithm::LineIntersector li(&fixedPM);
     IntersectionAdder ia(li);
     MCIndexNoder inoder(&ia);
-#endif
-
     ScaledNoder noder(inoder, fixedPM.getScale());
-
     BufferBuilder bufBuilder(bufParams);
     bufBuilder.setWorkingPrecisionModel(&fixedPM);
-
     bufBuilder.setNoder(&noder);
 
-    // Reduce precision of the input geometry
+    // Snap by reducing the precision of the input geometry
     //
     // NOTE: this reduction is not in JTS and should supposedly
     //       not be needed because the PrecisionModel we pass
@@ -266,6 +278,7 @@ BufferOp::bufferFixedPrecision(const PrecisionModel& fixedPM)
 
     // this may throw an exception, if robustness errors are encountered
     resultGeometry = bufBuilder.buffer(workGeom, distance);
+#endif
 }
 
 } // namespace geos.operation.buffer
diff --git a/tests/unit/operation/buffer/BufferOpTest.cpp b/tests/unit/operation/buffer/BufferOpTest.cpp
index b2dc84f..ac05b9b 100644
--- a/tests/unit/operation/buffer/BufferOpTest.cpp
+++ b/tests/unit/operation/buffer/BufferOpTest.cpp
@@ -12,6 +12,7 @@
 #include <geos/geom/Geometry.h>
 #include <geos/algorithm/PointLocator.h>
 #include <geos/io/WKTReader.h>
+#include <geos/io/WKTWriter.h>
 #include <geos/geom/CoordinateSequence.h>
 // std
 #include <memory>
@@ -27,6 +28,7 @@ namespace tut {
 struct test_bufferop_data {
     const geos::geom::GeometryFactory& gf;
     geos::io::WKTReader wktreader;
+    geos::io::WKTWriter wktwriter;
     int const default_quadrant_segments;
 
     typedef geos::geom::Geometry::Ptr GeomPtr;
@@ -363,7 +365,7 @@ MULTILINESTRING(  \
 
     // We're basically only interested an rough sense of a
     // meaningful result.
-    ensure_equals(gBuffer->getNumPoints(), std::size_t(47));
+    ensure_equals(gBuffer->getNumPoints(), std::size_t(46));
     ensure_equals(int(gBuffer->getArea()), 3520);
 }
 
@@ -421,5 +423,29 @@ void object::test<13>
     ensure_equals(gBuffer->getGeometryTypeId(), geos::geom::GEOS_POLYGON);
 }
 
+// Test for GEOSwift regression failure
+template<>
+template<>
+void object::test<14>
+()
+{
+    using geos::operation::buffer::BufferOp;
+    using geos::operation::buffer::BufferParameters;
+
+    std::string wkt0("GEOMETRYCOLLECTION (POINT (1 2), MULTIPOINT ((1 2), (3 4)), LINESTRING (1 2, 3 4), MULTILINESTRING ((1 2, 3 4), (5 6, 7 8)), POLYGON ((2 2, -2 2, -2 -2, 2 -2, 2 2), (1 1, 1 -1, -1 -1, -1 1, 1 1)), MULTIPOLYGON (((2 2, -2 2, -2 -2, 2 -2, 2 2), (1 1, 1 -1, -1 -1, -1 1, 1 1)), ((7 2, 3 2, 3 -2, 7 -2, 7 2))))");
+
+    GeomPtr g0(wktreader.read(wkt0));
+    BufferOp op(g0.get());
+
+    double const distance = 0.5;
+    GeomPtr gBuffer(op.getResultGeometry(distance));
+
+    // std::cout << wktwriter.write(gBuffer.get()) << std::endl;
+
+    ensure_not(gBuffer->isEmpty());
+    ensure(gBuffer->isValid());
+    ensure_equals(gBuffer->getGeometryTypeId(), geos::geom::GEOS_MULTIPOLYGON);
+}
+
 } // namespace tut
 

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

Summary of changes:
 src/operation/buffer/BufferOp.cpp            | 29 ++++++++++++++++++++--------
 tests/unit/operation/buffer/BufferOpTest.cpp | 28 ++++++++++++++++++++++++++-
 2 files changed, 48 insertions(+), 9 deletions(-)


hooks/post-receive
-- 
GEOS


More information about the geos-commits mailing list