mirror of https://github.com/apache/lucene.git
LUCENE-9251: Filter equal edges with different value on isEdgeFromPolygon (#1290)
Fix bug in the polygon tessellator where edges with different value on #isEdgeFromPolygon were bot filtered out properly
This commit is contained in:
parent
b732ce7002
commit
c313365c5f
|
@ -224,6 +224,9 @@ Bug Fixes
|
||||||
|
|
||||||
* LUCENE-9239: Circle2D#WithinTriangle detects properly if a triangle is Within distance. (Ignacio Vera)
|
* LUCENE-9239: Circle2D#WithinTriangle detects properly if a triangle is Within distance. (Ignacio Vera)
|
||||||
|
|
||||||
|
* LUCENE-9251: Fix bug in the polygon tessellator where edges with different value on #isEdgeFromPolygon
|
||||||
|
were bot filtered out properly. (Ignacio Vera)
|
||||||
|
|
||||||
Other
|
Other
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
|
|
|
@ -435,7 +435,6 @@ final public class Tessellator {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
currEar = nextNode;
|
currEar = nextNode;
|
||||||
|
|
||||||
// If the whole polygon has been iterated over and no more ears can be found.
|
// If the whole polygon has been iterated over and no more ears can be found.
|
||||||
if (currEar == stop) {
|
if (currEar == stop) {
|
||||||
switch (state) {
|
switch (state) {
|
||||||
|
@ -915,13 +914,14 @@ final public class Tessellator {
|
||||||
continueIteration = false;
|
continueIteration = false;
|
||||||
nextNode = node.next;
|
nextNode = node.next;
|
||||||
prevNode = node.previous;
|
prevNode = node.previous;
|
||||||
//We can filter points when they are the same, if not and they are co-linear we can only
|
// we can filter points when:
|
||||||
//remove it if both edges have the same value in .isNextEdgeFromPolygon
|
if (isVertexEquals(node, nextNode) || // 1. they are the same,
|
||||||
if (isVertexEquals(node, nextNode) ||
|
isVertexEquals(prevNode, nextNode) || // 2.- each one starts and ends in each other
|
||||||
(prevNode.isNextEdgeFromPolygon == node.isNextEdgeFromPolygon &&
|
(prevNode.isNextEdgeFromPolygon == node.isNextEdgeFromPolygon && // 3.- they are co-linear and both edges have the same value in .isNextEdgeFromPolygon
|
||||||
area(prevNode.getX(), prevNode.getY(), node.getX(), node.getY(), nextNode.getX(), nextNode.getY()) == 0)) {
|
area(prevNode.getX(), prevNode.getY(), node.getX(), node.getY(), nextNode.getX(), nextNode.getY()) == 0)) {
|
||||||
// Remove the node
|
// Remove the node
|
||||||
removeNode(node, prevNode.isNextEdgeFromPolygon);
|
boolean nextEdgeFromPol = prevNode.isNextEdgeFromPolygon != node.isNextEdgeFromPolygon ? true : prevNode.isNextEdgeFromPolygon;
|
||||||
|
removeNode(node, nextEdgeFromPol);
|
||||||
node = end = prevNode;
|
node = end = prevNode;
|
||||||
|
|
||||||
if (node == nextNode) {
|
if (node == nextNode) {
|
||||||
|
|
|
@ -561,6 +561,18 @@ public class TestTessellator extends LuceneTestCase {
|
||||||
checkPolygon(wkt);
|
checkPolygon(wkt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nightly
|
||||||
|
public void testComplexPolygon40() throws Exception {
|
||||||
|
String wkt = GeoTestUtil.readShape("lucene-9251.wkt.gz");
|
||||||
|
Polygon polygon = (Polygon) SimpleWKTShapeParser.parse(wkt);
|
||||||
|
List<Tessellator.Triangle> tessellation = Tessellator.tessellate(polygon);
|
||||||
|
// calculate the area of big polygons have numerical error
|
||||||
|
assertEquals(area(polygon), area(tessellation), 1e-12);
|
||||||
|
for (Tessellator.Triangle t : tessellation) {
|
||||||
|
checkTriangleEdgesFromPolygon(polygon, t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void checkPolygon(String wkt) throws Exception {
|
private void checkPolygon(String wkt) throws Exception {
|
||||||
Polygon polygon = (Polygon) SimpleWKTShapeParser.parse(wkt);
|
Polygon polygon = (Polygon) SimpleWKTShapeParser.parse(wkt);
|
||||||
List<Tessellator.Triangle> tessellation = Tessellator.tessellate(polygon);
|
List<Tessellator.Triangle> tessellation = Tessellator.tessellate(polygon);
|
||||||
|
|
|
@ -16,10 +16,17 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.lucene.geo;
|
package org.apache.lucene.geo;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
import java.util.zip.GZIPInputStream;
|
||||||
|
|
||||||
import org.apache.lucene.util.NumericUtils;
|
import org.apache.lucene.util.NumericUtils;
|
||||||
import org.apache.lucene.util.SloppyMath;
|
import org.apache.lucene.util.SloppyMath;
|
||||||
|
@ -718,4 +725,26 @@ public class GeoTestUtil {
|
||||||
}
|
}
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** reads a shape from file */
|
||||||
|
public static String readShape(String name) throws IOException {
|
||||||
|
return Loader.LOADER.readShape(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Loader {
|
||||||
|
|
||||||
|
static Loader LOADER = new Loader();
|
||||||
|
|
||||||
|
String readShape(String name) throws IOException {
|
||||||
|
InputStream is = getClass().getResourceAsStream(name);
|
||||||
|
if (is == null) {
|
||||||
|
throw new FileNotFoundException("classpath resource not found: " + name);
|
||||||
|
}
|
||||||
|
if (name.endsWith(".gz")) {
|
||||||
|
is = new GZIPInputStream(is);
|
||||||
|
}
|
||||||
|
BufferedReader reader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
|
||||||
|
return reader.readLine();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
Loading…
Reference in New Issue