Skip to content

Commit 8f49dba

Browse files
author
uditswaroopa
committed
Improve logic to compute center of a polygon
1 parent 352348e commit 8f49dba

File tree

1 file changed

+59
-4
lines changed

1 file changed

+59
-4
lines changed

lib/src/layer/polygon_layer/label.dart

Lines changed: 59 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,65 @@ LatLng _computeLabelPosition(
8181

8282
/// Calculate the centroid of a given list of [LatLng] points.
8383
LatLng _computeCentroid(List<LatLng> points) {
84-
return LatLng(
85-
points.map((e) => e.latitude).average,
86-
points.map((e) => e.longitude).average,
87-
);
84+
if (points.isEmpty) {
85+
throw ArgumentError('Polygon must contain at least one point');
86+
}
87+
88+
if (points.length == 1) {
89+
return points[0];
90+
}
91+
92+
double signedArea = 0;
93+
double centroidX = 0;
94+
double centroidY = 0;
95+
96+
// For all vertices except last
97+
for (int i = 0; i < points.length - 1; i++) {
98+
final double x0 = points[i].longitude;
99+
final double y0 = points[i].latitude;
100+
final double x1 = points[i + 1].longitude;
101+
final double y1 = points[i + 1].latitude;
102+
103+
// Calculate signed area contribution of current vertex
104+
final double a = x0 * y1 - x1 * y0;
105+
signedArea += a;
106+
107+
// Accumulate centroid components weighted by signed area
108+
centroidX += (x0 + x1) * a;
109+
centroidY += (y0 + y1) * a;
110+
}
111+
112+
// Close the polygon by connecting last vertex to first
113+
final double x0 = points.last.longitude;
114+
final double y0 = points.last.latitude;
115+
final double x1 = points.first.longitude;
116+
final double y1 = points.first.latitude;
117+
final double a = x0 * y1 - x1 * y0;
118+
signedArea += a;
119+
centroidX += (x0 + x1) * a;
120+
centroidY += (y0 + y1) * a;
121+
122+
// Complete the signed area calculation
123+
signedArea *= 0.5;
124+
125+
// Calculate centroid coordinates
126+
centroidX /= 6 * signedArea;
127+
centroidY /= 6 * signedArea;
128+
129+
// Handle special case of zero area (collinear points)
130+
if (signedArea == 0) {
131+
// Default to average of all points
132+
double sumX = 0;
133+
double sumY = 0;
134+
for (final point in points) {
135+
sumX += point.longitude;
136+
sumY += point.latitude;
137+
}
138+
return LatLng(sumY / points.length, sumX / points.length);
139+
}
140+
141+
return LatLng(centroidY, centroidX);
142+
88143
}
89144

90145
/// Calculate the centroid of a given list of [LatLng] points with multiple worlds.

0 commit comments

Comments
 (0)