parry2d/mass_properties/
mass_properties_trimesh2d.rs

1use crate::mass_properties::MassProperties;
2use crate::math::{Point, Real};
3use crate::shape::Triangle;
4
5impl MassProperties {
6    /// Computes the mass properties of a triangle-mesh.
7    pub fn from_trimesh(
8        density: Real,
9        vertices: &[Point<Real>],
10        indices: &[[u32; 3]],
11    ) -> MassProperties {
12        let (area, com) = trimesh_area_and_center_of_mass(vertices, indices);
13
14        if area == 0.0 {
15            return MassProperties::new(com, 0.0, 0.0);
16        }
17
18        let mut itot = 0.0;
19
20        for idx in indices {
21            let triangle = Triangle::new(
22                vertices[idx[0] as usize],
23                vertices[idx[1] as usize],
24                vertices[idx[2] as usize],
25            );
26
27            // TODO: is the parallel axis theorem correctly applied here?
28            let area = triangle.area();
29            let ipart = triangle.unit_angular_inertia();
30            itot += ipart * area;
31        }
32
33        Self::new(com, area * density, itot * density)
34    }
35}
36
37/// Computes the area and center-of-mass of a triangle-mesh.
38pub fn trimesh_area_and_center_of_mass(
39    vertices: &[Point<Real>],
40    indices: &[[u32; 3]],
41) -> (Real, Point<Real>) {
42    let mut res = Point::origin();
43    let mut areasum = 0.0;
44
45    for idx in indices {
46        let triangle = Triangle::new(
47            vertices[idx[0] as usize],
48            vertices[idx[1] as usize],
49            vertices[idx[2] as usize],
50        );
51        let area = triangle.area();
52        let center = triangle.center();
53
54        res += center.coords * area;
55        areasum += area;
56    }
57
58    if areasum == 0.0 {
59        (areasum, res)
60    } else {
61        (areasum, res / areasum)
62    }
63}