parry3d/mass_properties/
mass_properties_ball.rs

1use crate::mass_properties::MassProperties;
2#[cfg(feature = "dim3")]
3use crate::math::Vector;
4use crate::math::{Point, PrincipalAngularInertia, Real};
5use na::RealField;
6
7impl MassProperties {
8    pub(crate) fn ball_volume_unit_angular_inertia(
9        radius: Real,
10    ) -> (Real, PrincipalAngularInertia<Real>) {
11        #[cfg(feature = "dim2")]
12        {
13            let volume = Real::pi() * radius * radius;
14            let i = radius * radius / 2.0;
15            (volume, i)
16        }
17        #[cfg(feature = "dim3")]
18        {
19            let volume = Real::pi() * radius * radius * radius * 4.0 / 3.0;
20            let i = radius * radius * 2.0 / 5.0;
21
22            (volume, Vector::repeat(i))
23        }
24    }
25
26    /// Computes the mass properties of a ball (sphere in 3D, circle in 2D).
27    ///
28    /// A ball is a perfectly round geometric shape defined by its radius. This function
29    /// calculates the physical properties needed for physics simulation, including mass,
30    /// center of mass, and angular inertia (resistance to rotation).
31    ///
32    /// # Arguments
33    ///
34    /// * `density` - The material density (mass per unit volume/area). Higher values make heavier objects.
35    ///   - In 3D: units are typically kg/m³ (e.g., water = 1000, steel = 7850)
36    ///   - In 2D: units are typically kg/m² (mass per unit area)
37    /// * `radius` - The radius of the ball (distance from center to surface)
38    ///
39    /// # Returns
40    ///
41    /// A `MassProperties` struct containing:
42    /// - **mass**: Total mass calculated from volume and density
43    /// - **local_com**: Center of mass at the origin (balls are perfectly symmetric)
44    /// - **inv_principal_inertia**: Inverse angular inertia (resistance to spinning)
45    ///
46    /// # Physics Background
47    ///
48    /// Balls have uniform density and perfect symmetry, which means:
49    /// - The center of mass is at the geometric center (origin)
50    /// - All rotational axes have the same angular inertia (isotropic)
51    /// - In 3D: moment of inertia = (2/5) * mass * radius²
52    /// - In 2D: moment of inertia = (1/2) * mass * radius²
53    ///
54    /// # Example (3D)
55    ///
56    /// ```
57    /// # #[cfg(all(feature = "dim3", feature = "f32"))] {
58    /// use parry3d::mass_properties::MassProperties;
59    /// use nalgebra::Point3;
60    ///
61    /// // Create mass properties for a 0.5m radius ball with density 1000 kg/m³ (water density)
62    /// let radius = 0.5;
63    /// let density = 1000.0;
64    /// let ball_props = MassProperties::from_ball(density, radius);
65    ///
66    /// // Volume of sphere: (4/3) * π * r³ = 0.524 m³
67    /// // Mass: volume * density = 524 kg
68    /// let mass = ball_props.mass();
69    /// assert!((mass - 523.6).abs() < 1.0); // Approximately 524 kg
70    ///
71    /// // Center of mass is at the origin for symmetric shapes
72    /// assert_eq!(ball_props.local_com, Point3::origin());
73    ///
74    /// // Check if object can be moved (finite mass)
75    /// assert!(ball_props.inv_mass > 0.0, "Ball has finite mass and can move");
76    /// # }
77    /// ```
78    ///
79    /// # Example (2D)
80    ///
81    /// ```
82    /// # #[cfg(all(feature = "dim2", feature = "f32"))] {
83    /// use parry2d::mass_properties::MassProperties;
84    /// use nalgebra::Point2;
85    ///
86    /// // Create a circular disc with 1.0m radius and density 100 kg/m²
87    /// let radius = 1.0;
88    /// let density = 100.0;
89    /// let circle_props = MassProperties::from_ball(density, radius);
90    ///
91    /// // Area of circle: π * r² = 3.14 m²
92    /// // Mass: area * density = 314 kg
93    /// let mass = circle_props.mass();
94    /// assert!((mass - 314.159).abs() < 0.1); // Approximately 314 kg
95    ///
96    /// println!("Circle mass: {:.2} kg", mass);
97    /// println!("Moment of inertia: {:.2}", circle_props.principal_inertia());
98    /// # }
99    /// ```
100    ///
101    /// # Use Cases
102    ///
103    /// - **Sports balls**: Soccer balls, basketballs, bowling balls
104    /// - **Planets and celestial bodies**: Spherical approximations
105    /// - **Particles**: Point-like objects with rotational inertia
106    /// - **Wheels and gears**: Cylindrical objects in 2D simulations
107    ///
108    /// # Performance Note
109    ///
110    /// This is a very fast computation (constant time) as it only involves basic arithmetic
111    /// with the radius and density. Balls are the simplest shape for collision detection
112    /// and physics simulation.
113    pub fn from_ball(density: Real, radius: Real) -> Self {
114        let (vol, unit_i) = Self::ball_volume_unit_angular_inertia(radius);
115        let mass = vol * density;
116        Self::new(Point::origin(), mass, unit_i * mass)
117    }
118}