6

I've imported some polygons (ways) from OpenStreetMap and now want to calculate the centroids of them.

For this purpose I wrote following code:

    final List<Point2D.Double> points = getPoints();
    final Point2D.Double actualCentroid = calculateCentroidOurWay(points);

    LOGGER.debug("Centroid, x: " + actualCentroid.x);
    LOGGER.debug("Centroid, y: " + actualCentroid.y);

private Point.Double calculateCentroidOurWay(final List<Point2D.Double> aPoints) {
    final Building objectUnderTest = new Building();

    objectUnderTest.setPolygon(new Polygon(aPoints));

    return objectUnderTest.calculateCentroid();
}

@Override
public Point2D.Double calculateCentroid() {
    double x = 0.;
    double y = 0.;
    double area = 0.;

    for (int i = 0; i < polygon.getPoints().size() - 1; i++) {
        final Point2D.Double point = polygon.getPoints().get(i);
        final Point2D.Double pointN = polygon.getPoints().get(i + 1);

        final double temp = point.getX() * pointN.getY() - pointN.getX() * point
                .getY();
        x += (point.getX() + pointN.getX()) * temp;

        y += (point.getY() + pointN.getY()) * temp;

        area += temp;
    }

    area /= 2.;

    x *= 1 / 6. * area;
    y *= 1 / 6. * area;

    return new Point2D.Double(x, y);
}


private List<Point.Double> getPoints() {
    final List<Point.Double> points = new LinkedList<>();

    points.add(new Point.Double(132.1764353, 43.3539477));
    points.add(new Point.Double(132.1771393, 43.3539409));
    points.add(new Point.Double(132.177145, 43.3542587));
    points.add(new Point.Double(132.1768224, 43.3542618));
    points.add(new Point.Double(132.1768183, 43.3540332));
    points.add(new Point.Double(132.1766516, 43.3540348));
    points.add(new Point.Double(132.1766564, 43.3542949));
    points.add(new Point.Double(132.176566, 43.3542957));
    points.add(new Point.Double(132.1765705, 43.3545391));
    points.add(new Point.Double(132.1769718, 43.3545353));
    points.add(new Point.Double(132.1769691, 43.3543859));
    points.add(new Point.Double(132.177131, 43.3543843));
    points.add(new Point.Double(132.1771321, 43.3544446));
    points.add(new Point.Double(132.177341, 43.3544426));
    points.add(new Point.Double(132.1773296, 43.3538152));
    points.add(new Point.Double(132.176433, 43.3538238));
    points.add(new Point.Double(132.1764353, 43.3539477));
    return points;
}

The result of the calculation is

Centroid, x: 1.8787362164666136E-11
Centroid, y: 6.162273026564668E-12

which is obviously wrong (it's not a latitude/longitude pair).

When I use Java Topology Suite, it returns same results.

private Coordinate calculateJtsCentroid(final List<Point2D.Double> aPoints) {
    final CentroidPoint centroidPoint = new CentroidPoint();

    for (final Point.Double curPoint : aPoints) {
        centroidPoint.add(new Coordinate(curPoint.x, curPoint.y));
    }

    return centroidPoint.getCentroid();
}

How should I change my code in order to get the centroid of the polygon as a point identified by latitude and longitude?

0

1 Answer 1

0

Since you have the latitudes and longitudes of each point you can use the Finite Set of Points method indicated on Wikipedia. I think something like this might work.

public Point2D.Double calculateCentroid() {
    double x = 0.;
    double y = 0.;
    int pointCount = polygon.getPoints().size();
    for (int i = 0;i < pointCount - 1;i++){
        final Point2D.Double point = polygon.getPoints().get(i);
        x += point.getX();
        y += point.getY();
    }

    x = x/pointCount;
    y = y/pointCount;

    return new Point2D.Double(x, y);
}

Basically you just need to average the x and y separately, then create a new point with those averages as the coordinates.

2
  • 5
    Thank you for your contribution! This would be the centroid of the polygon's vertices, not of the polygon itself, assuming the latitudes and longitudes do not vary a lot (for then you would have to account for the spherical geometry). The code in the question makes it clear the polygon's centroid (center of mass) is desired instead. See gis.stackexchange.com/questions/22739/… for an explanation of the distinction.
    – whuber
    Commented Nov 13, 2013 at 21:24
  • 1
    Oops. You're right.
    – stuporglue
    Commented Nov 13, 2013 at 21:28

Not the answer you're looking for? Browse other questions tagged or ask your own question.