Skip to content

Commit 8b07747

Browse files
authored
Fix bug filtering collinear points in polygon decomposition (#81155)
1 parent 32ca555 commit 8b07747

2 files changed

Lines changed: 27 additions & 19 deletions

File tree

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

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -106,18 +106,9 @@ private static LinearRing filterRing(LinearRing linearRing) {
106106
int numPoints = linearRing.length();
107107
int count = 2;
108108
for (int i = 1; i < numPoints - 1; i++) {
109-
if (linearRing.getLon(i - 1) == linearRing.getLon(i)) {
110-
if (linearRing.getLat(i - 1) == linearRing.getLat(i)) {
111-
// same point
112-
continue;
113-
}
114-
if (linearRing.getLon(i - 1) == linearRing.getLon(i + 1)
115-
&& linearRing.getLat(i - 1) > linearRing.getLat(i) != linearRing.getLat(i + 1) > linearRing.getLat(i)) {
116-
// coplanar
117-
continue;
118-
}
109+
if (skipPoint(linearRing, i) == false) {
110+
count++;
119111
}
120-
count++;
121112
}
122113
if (numPoints == count) {
123114
return linearRing;
@@ -129,19 +120,31 @@ private static LinearRing filterRing(LinearRing linearRing) {
129120
lons[0] = lons[count - 1] = linearRing.getLon(0);
130121
count = 0;
131122
for (int i = 1; i < numPoints - 1; i++) {
132-
if (linearRing.getLon(i - 1) == linearRing.getLon(i)) {
133-
if (linearRing.getLat(i - 1) == linearRing.getLat(i) || linearRing.getLon(i - 1) == linearRing.getLon(i + 1)) {
134-
// filter
135-
continue;
136-
}
123+
if (skipPoint(linearRing, i) == false) {
124+
count++;
125+
lats[count] = linearRing.getLat(i);
126+
lons[count] = linearRing.getLon(i);
137127
}
138-
count++;
139-
lats[count] = linearRing.getLat(i);
140-
lons[count] = linearRing.getLon(i);
141128
}
142129
return new LinearRing(lons, lats);
143130
}
144131

132+
private static boolean skipPoint(LinearRing linearRing, int i) {
133+
if (linearRing.getLon(i - 1) == linearRing.getLon(i)) {
134+
if (linearRing.getLat(i - 1) == linearRing.getLat(i)) {
135+
// same point
136+
return true;
137+
}
138+
if (linearRing.getLon(i - 1) == linearRing.getLon(i + 1)
139+
&& linearRing.getLat(i - 1) > linearRing.getLat(i) != linearRing.getLat(i + 1) > linearRing.getLat(i)) {
140+
// collinear - we only remove points that go in the same direction. So latitudes [1,2,3] we would want
141+
// to remove 1 but for [1,2,-1] we don't.
142+
return true;
143+
}
144+
}
145+
return false;
146+
}
147+
145148
private static void validateHole(LinearRing shell, LinearRing hole) {
146149
Set<Point> exterior = new HashSet<>();
147150
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
@@ -193,6 +193,11 @@ public void testPolygonOrientation() throws IOException, ParseException {
193193
expected("POLYGON ((20 10, -20 10, -20 0, 20 0, 20 10)))"),
194194
actual(polygon(randomBoolean() ? null : randomBoolean(), 20, 0, 20, 10, -20, 10, -20, 0, 20, 0), randomBoolean())
195195
);
196+
197+
assertEquals(
198+
expected("POLYGON ((180 29, 180 38, 180 56, 180 53, 178 47, 177 23, 180 29))"),
199+
actual("POLYGON ((180 38, 180.0 56, 180.0 53, 178 47, 177 23, 180 29, 180 36, 180 37, 180 38))", randomBoolean())
200+
);
196201
}
197202

198203
public void testInvalidSelfCrossingPolygon() {

0 commit comments

Comments
 (0)