Skip to content

Commit 3f723a4

Browse files
authored
GeoPolygonDecomposer might fail due to numerical errors when calculating intersection with the dateline (#82953)
This change make sure that our intersection point lies either +180 or -180 always.
1 parent 9be18cb commit 3f723a4

File tree

2 files changed

+46
-18
lines changed

2 files changed

+46
-18
lines changed

server/src/main/java/org/elasticsearch/common/geo/GeoPolygonDecomposer.java

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -160,18 +160,6 @@ private static void validateHole(LinearRing shell, LinearRing hole) {
160160
}
161161
}
162162

163-
private static Point position(Point p1, Point p2, double position) {
164-
if (position == 0) {
165-
return p1;
166-
} else if (position == 1) {
167-
return p2;
168-
} else {
169-
final double x = p1.getX() + position * (p2.getX() - p1.getX());
170-
final double y = p1.getY() + position * (p2.getY() - p1.getY());
171-
return new Point(x, y);
172-
}
173-
}
174-
175163
private static int createEdges(
176164
int component,
177165
boolean orientation,
@@ -420,7 +408,7 @@ private static int intersections(double dateline, Edge[] edges) {
420408

421409
double position = intersection(p1.getX(), p2.getX(), dateline);
422410
if (Double.isNaN(position) == false) {
423-
edges[i].intersection(position);
411+
edges[i].setIntersection(position, dateline);
424412
numIntersections++;
425413
maxComponent = Math.max(maxComponent, edges[i].component);
426414
}
@@ -781,13 +769,20 @@ void setNext(Edge next) {
781769
}
782770

783771
/**
784-
* Set the intersection of this line segment to the given position
772+
* Set the intersection of this line segment with the given dateline
785773
*
786774
* @param position position of the intersection [0..1]
787-
* @return the {@link Point} of the intersection
775+
* @param dateline of the intersection
788776
*/
789-
Point intersection(double position) {
790-
return intersect = position(coordinate, next.coordinate, position);
777+
void setIntersection(double position, double dateline) {
778+
if (position == 0) {
779+
this.intersect = coordinate;
780+
} else if (position == 1) {
781+
this.intersect = next.coordinate;
782+
} else {
783+
final double y = coordinate.getY() + position * (next.coordinate.getY() - coordinate.getY());
784+
this.intersect = new Point(dateline, y);
785+
}
791786
}
792787

793788
@Override

server/src/test/java/org/elasticsearch/common/geo/GeometryNormalizerTests.java

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,7 @@ public void testPolygon() {
358358
polygon = new Polygon(new LinearRing(new double[] { 1, 0, 0, 1, 1 }, new double[] { 1, 1, 0, 0, 1 }));
359359
// for some reason, the normalizer always changes the order of the points
360360
indexed = new Polygon(new LinearRing(new double[] { 0, 0, 1, 1, 0 }, new double[] { 1, 0, 0, 1, 1 }));
361-
;
361+
362362
assertEquals(indexed, GeometryNormalizer.apply(Orientation.CCW, polygon));
363363
assertEquals(false, GeometryNormalizer.needsNormalize(Orientation.CCW, polygon));
364364

@@ -426,4 +426,37 @@ public void testMultiPolygon() {
426426
assertEquals(indexed, GeometryNormalizer.apply(Orientation.CCW, multiPolygon));
427427
assertEquals(true, GeometryNormalizer.needsNormalize(Orientation.CCW, multiPolygon));
428428
}
429+
430+
public void testIssue82840() {
431+
Polygon polygon = new Polygon(
432+
new LinearRing(
433+
new double[] { -143.10690080319134, -143.10690080319134, 62.41055750853541, -143.10690080319134 },
434+
new double[] { -90.0, -30.033129816260214, -30.033129816260214, -90.0 }
435+
)
436+
);
437+
MultiPolygon indexedCCW = new MultiPolygon(
438+
List.of(
439+
new Polygon(
440+
new LinearRing(
441+
new double[] { 180.0, 180.0, 62.41055750853541, 180.0 },
442+
new double[] { -75.67887564489237, -30.033129816260214, -30.033129816260214, -75.67887564489237 }
443+
)
444+
),
445+
new Polygon(
446+
new LinearRing(
447+
new double[] { -180.0, -180.0, -143.10690080319134, -143.10690080319134, -180.0 },
448+
new double[] { -30.033129816260214, -75.67887564489237, -90.0, -30.033129816260214, -30.033129816260214 }
449+
)
450+
)
451+
)
452+
);
453+
assertEquals(indexedCCW, GeometryNormalizer.apply(Orientation.CCW, polygon));
454+
Polygon indexedCW = new Polygon(
455+
new LinearRing(
456+
new double[] { -143.10690080319134, 62.41055750853541, -143.10690080319134, -143.10690080319134 },
457+
new double[] { -30.033129816260214, -30.033129816260214, -90.0, -30.033129816260214 }
458+
)
459+
);
460+
assertEquals(indexedCW, GeometryNormalizer.apply(Orientation.CW, polygon));
461+
}
429462
}

0 commit comments

Comments
 (0)