diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt index d906a699072..56f385830d3 100644 --- a/lucene/CHANGES.txt +++ b/lucene/CHANGES.txt @@ -217,6 +217,9 @@ Bug fixes * LUCENE-9365: FuzzyQuery was missing matches when prefix length was equal to the term length (Mark Harwood, Mike Drob) +* LUCENE-9580: Fix bug in the polygon tessellator when introducing collinear edges during polygon + splitting. (Ignacio Vera) + Changes in Backwards Compatibility Policy * LUCENE-9669: DirectoryReader#open now accepts an argument to open indices created with versions diff --git a/lucene/core/src/java/org/apache/lucene/geo/Tessellator.java b/lucene/core/src/java/org/apache/lucene/geo/Tessellator.java index 4d65b4460ab..cd45056966d 100644 --- a/lucene/core/src/java/org/apache/lucene/geo/Tessellator.java +++ b/lucene/core/src/java/org/apache/lucene/geo/Tessellator.java @@ -968,7 +968,12 @@ public final class Tessellator { && isIntersectingPolygon(a, a.getX(), a.getY(), b.getX(), b.getY()) == false && isLocallyInside(a, b) && isLocallyInside(b, a) - && middleInsert(a, a.getX(), a.getY(), b.getX(), b.getY()); + && middleInsert(a, a.getX(), a.getY(), b.getX(), b.getY()) + // make sure we don't introduce collinear lines + && area(a.previous.getX(), a.previous.getY(), a.getX(), a.getY(), b.getX(), b.getY()) != 0 + && area(a.getX(), a.getY(), b.getX(), b.getY(), b.next.getX(), b.next.getY()) != 0 + && area(a.next.getX(), a.next.getY(), a.getX(), a.getY(), b.getX(), b.getY()) != 0 + && area(a.getX(), a.getY(), b.getX(), b.getY(), b.previous.getX(), b.previous.getY()) != 0; } /** Determine whether the polygon defined between node start and node end is CW */ @@ -1175,11 +1180,7 @@ public final class Tessellator { nextNode.getY()) == 0)) { // Remove the node - boolean nextEdgeFromPol = - prevNode.isNextEdgeFromPolygon != node.isNextEdgeFromPolygon - ? true - : prevNode.isNextEdgeFromPolygon; - removeNode(node, nextEdgeFromPol); + removeNode(node, prevNode.isNextEdgeFromPolygon); node = end = prevNode; if (node == nextNode) { diff --git a/lucene/core/src/test/org/apache/lucene/geo/TestTessellator.java b/lucene/core/src/test/org/apache/lucene/geo/TestTessellator.java index e8d101aa5d6..742d92a266d 100644 --- a/lucene/core/src/test/org/apache/lucene/geo/TestTessellator.java +++ b/lucene/core/src/test/org/apache/lucene/geo/TestTessellator.java @@ -677,6 +677,23 @@ public class TestTessellator extends LuceneTestCase { } } + public void testComplexPolygon43() throws Exception { + String wkt = + "POLYGON((-88.3245325358123 41.9306419084828,-88.3243288475156 41.9308130944597,-88.3244513948451 41.930891654082,-88.3246174067624 41.930998076295,-88.3245448815692 41.9310557712027,-88.3239353718069 41.9313272600886,-88.3237355617867 41.9313362704162," + + "-88.3237347670323 41.9311150951881,-88.3237340649402 41.931103661118,-88.3235660813522 41.9311112432041,-88.3234509652339 41.9311164377155,-88.3232353124097 41.9311261692953,-88.3232343331295 41.9313588701899,-88.323028772523 41.9313681383084," + + "-88.3229999744274 41.930651995613,-88.3236147717043 41.9303655647412,-88.323780013667 41.929458561339,-88.3240657895016 41.9293998882959,-88.3243948640426 41.9293028003164,-88.324740490767 41.9301340399879,-88.3251305560187 41.9302766363048," + + "-88.3248260581475 41.9308286995884,-88.3246595186817 41.9307227160738,-88.3245325358123 41.9306419084828)," + + "(-88.3245658060855 41.930351580587,-88.3246004191532 41.9302095159456,-88.3246375011905 41.9300573183932,-88.3243392233337 41.9300159738164,-88.3243011787553 41.9301696594472,-88.3242661951392 41.9303109843373,-88.3245658060855 41.930351580587)," + + "(-88.3245325358123 41.9306419084828,-88.3245478066552 41.9305086556331,-88.3245658060855 41.930351580587,-88.3242368660096 41.9303327977821,-88.3242200926128 41.9304905242189,-88.324206161464 41.9306215207536,-88.3245325358123 41.9306419084828)," + + "(-88.3236767661893 41.9307089429871,-88.3237008716322 41.930748885445,-88.323876104365 41.9306891087739,-88.324063438129 41.9306252050871,-88.3239244290607 41.930399373909,-88.3237349076233 41.9304653056436,-88.3235653339759 41.9305242981369,-88.3236767661893 41.9307089429871))"; + Polygon polygon = (Polygon) SimpleWKTShapeParser.parse(wkt); + List tessellation = Tessellator.tessellate(polygon); + assertEquals(area(polygon), area(tessellation), 1e-11); + for (Tessellator.Triangle t : tessellation) { + checkTriangleEdgesFromPolygon(polygon, t); + } + } + private void checkPolygon(String wkt) throws Exception { Polygon polygon = (Polygon) SimpleWKTShapeParser.parse(wkt); List tessellation = Tessellator.tessellate(polygon);