fj_kernel/algorithms/intersect/
surface_surface.rs1use fj_math::{Line, Plane, Point, Scalar};
2
3use crate::{
4 geometry::curve::{Curve, GlobalPath},
5 objects::Surface,
6 storage::Handle,
7};
8
9#[derive(Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
11pub struct SurfaceSurfaceIntersection {
12 pub intersection_curves: [Curve; 2],
14}
15
16impl SurfaceSurfaceIntersection {
17 pub fn compute(surfaces: [Handle<Surface>; 2]) -> Option<Self> {
19 let planes = surfaces.map(|surface| plane_from_surface(&surface));
26
27 let [(a_distance, a_normal), (b_distance, b_normal)] =
28 planes.map(|plane| plane.constant_normal_form());
29
30 let direction = a_normal.cross(&b_normal);
31
32 let denom = direction.dot(&direction);
33 if denom == Scalar::ZERO {
34 return None;
42 }
43
44 let origin = (b_normal * a_distance - a_normal * b_distance)
45 .cross(&direction)
46 / denom;
47 let origin = Point { coords: origin };
48
49 let line = Line::from_origin_and_direction(origin, direction);
50
51 let curves = planes.map(|plane| Curve::Line(plane.project_line(&line)));
52
53 Some(Self {
54 intersection_curves: curves,
55 })
56 }
57}
58
59fn plane_from_surface(surface: &Surface) -> Plane {
60 let (line, path) = {
61 let line = match surface.geometry().u {
62 GlobalPath::Line(line) => line,
63 _ => todo!("Only plane-plane intersection is currently supported."),
64 };
65
66 (line, surface.geometry().v)
67 };
68
69 Plane::from_parametric(line.origin(), line.direction(), path)
70}
71
72#[cfg(test)]
73mod tests {
74 use fj_math::Transform;
75 use pretty_assertions::assert_eq;
76
77 use crate::{
78 algorithms::transform::TransformObject, geometry::curve::Curve,
79 services::Services,
80 };
81
82 use super::SurfaceSurfaceIntersection;
83
84 #[test]
85 fn plane_plane() {
86 let mut services = Services::new();
87
88 let xy = services.objects.surfaces.xy_plane();
89 let xz = services.objects.surfaces.xz_plane();
90
91 assert_eq!(
93 SurfaceSurfaceIntersection::compute([
94 xy.clone(),
95 xy.clone().transform(
96 &Transform::translation([0., 0., 1.],),
97 &mut services
98 )
99 ],),
100 None,
101 );
102
103 let expected_xy = Curve::u_axis();
104 let expected_xz = Curve::u_axis();
105
106 assert_eq!(
107 SurfaceSurfaceIntersection::compute([xy, xz],),
108 Some(SurfaceSurfaceIntersection {
109 intersection_curves: [expected_xy, expected_xz],
110 })
111 );
112 }
113}