use axiolid_core::Point3;
use axiolid_reference::coplanar::coplanar_overlap;
fn area(polygon: &[Point3]) -> f64 {
if polygon.len() < 3 {
return 0.0;
}
let mut total = Point3::new(0.0, 0.0, 0.0);
for index in 1..polygon.len() - 1 {
let u = polygon[index] - polygon[0];
let v = polygon[index + 1] - polygon[0];
total += u.cross(v);
}
total.length() / 2.0
}
#[test]
fn coplanar_triangles_that_miss_each_other_have_no_overlap() {
let left = [
Point3::new(0.0, 0.0, 0.0),
Point3::new(2.0, 0.0, 0.0),
Point3::new(0.0, 2.0, 0.0),
];
let right = [
Point3::new(9.0, 0.0, 0.0),
Point3::new(11.0, 0.0, 0.0),
Point3::new(9.0, 2.0, 0.0),
];
assert!(
coplanar_overlap(left, right).is_empty(),
"disjoint coplanar faces share no area"
);
}
#[test]
fn identical_triangles_overlap_completely() {
let triangle = [
Point3::new(0.0, 0.0, 0.0),
Point3::new(4.0, 0.0, 0.0),
Point3::new(0.0, 4.0, 0.0),
];
let overlap = coplanar_overlap(triangle, triangle);
assert!(
(area(&overlap) - 8.0).abs() < 1e-9,
"got {}",
area(&overlap)
);
}
#[test]
fn a_partial_overlap_has_the_area_the_geometry_implies() {
let first = [
Point3::new(0.0, 0.0, 0.0),
Point3::new(4.0, 0.0, 0.0),
Point3::new(0.0, 4.0, 0.0),
];
let second = [
Point3::new(2.0, 0.0, 0.0),
Point3::new(6.0, 0.0, 0.0),
Point3::new(2.0, 4.0, 0.0),
];
let overlap = coplanar_overlap(first, second);
assert!(
(area(&overlap) - 2.0).abs() < 1e-9,
"got {}",
area(&overlap)
);
}
#[test]
fn edge_contact_is_not_an_area_overlap() {
let left = [
Point3::new(0.0, 0.0, 0.0),
Point3::new(2.0, 0.0, 0.0),
Point3::new(0.0, 2.0, 0.0),
];
let right = [
Point3::new(2.0, 0.0, 0.0),
Point3::new(4.0, 0.0, 0.0),
Point3::new(4.0, 2.0, 0.0),
];
assert!(
coplanar_overlap(left, right).is_empty(),
"a shared edge or vertex is not an area"
);
}
#[test]
fn the_overlap_is_the_same_whichever_triangle_is_clipped() {
let first = [
Point3::new(0.0, 0.0, 1.0),
Point3::new(4.0, 0.0, 1.0),
Point3::new(0.0, 4.0, 1.0),
];
let second = [
Point3::new(1.0, 1.0, 1.0),
Point3::new(5.0, 1.0, 1.0),
Point3::new(1.0, 5.0, 1.0),
];
let forward = area(&coplanar_overlap(first, second));
let backward = area(&coplanar_overlap(second, first));
assert!(forward > 0.0, "these triangles do overlap");
assert!((forward - backward).abs() < 1e-9, "{forward} vs {backward}");
}
#[test]
fn a_contained_triangle_clips_to_its_own_area() {
let big = [
Point3::new(0.0, 0.0, 0.0),
Point3::new(10.0, 0.0, 0.0),
Point3::new(0.0, 10.0, 0.0),
];
let small = [
Point3::new(1.0, 1.0, 0.0),
Point3::new(3.0, 1.0, 0.0),
Point3::new(1.0, 3.0, 0.0),
];
let overlap = coplanar_overlap(small, big);
assert!(
(area(&overlap) - 2.0).abs() < 1e-9,
"got {}",
area(&overlap)
);
}