diff --git a/modules/core/src/main/java/org/locationtech/jts/algorithm/Centroid.java b/modules/core/src/main/java/org/locationtech/jts/algorithm/Centroid.java
index e82125c123..85e364c403 100644
--- a/modules/core/src/main/java/org/locationtech/jts/algorithm/Centroid.java
+++ b/modules/core/src/main/java/org/locationtech/jts/algorithm/Centroid.java
@@ -151,9 +151,8 @@ else if (ptCount > 0){
return cent;
}
- private void setBasePoint(Coordinate basePt)
+ private void setAreaBasePoint(Coordinate basePt)
{
- if (this.areaBasePt == null)
this.areaBasePt = basePt;
}
@@ -168,7 +167,7 @@ private void add(Polygon poly)
private void addShell(Coordinate[] pts)
{
if (pts.length > 0)
- setBasePoint(pts[0]);
+ setAreaBasePoint(pts[0]);
boolean isPositiveArea = ! CGAlgorithms.isCCW(pts);
for (int i = 0; i < pts.length - 1; i++) {
addTriangle(areaBasePt, pts[i], pts[i+1], isPositiveArea);
diff --git a/modules/core/src/test/java/org/locationtech/jts/algorithm/CentroidTest.java b/modules/core/src/test/java/org/locationtech/jts/algorithm/CentroidTest.java
new file mode 100644
index 0000000000..86b48a1454
--- /dev/null
+++ b/modules/core/src/test/java/org/locationtech/jts/algorithm/CentroidTest.java
@@ -0,0 +1,50 @@
+package org.locationtech.jts.algorithm;
+
+import junit.framework.TestCase;
+import org.locationtech.jts.geom.Coordinate;
+import org.locationtech.jts.geom.Geometry;
+import org.locationtech.jts.io.WKTReader;
+
+public class CentroidTest extends TestCase {
+
+ private static final double TOLERANCE = 1e-10;
+
+ public CentroidTest(String name) {
+ super(name);
+ }
+
+ /** Compute the centroid of a geometry as an area-weighted average of the centroids
+ * of its components.
+ *
+ * @param g a polygonal geometry
+ * @return Coordinate of the geometry's centroid
+ */
+ private static Coordinate areaWeightedCentroid(Geometry g) {
+ double totalArea = g.getArea();
+ double cx = 0;
+ double cy = 0;
+
+ for(int i = 0; i < g.getNumGeometries(); i++) {
+ Geometry component = g.getGeometryN(i);
+ double areaFraction = component.getArea() / totalArea;
+
+ Coordinate componentCentroid = component.getCentroid().getCoordinate();
+
+ cx += areaFraction * componentCentroid.x;
+ cy += areaFraction * componentCentroid.y;
+ }
+
+ return new Coordinate(cx, cy);
+ }
+
+ public void testCentroidMultiPolygon() throws Exception {
+ // Verify that the computed centroid of a MultiPolygon is equivalent to the
+ // area-weighted average of its components.
+ Geometry g = new WKTReader().read(
+ "MULTIPOLYGON ((( -92.661322 36.58994900000003, -92.66132199999993 36.58994900000005, -92.66132199999993 36.589949000000004, -92.661322 36.589949, -92.661322 36.58994900000003)), (( -92.65560500000008 36.58708800000005, -92.65560499999992 36.58708800000005, -92.65560499998745 36.587087999992576, -92.655605 36.587088, -92.65560500000008 36.58708800000005 )), (( -92.65512450000065 36.586800000000466, -92.65512449999994 36.58680000000004, -92.65512449998666 36.5867999999905, -92.65512450000065 36.586800000000466 )))"
+ );
+
+ assertTrue(areaWeightedCentroid(g).equals2D(g.getCentroid().getCoordinate(), TOLERANCE));
+ }
+
+}
\ No newline at end of file
diff --git a/modules/tests/src/test/resources/testxml/general/TestCentroid.xml b/modules/tests/src/test/resources/testxml/general/TestCentroid.xml
index 7ddc4e93a3..068b6177f3 100644
--- a/modules/tests/src/test/resources/testxml/general/TestCentroid.xml
+++ b/modules/tests/src/test/resources/testxml/general/TestCentroid.xml
@@ -242,6 +242,30 @@
POINT (56.52883333335 25.21033333335)
-
+
+ A - almost degenerate MultiPolygon
+
+ MULTIPOLYGON (((
+ -92.661322 36.58994900000003,
+ -92.66132199999993 36.58994900000005,
+ -92.66132199999993 36.589949000000004,
+ -92.661322 36.589949,
+ -92.661322 36.58994900000003)),
+ ((
+ -92.65560500000008 36.58708800000005,
+ -92.65560499999992 36.58708800000005,
+ -92.65560499998745 36.587087999992576,
+ -92.655605 36.587088,
+ -92.65560500000008 36.58708800000005
+ )),
+ ((
+ -92.65512450000065 36.586800000000466,
+ -92.65512449999994 36.58680000000004,
+ -92.65512449998666 36.5867999999905,
+ -92.65512450000065 36.586800000000466
+ )))
+
+ POINT (-92.6553838608954 36.58695407733924)
+