Question: This means excluding the area(s) of any `interiorPolygons`.

Once one has the centroid of the outer `points` polygon, how does one (i.e., in the form of an Objective-C example) adjust the centroid by the subtractive `interiorPolygons`? Or is there a more elegant way to compute the centroid in one go?

If you help get the code working, it will be open sourced ([WIP here](https://gist.github.com/steakknife/265775a0a7613a012494)).

Might be helpful: 

1. <http://www.ecourses.ou.edu/cgi-bin/eBook.cgi?topic=st&chap_sec=07.2&page=case_sol>
2. <https://en.wikipedia.org/wiki/Centroid#Centroid_of_polygon>

Answer: 
Thinking about it today, it makes qualitative sense that adding each interior centroid ***weighted by area*** to the exterior centroid would arrive at something sensible. (A square with an interior polygon (hole) on the left side would displace the centroid right, directly proportional to the area of the hole.)

Not to scale: ![nothing to scale](https://content.screencast.com/users/zxcvxzcvxcv/folders/Jing/media/356136d4-4359-4561-9c1b-4d47f5f5a22e/00000068.png)

```
- (MKMapPoint)calculateCentroid
{
    switch (self.pointCount) {
        case 0: return MKMapPointMake(0.0,
                                      0.0);
        case 1: return MKMapPointMake(self.points[0].x,
                                      self.points[0].y);
        case 2: return MKMapPointMake((self.points[0].x + self.points[1].x) / 2.0,
                                      (self.points[0].y + self.points[1].y) / 2.0);

    }

    // onward implies pointCount >= 3

    MKMapPoint centroid;
    MKMapPoint *previousPoint = &(self.points[self.pointCount-1]); // for i=0, wrap around to the last point

    for (NSUInteger i = 0; i < self.pointCount; ++i) {
        MKMapPoint *point = &(self.points[i]);

        double delta = (previousPoint->x * point->y) - (point->x * previousPoint->y); // x[i-1]*y[i] + x[i]*y[i-1]

        centroid.x += (previousPoint->x + point->x) * delta; // (x[i-1] + x[i]) / delta
        centroid.y += (previousPoint->y + point->y) * delta; // (y[i-1] + y[i]) / delta

        previousPoint = point;
    }

    centroid.x /= 6.0 * self.area;
    centroid.y /= 6.0 * self.area;

    // interiorPolygons are holes (subtractive geometry model)
    for (MKPolygon *interiorPoly in self.interiorPolygons) {
        if (interiorPoly.area == 0.0) {
            continue; // avoid div-by-zero
        }

        centroid.x += interiorPoly.centroid.x / interiorPoly.area;
        centroid.y += interiorPoly.centroid.y / interiorPoly.area;
    }

    return centroid;
}

```
in Swift 5

```swift
private func centroidForCoordinates(_ coords: [CLLocationCoordinate2D]) -> CLLocationCoordinate2D? {
        guard let firstCoordinate = coordinates.first else {
            return nil
        }

        guard coords.count > 1 else {
            return firstCoordinate
        }

        var minX = firstCoordinate.longitude
        var maxX = firstCoordinate.longitude
        var minY = firstCoordinate.latitude
        var maxY = firstCoordinate.latitude

        for i in 1..<coords.count {
            let current = coords[i]
            if minX > current.longitude {
                minX = current.longitude
            } else if maxX < current.longitude {
                maxX = current.longitude
            } else if minY > current.latitude {
                minY = current.latitude
            } else if maxY < current.latitude {
                maxY = current.latitude
            }
        }

        let centerX = minX + ((maxX - minX) / 2)
        let centerY = minY + ((maxY - minY) / 2)
        return CLLocationCoordinate2D(latitude: centerY, longitude: centerX)
    }

```