diff --git a/modules/core/src/main/java/org/locationtech/jts/noding/snapround/SnapRoundingIntersectionAdder.java b/modules/core/src/main/java/org/locationtech/jts/noding/snapround/SnapRoundingIntersectionAdder.java index 94e6a5cd14..22f8eba381 100644 --- a/modules/core/src/main/java/org/locationtech/jts/noding/snapround/SnapRoundingIntersectionAdder.java +++ b/modules/core/src/main/java/org/locationtech/jts/noding/snapround/SnapRoundingIntersectionAdder.java @@ -43,16 +43,9 @@ */ public class SnapRoundingIntersectionAdder implements SegmentIntersector -{ - /** - * The division factor used to determine - * nearness distance tolerance for interior intersection detection. - */ - private static final int NEARNESS_FACTOR = 100; - +{ private final LineIntersector li; private final List intersections; - private final PrecisionModel precModel; private final double nearnessTol; @@ -60,16 +53,11 @@ public class SnapRoundingIntersectionAdder * Creates an intersector which finds all snapped interior intersections, * and adds them as nodes. * - * @param pm the precision mode to use + * @param nearnessTol the intersection distance tolerance */ - public SnapRoundingIntersectionAdder(PrecisionModel pm) + public SnapRoundingIntersectionAdder(double nearnessTol) { - precModel = pm; - /** - * Nearness distance tolerance is a small fraction of the snap grid size - */ - double snapGridSize = 1.0 / precModel.getScale(); - nearnessTol = snapGridSize / NEARNESS_FACTOR; + this.nearnessTol = nearnessTol; /** * Intersections are detected and computed using full precision. diff --git a/modules/core/src/main/java/org/locationtech/jts/noding/snapround/SnapRoundingNoder.java b/modules/core/src/main/java/org/locationtech/jts/noding/snapround/SnapRoundingNoder.java index 87ec99fb7b..6dc3543d82 100644 --- a/modules/core/src/main/java/org/locationtech/jts/noding/snapround/SnapRoundingNoder.java +++ b/modules/core/src/main/java/org/locationtech/jts/noding/snapround/SnapRoundingNoder.java @@ -57,6 +57,12 @@ public class SnapRoundingNoder implements Noder { + /** + * The division factor used to determine + * nearness distance tolerance for intersection detection. + */ + private static final int NEARNESS_FACTOR = 100; + private final PrecisionModel pm; private final HotPixelIndex pixelIndex; @@ -111,9 +117,14 @@ private List snapRound(Collection segStr */ private void addIntersectionPixels(Collection segStrings) { - SnapRoundingIntersectionAdder intAdder = new SnapRoundingIntersectionAdder(pm); - MCIndexNoder noder = new MCIndexNoder(); - noder.setSegmentIntersector(intAdder); + /** + * nearness tolerance is a small fraction of the grid size. + */ + double snapGridSize = 1.0 / pm.getScale(); + double nearnessTol = snapGridSize / NEARNESS_FACTOR; + + SnapRoundingIntersectionAdder intAdder = new SnapRoundingIntersectionAdder(nearnessTol); + MCIndexNoder noder = new MCIndexNoder(intAdder, nearnessTol); noder.computeNodes(segStrings); List intPts = intAdder.getIntersections(); pixelIndex.addNodes(intPts); diff --git a/modules/core/src/test/java/org/locationtech/jts/noding/snapround/SnapRoundingNoderTest.java b/modules/core/src/test/java/org/locationtech/jts/noding/snapround/SnapRoundingNoderTest.java index e9f23def7a..305b512b49 100644 --- a/modules/core/src/test/java/org/locationtech/jts/noding/snapround/SnapRoundingNoderTest.java +++ b/modules/core/src/test/java/org/locationtech/jts/noding/snapround/SnapRoundingNoderTest.java @@ -199,6 +199,16 @@ public void testVertexNearHorizSegNotNoded() { checkRounding(wkt, 1000000, expected); } + /** + * Tests that MCIndexNoder tolerance is set correctly. + * See https://trac.osgeo.org/geos/ticket/1127 and https://github.com/libgeos/geos/pull/504 + */ + public void testMCIndexNoderTolerance() { + String wkt = "LINESTRING (3670939.6336634574 3396937.3777869204, 3670995.4715200397 3396926.0316904164, 3671077.280213823 3396905.4302639295, 3671203.8838707027 3396908.120176068, 3671334.962571111 3396904.8310892633, 3670037.299066126 3396904.8310892633, 3670037.299066126 3398075.9808747065, 3670939.6336634574 3396937.3777869204)"; + String expected = "MULTILINESTRING ((3670776.0631373483 3397212.0584320477, 3670776.0631373483 3396600.058421521), (3670776.0631373483 3396600.058421521, 3671388.063147875 3396600.058421521), (3671388.063147875 3396600.058421521, 3671388.063147875 3397212.0584320477), (3671388.063147875 3397212.0584320477, 3671388.063147875 3396600.058421521), (3671388.063147875 3396600.058421521, 3671388.063147875 3397212.0584320477), (3671388.063147875 3397212.0584320477, 3671388.063147875 3396600.058421521), (3671388.063147875 3396600.058421521, 3670776.0631373483 3396600.058421521), (3670776.0631373483 3396600.058421521, 3670164.063126822 3396600.058421521, 3670164.063126822 3397824.058442574, 3670776.0631373483 3397212.0584320477))"; + checkRounding(wkt, 0.0016339869, expected); + } + void checkRounding(String wkt, double scale, String expectedWKT) { Geometry geom = read(wkt); diff --git a/modules/core/src/test/java/org/locationtech/jts/precision/GeometryPrecisionReducerTest.java b/modules/core/src/test/java/org/locationtech/jts/precision/GeometryPrecisionReducerTest.java index 5a560a9914..94712bc855 100644 --- a/modules/core/src/test/java/org/locationtech/jts/precision/GeometryPrecisionReducerTest.java +++ b/modules/core/src/test/java/org/locationtech/jts/precision/GeometryPrecisionReducerTest.java @@ -212,6 +212,19 @@ public void testKeepCollapsedMultiPolygon() "POLYGON ((2 2, 2 1, 1 1, 1 2, 2 2))"); } + //------------------------------------------------- + + /** + * Test issue showing bug in SnapRoundingNoder not passing tolerance to MCIndexNoder. + * + * See https://trac.osgeo.org/geos/ticket/1127 + */ + public void testLargeGridsizeFail() + { + checkReduce(1.0/612, "POLYGON((3670939.6336634574 3396937.3777869204, 3670995.4715200397 3396926.0316904164, 3671077.280213823 3396905.4302639295, 3671203.8838707027 3396908.120176068, 3671334.962571111 3396904.8310892633, 3670037.299066126 3396904.8310892633, 3670037.299066126 3398075.9808747065, 3670939.6336634574 3396937.3777869204))", + "POLYGON ((3670164 3396600, 3670164 3397824, 3670776 3397212, 3670776 3396600, 3670164 3396600))"); + } + //======================================= private void checkReduce(