use glam::DVec3;
use crate::geometry::stone_metrics::measure_solid;
#[test]
fn measures_a_plain_box() {
let planes = vec![
(DVec3::X, 1.0),
(DVec3::NEG_X, 1.0),
(DVec3::Y, 0.6),
(DVec3::NEG_Y, 0.6),
(DVec3::Z, 1.0),
(DVec3::NEG_Z, 1.0),
];
let m = measure_solid(&planes).expect("box must measure");
assert!((m.volume - 4.8).abs() < 1e-9, "volume {}", m.volume);
assert!((m.width_axis - 2.0).abs() < 1e-9);
assert!((m.length_axis - 2.0).abs() < 1e-9);
assert!((m.width_caliper - 2.0).abs() < 1e-9);
assert!((m.total_height - 1.2).abs() < 1e-9);
assert_eq!(m.vertex_count, 8);
assert!((m.crown_height.expect("girdle present")).abs() < 1e-9);
assert!((m.pavilion_depth.expect("girdle present")).abs() < 1e-9);
assert!((m.girdle_thickness.expect("girdle present") - 1.2).abs() < 1e-9);
}
#[test]
fn measures_crown_height_against_the_girdle_band() {
let s = std::f64::consts::FRAC_1_SQRT_2;
let planes = vec![
(DVec3::X, 1.0),
(DVec3::NEG_X, 1.0),
(DVec3::Z, 1.0),
(DVec3::NEG_Z, 1.0),
(DVec3::NEG_Y, 0.5),
(DVec3::new(s, s, 0.0), s),
(DVec3::new(-s, s, 0.0), s),
(DVec3::new(0.0, s, s), s),
(DVec3::new(0.0, s, -s), s),
];
let m = measure_solid(&planes).expect("roofed block must measure");
assert!(
(m.volume - (2.0 + 4.0 / 3.0)).abs() < 1e-9,
"volume {}",
m.volume
);
assert!((m.total_height - 1.5).abs() < 1e-9);
assert!((m.crown_height.expect("girdle present") - 1.0).abs() < 1e-9);
assert!((m.pavilion_depth.expect("girdle present")).abs() < 1e-9);
assert!((m.girdle_thickness.expect("girdle present") - 0.5).abs() < 1e-9);
assert!((m.width_axis - 2.0).abs() < 1e-9);
}
#[test]
fn unbounded_solid_reports_none() {
let planes = vec![
(DVec3::X, 1.0),
(DVec3::NEG_X, 1.0),
(DVec3::Y, 0.6),
(DVec3::Z, 1.0),
(DVec3::NEG_Z, 1.0),
];
assert!(measure_solid(&planes).is_none());
}
#[test]
fn duplicate_planes_do_not_double_count() {
let planes = vec![
(DVec3::X, 1.0),
(DVec3::X, 1.0),
(DVec3::NEG_X, 1.0),
(DVec3::Y, 0.6),
(DVec3::NEG_Y, 0.6),
(DVec3::Z, 1.0),
(DVec3::NEG_Z, 1.0),
];
let m = measure_solid(&planes).expect("box must measure");
assert!((m.volume - 4.8).abs() < 1e-9, "volume {}", m.volume);
}
#[test]
fn caliper_width_beats_axis_width_on_a_rotated_outline() {
let s = std::f64::consts::FRAC_1_SQRT_2;
let planes = vec![
(DVec3::new(s, 0.0, s), 1.0),
(DVec3::new(-s, 0.0, s), 1.0),
(DVec3::new(s, 0.0, -s), 1.0),
(DVec3::new(-s, 0.0, -s), 1.0),
(DVec3::Y, 0.5),
(DVec3::NEG_Y, 0.5),
];
let m = measure_solid(&planes).expect("rotated box must measure");
let diag = 2.0 * std::f64::consts::SQRT_2;
assert!((m.width_axis - diag).abs() < 1e-9, "axis {}", m.width_axis);
assert!(
(m.width_caliper - 2.0).abs() < 1e-9,
"caliper {}",
m.width_caliper
);
assert!((m.volume - 4.0).abs() < 1e-9, "volume {}", m.volume);
}
#[test]
fn measurement_is_deterministic() {
let s = std::f64::consts::FRAC_1_SQRT_2;
let planes = vec![
(DVec3::X, 1.0),
(DVec3::NEG_X, 1.0),
(DVec3::Z, 1.0),
(DVec3::NEG_Z, 1.0),
(DVec3::NEG_Y, 0.5),
(DVec3::new(s, s, 0.0), s),
(DVec3::new(-s, s, 0.0), s),
(DVec3::new(0.0, s, s), s),
(DVec3::new(0.0, s, -s), s),
];
let a = measure_solid(&planes).expect("must measure");
let b = measure_solid(&planes).expect("must measure");
assert_eq!(a.volume.to_bits(), b.volume.to_bits());
assert_eq!(a.width_caliper.to_bits(), b.width_caliper.to_bits());
assert_eq!(a.total_height.to_bits(), b.total_height.to_bits());
}