use crate::compiled::real::{Real, Vec3R};
use glam::Vec3;
#[inline(always)]
pub fn sdf_link_r<R: Real>(p: Vec3R<R>, half_length: f32, r1: f32, r2: f32) -> R {
let qx = p.x;
let qy = (p.y.abs() - R::splat(half_length)).max(R::zero());
let qz = p.z;
let xy_len = (qx * qx + qy * qy).sqrt() - R::splat(r1);
(xy_len * xy_len + qz * qz).sqrt() - R::splat(r2)
}
#[inline(always)]
pub fn sdf_link(p: Vec3, half_length: f32, r1: f32, r2: f32) -> f32 {
sdf_link_r::<f32>(p.into(), half_length, r1, r2)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_link_origin_outside() {
let d = sdf_link(Vec3::ZERO, 0.5, 1.0, 0.3);
assert!(
(d - 0.7).abs() < 0.001,
"Origin distance should be r1-r2=0.7, got {}",
d
);
}
#[test]
fn test_link_on_tube() {
let d = sdf_link(Vec3::new(1.0, 0.0, 0.0), 0.5, 1.0, 0.3);
assert!(
(d + 0.3).abs() < 0.01,
"On major radius, d should be ~-r2, got {}",
d
);
}
#[test]
fn test_link_outside() {
let d = sdf_link(Vec3::new(5.0, 0.0, 0.0), 0.5, 1.0, 0.3);
assert!(d > 0.0, "Far point should be outside, got {}", d);
}
#[test]
fn test_link_symmetry_y() {
let d1 = sdf_link(Vec3::new(0.5, 1.0, 0.2), 0.5, 1.0, 0.3);
let d2 = sdf_link(Vec3::new(0.5, -1.0, 0.2), 0.5, 1.0, 0.3);
assert!((d1 - d2).abs() < 0.001, "Should be symmetric in Y");
}
}