use std::f32::consts::FRAC_1_SQRT_2;
#[inline(always)]
pub fn chamfer_min(a: f32, b: f32, r: f32) -> f32 {
a.min(b).min((a + b).mul_add(FRAC_1_SQRT_2, -r))
}
#[inline(always)]
pub fn chamfer_max(a: f32, b: f32, r: f32) -> f32 {
-chamfer_min(-a, -b, r)
}
#[inline(always)]
pub fn sdf_chamfer_union(d1: f32, d2: f32, r: f32) -> f32 {
chamfer_min(d1, d2, r)
}
#[inline(always)]
pub fn sdf_chamfer_intersection(d1: f32, d2: f32, r: f32) -> f32 {
chamfer_max(d1, d2, r)
}
#[inline(always)]
pub fn sdf_chamfer_subtraction(d1: f32, d2: f32, r: f32) -> f32 {
chamfer_max(d1, -d2, r)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_chamfer_union_basic() {
let a = 5.0;
let b = 10.0;
let r = 0.5;
let result = sdf_chamfer_union(a, b, r);
assert!(result <= a, "chamfer union should be <= min(a,b)");
}
#[test]
fn test_chamfer_union_symmetry() {
let d1 = 0.5;
let d2 = 0.8;
let r = 0.3;
assert!((sdf_chamfer_union(d1, d2, r) - sdf_chamfer_union(d2, d1, r)).abs() < 1e-6);
}
#[test]
fn test_chamfer_intersection() {
let d1 = -0.5;
let d2 = -0.3;
let r = 0.1;
let result = sdf_chamfer_intersection(d1, d2, r);
assert!(result >= d1.max(d2) - r * 2.0);
}
#[test]
fn test_chamfer_creates_bevel() {
let a = 0.1;
let b = 0.1;
let r = 0.5;
let chamfer = sdf_chamfer_union(a, b, r);
let hard_union = a.min(b);
assert!(chamfer < hard_union);
}
}