Skip to content

Commit

Permalink
Improve MultiPolygon centroid robustness (#118)
Browse files Browse the repository at this point in the history
* Improve MultiPolygon centroid robustness

Do this by allowing each polygon shell to set its own origin point,
instead of re-using the origin point from the first polygon in
the geometry.

Signed-off-by: Daniel Baston <[email protected]>

* Refactor test case

Signed-off-by: Daniel Baston <[email protected]>

* Rename method for clarity

* Fix formatting of tolerance constant
  • Loading branch information
dbaston authored and dr-jts committed Aug 22, 2017
1 parent c39f7d2 commit b430ca9
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand All @@ -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);
Expand Down
Original file line number Diff line number Diff line change
@@ -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));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,30 @@
<test><op name="getCentroid" arg1="A" > POINT (56.52883333335 25.21033333335) </op></test>
</case>


<case>
<desc>A - almost degenerate MultiPolygon</desc>
<a>
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
)))
</a>
<test><op name="getCentroid" arg1="A" >POINT (-92.6553838608954 36.58695407733924)</op></test>
</case>

</run>

0 comments on commit b430ca9

Please sign in to comment.