From 0f7f19f64c838935cb2e3c73280258d1c4bf7618 Mon Sep 17 00:00:00 2001 From: Martin Davis Date: Fri, 4 Jun 2021 15:41:17 -0700 Subject: [PATCH] Fix IsValid for LinearRings (#737) Signed-off-by: Martin Davis --- .../jts/operation/valid/IsValidOp.java | 14 +++++++++++--- .../jts/operation/valid/IsValidTest.java | 18 ++++++++++++++++++ 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/modules/core/src/main/java/org/locationtech/jts/operation/valid/IsValidOp.java b/modules/core/src/main/java/org/locationtech/jts/operation/valid/IsValidOp.java index 066d4c692b..2d0f6e2c04 100644 --- a/modules/core/src/main/java/org/locationtech/jts/operation/valid/IsValidOp.java +++ b/modules/core/src/main/java/org/locationtech/jts/operation/valid/IsValidOp.java @@ -407,11 +407,15 @@ private void checkNoSelfIntersectingRings(GeometryGraph graph) private void checkNoSelfIntersectingRing(EdgeIntersectionList eiList) { Set nodeSet = new TreeSet(); - boolean isFirst = true; for (Iterator i = eiList.iterator(); i.hasNext(); ) { EdgeIntersection ei = (EdgeIntersection) i.next(); - if (isFirst) { - isFirst = false; + /** + * Do not count start point, so start/end node is not counted as a self-intersection. + * Another segment with a node in same location will still trigger an invalid error. + * (Note that the edgeIntersectionList may not contain the start/end node, + * due to noding short-circuiting.) + */ + if (isStartNode(ei)) { continue; } if (nodeSet.contains(ei.coord)) { @@ -426,6 +430,10 @@ private void checkNoSelfIntersectingRing(EdgeIntersectionList eiList) } } + private static boolean isStartNode(EdgeIntersection ei) { + return ei.getSegmentIndex() == 0 && ei.getDistance() == 0.0; + } + /** * Tests that each hole is inside the polygon shell. * This routine assumes that the holes have previously been tested diff --git a/modules/core/src/test/java/org/locationtech/jts/operation/valid/IsValidTest.java b/modules/core/src/test/java/org/locationtech/jts/operation/valid/IsValidTest.java index 2818eca5cd..4d39010a3b 100644 --- a/modules/core/src/test/java/org/locationtech/jts/operation/valid/IsValidTest.java +++ b/modules/core/src/test/java/org/locationtech/jts/operation/valid/IsValidTest.java @@ -65,5 +65,23 @@ public void testLineString() throws Exception { g.isValid(); assertTrue(true); //No exception thrown [Jon Aquino] } + + public void testLinearRingTriangle() throws Exception { + Geometry g = reader.read( + "LINEARRING (100 100, 150 200, 200 100, 100 100)"); + assertTrue(g.isValid()); + } + + public void testLinearRingSelfCrossing() throws Exception { + Geometry g = reader.read( + "LINEARRING (150 100, 300 300, 100 300, 350 100, 150 100)"); + assertTrue(! g.isValid()); + } + + public void testLinearRingSelfCrossing2() throws Exception { + Geometry g = reader.read( + "LINEARRING (0 0, 100 100, 100 0, 0 100, 0 0)"); + assertTrue(! g.isValid()); + } }