Skip to content

Commit 8c3a1b8

Browse files
committed
ignore infinite centroid values in CentroidCalculator (#52782)
there are times where small triangle areas within a polygon have really small areas 1e-11, while the whole polygon's area is zero. This results in an infinite valuation of the centroid point representing that triangle. This commit ignores the addition of such values Addresses #52774
1 parent 77f9bb6 commit 8c3a1b8

File tree

2 files changed

+47
-11
lines changed

2 files changed

+47
-11
lines changed

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

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -67,17 +67,20 @@ public CentroidCalculator(Geometry geometry) {
6767
* @param weight the associated weight of the coordinate
6868
*/
6969
private void addCoordinate(double x, double y, double weight, DimensionalShapeType dimensionalShapeType) {
70-
if (this.dimensionalShapeType == null || this.dimensionalShapeType == dimensionalShapeType) {
71-
compSumX.add(x * weight);
72-
compSumY.add(y * weight);
73-
compSumWeight.add(weight);
74-
this.dimensionalShapeType = dimensionalShapeType;
75-
} else if (dimensionalShapeType.compareTo(this.dimensionalShapeType) > 0) {
76-
// reset counters
77-
compSumX.reset(x * weight, 0);
78-
compSumY.reset(y * weight, 0);
79-
compSumWeight.reset(weight, 0);
80-
this.dimensionalShapeType = dimensionalShapeType;
70+
// x and y can be infinite due to really small areas and rounding problems
71+
if (Double.isFinite(x) && Double.isFinite(y)) {
72+
if (this.dimensionalShapeType == null || this.dimensionalShapeType == dimensionalShapeType) {
73+
compSumX.add(x * weight);
74+
compSumY.add(y * weight);
75+
compSumWeight.add(weight);
76+
this.dimensionalShapeType = dimensionalShapeType;
77+
} else if (dimensionalShapeType.compareTo(this.dimensionalShapeType) > 0) {
78+
// reset counters
79+
compSumX.reset(x * weight, 0);
80+
compSumY.reset(y * weight, 0);
81+
compSumWeight.reset(weight, 0);
82+
this.dimensionalShapeType = dimensionalShapeType;
83+
}
8184
}
8285
}
8386

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

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
import org.elasticsearch.geometry.Point;
2929
import org.elasticsearch.geometry.Polygon;
3030
import org.elasticsearch.geometry.ShapeType;
31+
import org.elasticsearch.geometry.utils.GeographyValidator;
32+
import org.elasticsearch.geometry.utils.WellKnownText;
3133
import org.elasticsearch.test.ESTestCase;
3234

3335
import java.util.Arrays;
@@ -39,6 +41,7 @@
3941
import static org.elasticsearch.common.geo.DimensionalShapeType.POINT;
4042
import static org.elasticsearch.common.geo.DimensionalShapeType.POLYGON;
4143
import static org.hamcrest.Matchers.anyOf;
44+
import static org.hamcrest.Matchers.closeTo;
4245
import static org.hamcrest.Matchers.equalTo;
4346

4447
public class CentroidCalculatorTests extends ESTestCase {
@@ -53,6 +56,36 @@ public void testPoint() {
5356
assertThat(calculator.getDimensionalShapeType(), equalTo(POINT));
5457
}
5558

59+
public void testPolygonWithSmallTrianglesOfZeroWeight() throws Exception {
60+
Geometry geometry = new WellKnownText(false, new GeographyValidator(true))
61+
.fromWKT("POLYGON((-4.385064 55.2259599,-4.385056 55.2259224,-4.3850466 55.2258994,-4.3849755 55.2258574," +
62+
"-4.3849339 55.2258589,-4.3847033 55.2258742,-4.3846805 55.2258818,-4.3846282 55.2259132,-4.3846215 55.2259247," +
63+
"-4.3846121 55.2259683,-4.3846147 55.2259798,-4.3846369 55.2260157,-4.3846472 55.2260241," +
64+
"-4.3846697 55.2260409,-4.3846952 55.2260562,-4.384765 55.22608,-4.3848199 55.2260861,-4.3848481 55.2260845," +
65+
"-4.3849245 55.2260761,-4.3849393 55.22607,-4.3849996 55.2260432,-4.3850131 55.2260364,-4.3850426 55.2259989," +
66+
"-4.385064 55.2259599),(-4.3850104 55.2259583,-4.385005 55.2259752,-4.384997 55.2259892,-4.3849339 55.2259981," +
67+
"-4.3849272 55.2259308,-4.3850016 55.2259262,-4.385005 55.2259377,-4.3850104 55.2259583)," +
68+
"(-4.3849996 55.2259193,-4.3847502 55.2259331,-4.3847548 55.2258921,-4.3848012 55.2258895," +
69+
"-4.3849219 55.2258811,-4.3849514 55.2258818,-4.3849728 55.2258933,-4.3849996 55.2259193)," +
70+
"(-4.3849917 55.2259984,-4.3849849 55.2260103,-4.3849771 55.2260192,-4.3849701 55.2260019,-4.3849917 55.2259984)," +
71+
"(-4.3846608 55.2259374,-4.384663 55.2259316,-4.3846711 55.2259201,-4.3846992 55.225904," +
72+
"-4.384718 55.2258941,-4.3847434 55.2258927,-4.3847314 55.2259407,-4.3849098 55.2259316,-4.3849098 55.2259492," +
73+
"-4.3848843 55.2259515,-4.3849017 55.2260119,-4.3849567 55.226005,-4.3849701 55.2260272,-4.3849299 55.2260486," +
74+
"-4.3849192 55.2260295,-4.384883 55.2260188,-4.3848776 55.2260119,-4.3848441 55.2260149,-4.3848441 55.2260226," +
75+
"-4.3847864 55.2260241,-4.384722 55.2259652,-4.3847053 55.2259706,-4.384683 55.225954,-4.3846608 55.2259374)," +
76+
"(-4.3846541 55.2259549,-4.384698 55.2259883,-4.3847173 55.2259828,-4.3847743 55.2260333,-4.3847891 55.2260356," +
77+
"-4.3848146 55.226031,-4.3848199 55.2260409,-4.3848387 55.2260417,-4.3848494 55.2260593,-4.3848092 55.2260616," +
78+
"-4.3847623 55.2260539,-4.3847341 55.2260432,-4.3847046 55.2260279,-4.3846738 55.2260062,-4.3846496 55.2259844," +
79+
"-4.3846429 55.2259737,-4.3846523 55.2259714,-4.384651 55.2259629,-4.3846541 55.2259549)," +
80+
"(-4.3846608 55.2259374,-4.3846559 55.2259502,-4.3846541 55.2259549,-4.3846608 55.2259374))");
81+
CentroidCalculator calculator = new CentroidCalculator(geometry);
82+
assertThat(calculator.getX(), closeTo( -4.3848, 1e-4));
83+
assertThat(calculator.getY(), closeTo(55.22595, 1e-4));
84+
assertThat(calculator.sumWeight(), closeTo(0, 1e-5));
85+
assertThat(calculator.getDimensionalShapeType(), equalTo(POLYGON));
86+
}
87+
88+
5689
public void testLine() {
5790
double[] y = new double[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
5891
double[] x = new double[] { 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 };

0 commit comments

Comments
 (0)