parry3d/mass_properties/
mass_properties_convex_polyhedron.rs

1use crate::mass_properties::MassProperties;
2use crate::math::{Point, Real, DIM};
3
4impl MassProperties {
5    /// Computes the mass properties of a convex polyhedron (3D) or polygon (2D).
6    ///
7    /// A convex polyhedron is a 3D solid where all faces are flat and all vertices point
8    /// outward. This is a convenience function that delegates to `from_trimesh()`, which
9    /// handles the actual computation by treating the polyhedron as a triangle mesh.
10    ///
11    /// # Arguments
12    ///
13    /// * `density` - The material density
14    ///   - In 3D: kg/m³ (mass per unit volume)
15    ///   - In 2D: kg/m² (mass per unit area)
16    /// * `vertices` - Array of vertex positions defining the polyhedron
17    /// * `indices` - Array of triangle indices
18    ///   - In 3D: Each element is `[u32; 3]` indexing into vertices array
19    ///   - In 2D: Each element is `[u32; 2]` for line segments
20    ///
21    /// # Returns
22    ///
23    /// A `MassProperties` struct containing:
24    /// - **mass**: Total mass calculated from volume/area and density
25    /// - **local_com**: Center of mass (volume-weighted centroid)
26    /// - **inv_principal_inertia**: Inverse angular inertia tensor
27    ///
28    /// # Example (3D) - Tetrahedron
29    ///
30    /// ```
31    /// # #[cfg(all(feature = "dim3", feature = "f32"))] {
32    /// use parry3d::mass_properties::MassProperties;
33    /// use nalgebra::Point3;
34    ///
35    /// // Create a regular tetrahedron (4 vertices, 4 triangular faces)
36    /// let vertices = vec![
37    ///     Point3::new(1.0, 0.0, 0.0),
38    ///     Point3::new(0.0, 1.0, 0.0),
39    ///     Point3::new(0.0, 0.0, 1.0),
40    ///     Point3::origin(),
41    /// ];
42    ///
43    /// let indices = vec![
44    ///     [0, 1, 2], // Face 1
45    ///     [0, 1, 3], // Face 2
46    ///     [0, 2, 3], // Face 3
47    ///     [1, 2, 3], // Face 4
48    /// ];
49    ///
50    /// let density = 1000.0;
51    /// let tetra_props = MassProperties::from_convex_polyhedron(density, &vertices, &indices);
52    ///
53    /// println!("Tetrahedron mass: {:.4} kg", tetra_props.mass());
54    /// println!("Center of mass: {:?}", tetra_props.local_com);
55    /// # }
56    /// ```
57    ///
58    /// # Example (3D) - Octahedron
59    ///
60    /// ```
61    /// # #[cfg(all(feature = "dim3", feature = "f32"))] {
62    /// use parry3d::mass_properties::MassProperties;
63    /// use nalgebra::Point3;
64    ///
65    /// // Regular octahedron (6 vertices, 8 triangular faces)
66    /// let vertices = vec![
67    ///     Point3::new(1.0, 0.0, 0.0),   // +X
68    ///     Point3::new(-1.0, 0.0, 0.0),  // -X
69    ///     Point3::new(0.0, 1.0, 0.0),   // +Y
70    ///     Point3::new(0.0, -1.0, 0.0),  // -Y
71    ///     Point3::new(0.0, 0.0, 1.0),   // +Z
72    ///     Point3::new(0.0, 0.0, -1.0),  // -Z
73    /// ];
74    ///
75    /// let indices = vec![
76    ///     [0, 2, 4], [0, 4, 3], [0, 3, 5], [0, 5, 2],  // Right hemisphere
77    ///     [1, 4, 2], [1, 3, 4], [1, 5, 3], [1, 2, 5],  // Left hemisphere
78    /// ];
79    ///
80    /// let density = 800.0;
81    /// let octa_props = MassProperties::from_convex_polyhedron(density, &vertices, &indices);
82    ///
83    /// println!("Octahedron mass: {:.2} kg", octa_props.mass());
84    /// # }
85    /// ```
86    ///
87    /// # Use Cases
88    ///
89    /// - **Custom 3D shapes**: Game objects with specific polyhedral geometry
90    /// - **Crystalline structures**: Geometric solids (tetrahedra, octahedra, dodecahedra)
91    /// - **Simplified models**: Convex approximations of complex shapes
92    /// - **Gems and jewels**: Faceted objects
93    /// - **Dice**: Polyhedral game dice (d4, d6, d8, d12, d20)
94    ///
95    /// # Requirements
96    ///
97    /// - **Must be convex**: All faces must be flat and point outward
98    /// - **Closed mesh**: Triangles must form a watertight volume
99    /// - **Consistent winding**: Triangle vertices should follow consistent order
100    ///   (counter-clockwise when viewed from outside)
101    /// - **Valid indices**: All index values must be < vertices.len()
102    ///
103    /// # Convex vs Non-Convex
104    ///
105    /// This function assumes the shape is convex. For non-convex (concave) meshes:
106    /// - The result may be incorrect
107    /// - Consider using `from_compound()` with a convex decomposition
108    /// - Or use `from_trimesh()` directly (handles both convex and concave)
109    ///
110    /// # Implementation Note
111    ///
112    /// This function is a thin wrapper around `from_trimesh()`. Both produce identical
113    /// results. Use `from_convex_polyhedron()` when you know the shape is convex to
114    /// make intent clear in code.
115    ///
116    /// # See Also
117    ///
118    /// - `from_trimesh()`: For general triangle meshes (convex or concave)
119    /// - `from_convex_polygon()`: For 2D convex polygons
120    /// - `from_compound()`: For combining multiple convex shapes
121    pub fn from_convex_polyhedron(
122        density: Real,
123        vertices: &[Point<Real>],
124        indices: &[[u32; DIM]],
125    ) -> MassProperties {
126        Self::from_trimesh(density, vertices, indices)
127    }
128}