Skip to content

Commit 45241aa

Browse files
authored
Fix bug filtering collinear points in polygon decomposition (#81155) (#81241)
1 parent 226091f commit 45241aa

File tree

2 files changed

+27
-19
lines changed

2 files changed

+27
-19
lines changed

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

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -88,18 +88,9 @@ private static LinearRing filterRing(LinearRing linearRing) {
8888
int numPoints = linearRing.length();
8989
int count = 2;
9090
for (int i = 1; i < numPoints - 1; i++) {
91-
if (linearRing.getLon(i - 1) == linearRing.getLon(i)) {
92-
if (linearRing.getLat(i - 1) == linearRing.getLat(i)) {
93-
// same point
94-
continue;
95-
}
96-
if (linearRing.getLon(i - 1) == linearRing.getLon(i + 1)
97-
&& linearRing.getLat(i - 1) > linearRing.getLat(i) != linearRing.getLat(i + 1) > linearRing.getLat(i)) {
98-
// coplanar
99-
continue;
100-
}
91+
if (skipPoint(linearRing, i) == false) {
92+
count++;
10193
}
102-
count++;
10394
}
10495
if (numPoints == count) {
10596
return linearRing;
@@ -111,19 +102,31 @@ private static LinearRing filterRing(LinearRing linearRing) {
111102
lons[0] = lons[count - 1] = linearRing.getLon(0);
112103
count = 0;
113104
for (int i = 1; i < numPoints - 1; i++) {
114-
if (linearRing.getLon(i - 1) == linearRing.getLon(i)) {
115-
if (linearRing.getLat(i - 1) == linearRing.getLat(i) || linearRing.getLon(i - 1) == linearRing.getLon(i + 1)) {
116-
// filter
117-
continue;
118-
}
105+
if (skipPoint(linearRing, i) == false) {
106+
count++;
107+
lats[count] = linearRing.getLat(i);
108+
lons[count] = linearRing.getLon(i);
119109
}
120-
count++;
121-
lats[count] = linearRing.getLat(i);
122-
lons[count] = linearRing.getLon(i);
123110
}
124111
return new LinearRing(lons, lats);
125112
}
126113

114+
private static boolean skipPoint(LinearRing linearRing, int i) {
115+
if (linearRing.getLon(i - 1) == linearRing.getLon(i)) {
116+
if (linearRing.getLat(i - 1) == linearRing.getLat(i)) {
117+
// same point
118+
return true;
119+
}
120+
if (linearRing.getLon(i - 1) == linearRing.getLon(i + 1)
121+
&& linearRing.getLat(i - 1) > linearRing.getLat(i) != linearRing.getLat(i + 1) > linearRing.getLat(i)) {
122+
// collinear - we only remove points that go in the same direction. So latitudes [1,2,3] we would want
123+
// to remove 1 but for [1,2,-1] we don't.
124+
return true;
125+
}
126+
}
127+
return false;
128+
}
129+
127130
private static void validateHole(LinearRing shell, LinearRing hole) {
128131
Set<Point> exterior = new HashSet<>();
129132
Set<Point> interior = new HashSet<>();

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,11 @@ public void testPolygonOrientation() throws IOException, ParseException {
484484
expected("POLYGON ((20 10, -20 10, -20 0, 20 0, 20 10)))"),
485485
actual(polygon(randomBoolean() ? null : randomBoolean(), 20, 0, 20, 10, -20, 10, -20, 0, 20, 0), randomBoolean())
486486
);
487+
488+
assertEquals(
489+
expected("POLYGON ((180 29, 180 38, 180 56, 180 53, 178 47, 177 23, 180 29))"),
490+
actual("POLYGON ((180 38, 180.0 56, 180.0 53, 178 47, 177 23, 180 29, 180 36, 180 37, 180 38))", randomBoolean())
491+
);
487492
}
488493

489494
public void testInvalidSelfCrossingPolygon() {

0 commit comments

Comments
 (0)