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()); + } }