mesh_geometry/metrics/
polygon.rs

1//! Polygon metrics: area and centroid for arbitrary planar polygons.
2//!
3//! This module provides functions to calculate the signed area and centroid of
4//! arbitrary planar polygons using the shoelace formula. The polygon vertices
5//! should be ordered either in a clockwise or counter-clockwise direction, and
6//!
7//! # Examples
8//!
9//! ```rust
10//! use mesh_geometry::{polygon_area, Point2};
11//! let tri = [
12//!     Point2::new(0.0_f64, 0.0_f64),
13//!     Point2::new(2.0_f64, 0.0_f64),
14//!     Point2::new(1.0_f64, 1.7320508_f64),
15//! ];
16//! let area = polygon_area(&tri);
17//! assert!((area - 1.7320508_f64).abs() < 1e-6);
18//! ```
19
20use crate::{Float, Point2};
21
22/// Signed area of an arbitrary planar polygon (shoelace formula).
23/// Vertices ordered CCW or CW, first and last need not repeat.
24pub fn polygon_area<T: Float>(verts: &[Point2<T>]) -> T {
25    let n = verts.len();
26    assert!(n >= 3, "polygon_area requires ≥3 vertices");
27    let mut sum = T::zero();
28    for i in 0..n {
29        let a = verts[i];
30        let b = verts[(i + 1) % n];
31        sum = sum + (a.x * b.y - b.x * a.y);
32    }
33    (sum * T::from(0.5).unwrap()).abs()
34}
35
36/// Centroid of a planar polygon: (Cx, Cy) = (1/(6A)) Σ (xi + xi+1)(xi yi+1 − xi+1 yi)
37pub fn polygon_centroid<T: Float>(verts: &[Point2<T>]) -> Point2<T> {
38    let n = verts.len();
39    assert!(n >= 3, "polygon_centroid requires ≥3 vertices");
40    let mut a_twice = T::zero();
41    let mut cx = T::zero();
42    let mut cy = T::zero();
43    for i in 0..n {
44        let xi = verts[i].x;
45        let yi = verts[i].y;
46        let xj = verts[(i + 1) % n].x;
47        let yj = verts[(i + 1) % n].y;
48        let cross = xi * yj - xj * yi;
49        a_twice = a_twice + cross;
50        cx = cx + (xi + xj) * cross;
51        cy = cy + (yi + yj) * cross;
52    }
53    let a = a_twice * T::from(0.5).unwrap();
54    let factor = T::one() / (T::from(6.0).unwrap() * a);
55    Point2::new(cx * factor, cy * factor)
56}