parry2d/mass_properties/
mass_properties_ball.rs

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