use fj_math::{Line, Plane, Point, Scalar};
use crate::{
geometry::curve::{Curve, GlobalPath},
objects::Surface,
storage::Handle,
};
#[derive(Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
pub struct SurfaceSurfaceIntersection {
pub intersection_curves: [Curve; 2],
}
impl SurfaceSurfaceIntersection {
pub fn compute(surfaces: [Handle<Surface>; 2]) -> Option<Self> {
let planes = surfaces.map(|surface| plane_from_surface(&surface));
let [(a_distance, a_normal), (b_distance, b_normal)] =
planes.map(|plane| plane.constant_normal_form());
let direction = a_normal.cross(&b_normal);
let denom = direction.dot(&direction);
if denom == Scalar::ZERO {
return None;
}
let origin = (b_normal * a_distance - a_normal * b_distance)
.cross(&direction)
/ denom;
let origin = Point { coords: origin };
let line = Line::from_origin_and_direction(origin, direction);
let curves = planes.map(|plane| Curve::Line(plane.project_line(&line)));
Some(Self {
intersection_curves: curves,
})
}
}
fn plane_from_surface(surface: &Surface) -> Plane {
let (line, path) = {
let line = match surface.geometry().u {
GlobalPath::Line(line) => line,
_ => todo!("Only plane-plane intersection is currently supported."),
};
(line, surface.geometry().v)
};
Plane::from_parametric(line.origin(), line.direction(), path)
}
#[cfg(test)]
mod tests {
use fj_math::Transform;
use pretty_assertions::assert_eq;
use crate::{
algorithms::transform::TransformObject, geometry::curve::Curve,
services::Services,
};
use super::SurfaceSurfaceIntersection;
#[test]
fn plane_plane() {
let mut services = Services::new();
let xy = services.objects.surfaces.xy_plane();
let xz = services.objects.surfaces.xz_plane();
assert_eq!(
SurfaceSurfaceIntersection::compute([
xy.clone(),
xy.clone().transform(
&Transform::translation([0., 0., 1.],),
&mut services.objects
)
],),
None,
);
let expected_xy = Curve::u_axis();
let expected_xz = Curve::u_axis();
assert_eq!(
SurfaceSurfaceIntersection::compute([xy, xz],),
Some(SurfaceSurfaceIntersection {
intersection_curves: [expected_xy, expected_xz],
})
);
}
}