LUCENE-9239: Circle2D#WithinTriangle detects properly if a triangle is Within distance. (#1280)

This commit is contained in:
Ignacio Vera 2020-03-03 06:44:35 +01:00 committed by GitHub
parent 17c576a36f
commit b732ce7002
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 42 additions and 36 deletions

View File

@ -222,6 +222,8 @@ Bug Fixes
* LUCENE-9243: Add fudge factor when creating a bounding box of a XYCircle. (Ignacio Vera)
* LUCENE-9239: Circle2D#WithinTriangle detects properly if a triangle is Within distance. (Ignacio Vera)
Other
---------------------

View File

@ -102,50 +102,30 @@ class Circle2D implements Component2D {
return WithinRelation.DISJOINT;
}
// if any of the points is inside the polygon, the polygon cannot be within this indexed
// shape because points belong to the original indexed shape.
// if any of the points is inside the circle then we cannot be within this
// indexed shape
if (contains(ax, ay) || contains(bx, by) || contains(cx, cy)) {
return WithinRelation.NOTWITHIN;
}
WithinRelation relation = WithinRelation.DISJOINT;
// if any of the edges intersects an the edge belongs to the shape then it cannot be within.
// if it only intersects edges that do not belong to the shape, then it is a candidate
// we skip edges at the dateline to support shapes crossing it
if (calculator.intersectsLine(ax, ay, bx, by)) {
if (ab == true) {
return WithinRelation.NOTWITHIN;
} else {
relation = WithinRelation.CANDIDATE;
}
// we only check edges that belong to the original polygon. If we intersect any of them, then
// we are not within.
if (ab == true && calculator.intersectsLine(ax, ay, bx, by)) {
return WithinRelation.NOTWITHIN;
}
if (bc == true && calculator.intersectsLine(bx, by, cx, cy)) {
return WithinRelation.NOTWITHIN;
}
if (ca == true && calculator.intersectsLine(cx, cy, ax, ay)) {
return WithinRelation.NOTWITHIN;
}
if (calculator.intersectsLine(bx, by, cx, cy)) {
if (bc == true) {
return WithinRelation.NOTWITHIN;
} else {
relation = WithinRelation.CANDIDATE;
}
}
if (calculator.intersectsLine(cx, cy, ax, ay)) {
if (ca == true) {
return WithinRelation.NOTWITHIN;
} else {
relation = WithinRelation.CANDIDATE;
}
}
// if any of the edges crosses and edge that does not belong to the shape
// then it is a candidate for within
if (relation == WithinRelation.CANDIDATE) {
return WithinRelation.CANDIDATE;
}
// Check if shape is within the triangle
// check if center is within the triangle. This is the only check that returns this circle as a candidate but that is ol
// is fine as the center must be inside to be one of the triangles.
if (Component2D.pointInTriangle(minX, maxX, minY, maxY, calculator.geX(), calculator.getY(), ax, ay, bx, by, cx, cy) == true) {
return WithinRelation.CANDIDATE;
}
return relation;
return WithinRelation.DISJOINT;
}
/** relates an indexed line segment (a "flat triangle") with the polygon */

View File

@ -742,7 +742,6 @@ public class TestLatLonShape extends LuceneTestCase {
IOUtils.close(w, reader, dir);
}
public void testPointIndexAndDistanceQuery() throws Exception {
Directory dir = newDirectory();
RandomIndexWriter writer = new RandomIndexWriter(random(), dir);
@ -788,4 +787,29 @@ public class TestLatLonShape extends LuceneTestCase {
IOUtils.close(r, dir);
}
public void testLucene9239() throws Exception {
double[] lats = new double[] {-22.350172194105966, 90.0, 90.0, -22.350172194105966, -22.350172194105966};
double[] lons = new double[] {49.931598911327825, 49.931598911327825,51.40819689137876, 51.408196891378765, 49.931598911327825};
Polygon polygon = new Polygon(lats, lons);
Directory dir = newDirectory();
RandomIndexWriter writer = new RandomIndexWriter(random(), dir);
Document document = new Document();
addPolygonsToDoc(FIELDNAME, document, polygon);
writer.addDocument(document);
//// search
IndexReader r = writer.getReader();
writer.close();
IndexSearcher s = newSearcher(r);
Circle circle = new Circle(78.01086555431775, 0.9513280497489234, 1097753.4254892308);
// Circle is not within the polygon
Query q = LatLonShape.newDistanceQuery(FIELDNAME, QueryRelation.CONTAINS, circle);
assertEquals(0, s.count(q));
IOUtils.close(r, dir);
}
}