use std::f64::consts::PI;
use brepkit_math::vec::Point3;
use super::accumulator::GProps;
#[must_use]
pub fn box_props(dx: f64, dy: f64, dz: f64) -> GProps {
let v = dx * dy * dz;
let center = Point3::new(dx / 2.0, dy / 2.0, dz / 2.0);
let ixx = v / 12.0 * (dy * dy + dz * dz);
let iyy = v / 12.0 * (dx * dx + dz * dz);
let izz = v / 12.0 * (dx * dx + dy * dy);
GProps {
mass: v,
center,
inertia: [ixx, iyy, izz, 0.0, 0.0, 0.0],
}
}
#[must_use]
pub fn sphere_props(radius: f64) -> GProps {
let v = 4.0 / 3.0 * PI * radius.powi(3);
let center = Point3::new(0.0, 0.0, 0.0);
let i = 2.0 / 5.0 * v * radius * radius;
GProps {
mass: v,
center,
inertia: [i, i, i, 0.0, 0.0, 0.0],
}
}
#[must_use]
pub fn cylinder_props(radius: f64, height: f64) -> GProps {
let v = PI * radius * radius * height;
let center = Point3::new(0.0, 0.0, height / 2.0);
let ixx = v / 12.0 * (3.0 * radius * radius + height * height);
let iyy = ixx;
let izz = v / 2.0 * radius * radius;
GProps {
mass: v,
center,
inertia: [ixx, iyy, izz, 0.0, 0.0, 0.0],
}
}
#[must_use]
#[allow(clippy::similar_names)]
pub fn cone_props(r_bottom: f64, r_top: f64, height: f64) -> GProps {
let rb2 = r_bottom * r_bottom;
let rt2 = r_top * r_top;
let rbrt = r_bottom * r_top;
let r_sum2 = rb2 + rbrt + rt2;
if r_sum2 < 1e-30 {
return GProps {
mass: 0.0,
center: Point3::new(0.0, 0.0, height / 2.0),
inertia: [0.0; 6],
};
}
let v = PI * height / 3.0 * r_sum2;
let z_com = height * (rb2 + 2.0 * rbrt + 3.0 * rt2) / (4.0 * r_sum2);
let center = Point3::new(0.0, 0.0, z_com);
let r_sum4 = rb2 * rb2 + rb2 * rbrt + rb2 * rt2 + rbrt * rt2 + rt2 * rt2;
let izz = 3.0 * v / 10.0 * r_sum4 / r_sum2;
let ixx_about_base = 3.0 * v / 20.0 * r_sum4 / r_sum2
+ v * height * height * (rb2 + 3.0 * rbrt + 6.0 * rt2) / (10.0 * r_sum2);
let ixx = ixx_about_base - v * z_com * z_com;
let iyy = ixx;
GProps {
mass: v,
center,
inertia: [ixx, iyy, izz, 0.0, 0.0, 0.0],
}
}
#[must_use]
pub fn torus_props(major_r: f64, minor_r: f64) -> GProps {
let v = 2.0 * PI * PI * major_r * minor_r * minor_r;
let center = Point3::new(0.0, 0.0, 0.0);
let izz = v * (major_r * major_r + 0.75 * minor_r * minor_r);
let ixx = v * (major_r * major_r / 2.0 + 5.0 / 8.0 * minor_r * minor_r);
let iyy = ixx;
GProps {
mass: v,
center,
inertia: [ixx, iyy, izz, 0.0, 0.0, 0.0],
}
}
#[must_use]
pub fn box_area(dx: f64, dy: f64, dz: f64) -> f64 {
2.0 * (dx * dy + dy * dz + dx * dz)
}
#[must_use]
pub fn sphere_area(radius: f64) -> f64 {
4.0 * PI * radius * radius
}
#[must_use]
pub fn cylinder_area(radius: f64, height: f64) -> f64 {
2.0 * PI * radius * height + 2.0 * PI * radius * radius
}
#[must_use]
pub fn torus_area(major_r: f64, minor_r: f64) -> f64 {
4.0 * PI * PI * major_r * minor_r
}