parry2d/utils/center.rs
1use crate::math::{Real, Vector};
2
3/// Computes the geometric center (centroid) of a set of points.
4///
5/// The center is calculated by averaging all the point coordinates. This is also known as
6/// the centroid or barycenter of the point cloud. All points are weighted equally.
7///
8/// # Arguments
9///
10/// * `pts` - A slice of points. Must contain at least one point.
11///
12/// # Returns
13///
14/// The geometric center as a `Vector`.
15///
16/// # Panics
17///
18/// Panics if the input slice is empty.
19///
20/// # Examples
21///
22/// ## 2D Example
23///
24/// ```
25/// # #[cfg(all(feature = "dim2", feature = "f32"))] {
26/// use parry2d::utils::center;
27/// use parry2d::math::Vector;
28///
29/// let points = vec![
30/// Vector::new(0.0, 0.0),
31/// Vector::new(2.0, 0.0),
32/// Vector::new(2.0, 2.0),
33/// Vector::new(0.0, 2.0),
34/// ];
35///
36/// let c = center(&points);
37///
38/// // The center of a square is at its middle
39/// assert!((c.x - 1.0).abs() < 1e-6);
40/// assert!((c.y - 1.0).abs() < 1e-6);
41/// # }
42/// ```
43///
44/// ## 3D Example
45///
46/// ```
47/// # #[cfg(all(feature = "dim3", feature = "f32"))] {
48/// use parry3d::utils::center;
49/// use parry3d::math::Vector;
50///
51/// let points = vec![
52/// Vector::new(0.0, 0.0, 0.0),
53/// Vector::new(4.0, 0.0, 0.0),
54/// Vector::new(0.0, 4.0, 0.0),
55/// ];
56///
57/// let c = center(&points);
58///
59/// // The center of these three points
60/// assert!((c.x - 4.0 / 3.0).abs() < 1e-6);
61/// assert!((c.y - 4.0 / 3.0).abs() < 1e-6);
62/// assert!(c.z.abs() < 1e-6);
63/// # }
64/// ```
65///
66/// ## Single Vector
67///
68/// ```
69/// # #[cfg(all(feature = "dim2", feature = "f32"))] {
70/// use parry2d::utils::center;
71/// use parry2d::math::Vector;
72///
73/// let points = vec![Vector::new(5.0, 10.0)];
74/// let c = center(&points);
75///
76/// // The center of a single point is the point itself
77/// assert_eq!(c, points[0]);
78/// # }
79/// ```
80#[inline]
81pub fn center(pts: &[Vector]) -> Vector {
82 assert!(
83 !pts.is_empty(),
84 "Cannot compute the center of less than 1 point."
85 );
86
87 let denom: Real = 1.0 / (pts.len() as Real);
88
89 let mut piter = pts.iter();
90 let mut res = *piter.next().unwrap() * denom;
91
92 for pt in piter {
93 res += pt * denom;
94 }
95
96 res
97}