parry2d/mass_properties/
mass_properties_trimesh2d.rs1use crate::mass_properties::MassProperties;
2use crate::math::{Point, Real};
3use crate::shape::Triangle;
4
5impl MassProperties {
6 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 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
37pub 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}