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-9251: Fix bug in the polygon tessellator where edges with different value on #isEdgeFromPolygon
|
||||
were bot filtered out properly. (Ignacio Vera)
|
||||
|
||||
Other
|
||||
---------------------
|
||||
|
||||
|
|
|
@ -435,7 +435,6 @@ final public class Tessellator {
|
|||
continue;
|
||||
}
|
||||
currEar = nextNode;
|
||||
|
||||
// If the whole polygon has been iterated over and no more ears can be found.
|
||||
if (currEar == stop) {
|
||||
switch (state) {
|
||||
|
@ -915,13 +914,14 @@ final public class Tessellator {
|
|||
continueIteration = false;
|
||||
nextNode = node.next;
|
||||
prevNode = node.previous;
|
||||
//We can filter points when they are the same, if not and they are co-linear we can only
|
||||
//remove it if both edges have the same value in .isNextEdgeFromPolygon
|
||||
if (isVertexEquals(node, nextNode) ||
|
||||
(prevNode.isNextEdgeFromPolygon == node.isNextEdgeFromPolygon &&
|
||||
// we can filter points when:
|
||||
if (isVertexEquals(node, nextNode) || // 1. they are the same,
|
||||
isVertexEquals(prevNode, nextNode) || // 2.- each one starts and ends in each other
|
||||
(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)) {
|
||||
// Remove the node
|
||||
removeNode(node, prevNode.isNextEdgeFromPolygon);
|
||||
boolean nextEdgeFromPol = prevNode.isNextEdgeFromPolygon != node.isNextEdgeFromPolygon ? true : prevNode.isNextEdgeFromPolygon;
|
||||
removeNode(node, nextEdgeFromPol);
|
||||
node = end = prevNode;
|
||||
|
||||
if (node == nextNode) {
|
||||
|
|
|
@ -561,6 +561,18 @@ public class TestTessellator extends LuceneTestCase {
|
|||
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 {
|
||||
Polygon polygon = (Polygon) SimpleWKTShapeParser.parse(wkt);
|
||||
List<Tessellator.Triangle> tessellation = Tessellator.tessellate(polygon);
|
||||
|
|
|
@ -16,10 +16,17 @@
|
|||
*/
|
||||
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.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
import org.apache.lucene.util.NumericUtils;
|
||||
import org.apache.lucene.util.SloppyMath;
|
||||
|
@ -718,4 +725,26 @@ public class GeoTestUtil {
|
|||
}
|
||||
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