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}