centerOfMass function
Feature<Point>
centerOfMass(
- GeoJSONObject geoJson, {
- Map<
String, dynamic> ? properties = const {},
Computes the center of mass of any GeoJSON object and returns it as a Feature<Point>.
Handles the following geometry types:
-
Point: returns the point itself.
-
LineString: returns the average of its vertices.
-
Polygon: uses the geometric centroid formula weighted by area.
-
MultiPolygon: computes a weighted average of each polygon's center of mass by area.
-
All other types: falls back to centroid.
-
geoJsonthe GeoJSON object to compute the center of mass for. -
propertiesoptional properties to attach to the returned Feature.
Implementation
Feature<Point> centerOfMass(
GeoJSONObject geoJson, {
Map<String, dynamic>? properties = const {},
}) {
GeometryObject? geometry;
if (geoJson is Feature) {
geometry = geoJson.geometry;
} else if (geoJson is GeometryObject) {
geometry = geoJson;
} else {
return centroid(geoJson);
}
if (geometry is Point) {
return Feature<Point>(
geometry: Point(coordinates: geometry.coordinates),
properties: properties,
);
}
if (geometry is LineString) {
// line center = average of vertices
final coords = geometry.coordinates;
final n = coords.length;
double sx = 0, sy = 0;
for (final p in coords) {
sx += p.lng;
sy += p.lat;
}
return Feature<Point>(
geometry: Point(coordinates: Position(sx / n, sy / n)),
properties: properties,
);
}
if (geometry is Polygon) {
return _centerOfMassPolygon(geometry, properties: properties);
}
if (geometry is MultiPolygon) {
double totalArea = 0.0;
double sx = 0.0;
double sy = 0.0;
for (final polygonCoords in geometry.coordinates) {
final poly = Polygon(coordinates: polygonCoords);
final comFeature = _centerOfMassPolygon(poly, properties: properties);
final com = comFeature.geometry!.coordinates;
// Compute polygon area
final area = _polygonArea(polygonCoords.first);
totalArea += area;
sx += com.lng * area;
sy += com.lat * area;
}
if (totalArea == 0) {
// all polygons degenerate -> average of all vertices
final allVerts = geometry.coordinates.expand((p) => p.first).toList();
final n = allVerts.length;
double ax = 0, ay = 0;
for (final v in allVerts) {
ax += v.lng;
ay += v.lat;
}
return Feature<Point>(
geometry: Point(coordinates: Position(ax / n, ay / n)),
properties: properties,
);
}
final center = Position(sx / totalArea, sy / totalArea);
return Feature<Point>(
geometry: Point(coordinates: center),
properties: properties,
);
}
// fallback
return centroid(geoJson);
}