Closed jaumard closed 2 months ago
Sorry for the late answer, but if you have not found an answer yet here some hints for current capabilities of the library.
See blog post: https://medium.com/@navibyte/geospatial-tools-for-dart-version-1-0-published-0f9673e510b3
There is a section about Operators and functions on cartesian positions.
A PositionSeries containing a closed linear ring (or simple polygon) could be created for example:
// a closed linear ring with positions in the counterclockwise (CCW) order
final polygon = [
[1.0, 6.0].xy,
[3.0, 1.0].xy,
[7.0, 2.0].xy,
[4.0, 4.0].xy,
[8.0, 5.0].xy,
[1.0, 6.0].xy,
].series();
Now you can calculate a centroid point of such a polygon, this sample prints coordinates:
// the centroid position of a polygon - prints "3.9,3.7"
print(polygon.centroid2D()!.toText(decimals: 1));
See source code for a position series, it has centroid2D method:
/// Returns the centroid of a geometry represented by this position series
/// calculated in a cartesian 2D plane.
///
/// The *centroid* is - as by definition - *a geometric center of mass of a
/// geometry*.
///
/// The centroid is computed according to [dimensionality]:
/// * `Dimensionality.volymetric`: not supported, works as `areal`
/// * `Dimensionality.areal`: weighted by the area with this position series
/// representing a polygon with positions in the counterclockwise (CCW)
/// order.
/// * `Dimensionality.linear`: computed from midpoints of line segments that
/// are weighted by the length of each line segment.
/// * `Dimensionality.punctual`: the arithmetic mean of all separate
/// positions in this series.
///
/// Returns null if a centroid position could not be calculated.
///
/// See also [Centroid](https://en.wikipedia.org/wiki/Centroid) in Wikipedia.
Position? centroid2D({
Dimensionality dimensionality = Dimensionality.areal,
}) {
final topoDim = dimensionality.topologicalDimension;
final posCount = positionCount;
// Areal geometry (weighted by area triangles).
if (topoDim >= 2 && posCount >= 3) {
// See "Of a polygon" in https://en.wikipedia.org/wiki/Centroid
var area = 0.0;
var cx = 0.0;
var cy = 0.0;
var x1 = x(0);
var y1 = y(0);
for (var i = 1; i <= posCount; i++) {
final isLast = i == posCount;
final x2 = x(isLast ? 0 : i);
final y2 = y(isLast ? 0 : i);
final shoelace = x1 * y2 - x2 * y1;
area += shoelace;
cx += (x1 + x2) * shoelace;
cy += (y1 + y2) * shoelace;
x1 = x2;
y1 = y2;
}
if (area.abs() > 0.0) {
final area6 = 6.0 * (area / 2.0);
return Position.create(
x: cx / area6,
y: cy / area6,
);
}
}
// Linear geometry (weighted by line segments).
if (topoDim >= 1 && posCount >= 2) {
var length = 0.0;
var cx = 0.0;
var cy = 0.0;
var x1 = x(0);
var y1 = y(0);
for (var i = 1; i < posCount; i++) {
final x2 = x(i);
final y2 = y(i);
final dx = x2 - x1;
final dy = y2 - y1;
final segmentLength = math.sqrt(dx * dx + dy * dy);
if (segmentLength > 0.0) {
length += segmentLength;
cx += segmentLength * (x1 + x2) / 2.0;
cy += segmentLength * (y1 + y2) / 2.0;
}
x1 = x2;
y1 = y2;
}
if (length > 0.0) {
return Position.create(
x: cx / length,
y: cy / length,
);
}
}
// Punctual geometry (arithmethic mean of all points).
if (posCount >= 1) {
var cx = 0.0;
var cy = 0.0;
for (var i = 0; i < posCount; i++) {
cx += x(i);
cy += y(i);
}
return Position.create(
x: cx / posCount,
y: cy / posCount,
);
}
// could not calculate
return null;
}
A centroid for a closed linear ring of positions (or a simple polygon) might be center point asked.
If you have a Polygon geometry object, then you should access an outer linear ring of a polygon using exterior member, and use centroid2D method to get a centroid position for that.
However currently not supported calculating a centroid for:
Implementing these might be a good possible future feature to add.
Implemented in geobase version 1.1.0, see milestone.
Hello,
I was hoping to find a
.center
available on the geometry collection or polygon but look like it doesn't exist.Do you know any way to have that center ? Or calculate it?