LUCENE-8550: Fix filtering of coplanar points when creating linked list on polygon tesselator

This commit is contained in:
iverase 2018-11-02 08:01:29 +01:00
parent f7720aad82
commit ae9185f7d8
3 changed files with 12 additions and 20 deletions

View File

@ -238,6 +238,9 @@ Improvements:
Bug Fixes: Bug Fixes:
* LUCENE-8550: Fix filtering of coplanar points when creating linked list on
polygon tesselator. (Ignacio Vera)
* LUCENE-8549: Polygon tessellator throws an error if some parts of the shape * LUCENE-8549: Polygon tessellator throws an error if some parts of the shape
could not be processed. (Ignacio Vera) could not be processed. (Ignacio Vera)

View File

@ -124,15 +124,11 @@ final public class Tessellator {
// Link points into the circular doubly-linked list in the specified winding order // Link points into the circular doubly-linked list in the specified winding order
if (windingOrder == polygon.getWindingOrder()) { if (windingOrder == polygon.getWindingOrder()) {
for (int i = 0; i < polygon.numPoints(); ++i) { for (int i = 0; i < polygon.numPoints(); ++i) {
if (lastNode == null || filter(polygon, i, lastNode) == false) { lastNode = insertNode(polygon, startIndex++, i, lastNode);
lastNode = insertNode(polygon, startIndex++, i, lastNode);
}
} }
} else { } else {
for (int i = polygon.numPoints() - 1; i >= 0; --i) { for (int i = polygon.numPoints() - 1; i >= 0; --i) {
if (lastNode == null || filter(polygon, i, lastNode) == false) { lastNode = insertNode(polygon, startIndex++, i, lastNode);
lastNode = insertNode(polygon, startIndex++, i, lastNode);
}
} }
} }
// if first and last node are the same then remove the end node and set lastNode to the start // if first and last node are the same then remove the end node and set lastNode to the start
@ -142,7 +138,7 @@ final public class Tessellator {
} }
// Return the last node in the Doubly-Linked List // Return the last node in the Doubly-Linked List
return lastNode; return filterPoints(lastNode, null);
} }
/** Links every hole into the outer loop, producing a single-ring polygon without holes. **/ /** Links every hole into the outer loop, producing a single-ring polygon without holes. **/
@ -641,19 +637,6 @@ final public class Tessellator {
} while (numMerges > 1); } while (numMerges > 1);
} }
/** utility method to filter a single duplicate or colinear triangle */
private static boolean filter(final Polygon polygon, final int i, final Node node) {
final double x = polygon.getPolyLon(i);
final double y = polygon.getPolyLat(i);
final boolean equal = (x == node.getX() && y == node.getY());
if (equal == true) {
return true;
} else if (node.previous == node || node.previous.previous == node) {
return false;
}
return area(node.previous.previous.getX(), node.previous.previous.getY(), node.previous.getX(), node.previous.getY(), x, y) == 0d;
}
/** Eliminate colinear/duplicate points from the doubly linked list */ /** Eliminate colinear/duplicate points from the doubly linked list */
private static final Node filterPoints(final Node start, Node end) { private static final Node filterPoints(final Node start, Node end) {
if (start == null) { if (start == null) {

View File

@ -90,4 +90,10 @@ public class TestTessellator extends LuceneTestCase {
Polygon polygon = (Polygon)SimpleWKTShapeParser.parse(wkt); Polygon polygon = (Polygon)SimpleWKTShapeParser.parse(wkt);
expectThrows( IllegalArgumentException.class, () -> {Tessellator.tessellate(polygon); }); expectThrows( IllegalArgumentException.class, () -> {Tessellator.tessellate(polygon); });
} }
public void testLUCENE8550() throws Exception {
String wkt = "POLYGON((24.04725 59.942,24.04825 59.94125,24.04875 59.94125,24.04875 59.94175,24.048 59.9425,24.0475 59.94275,24.0465 59.94225,24.046 59.94225,24.04575 59.9425,24.04525 59.94225,24.04725 59.942))";
Polygon polygon = (Polygon)SimpleWKTShapeParser.parse(wkt);
assertTrue(Tessellator.tessellate(polygon).size() == 8);
}
} }