1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
use fj_math::{Line, Point, Scalar, Vector};
use crate::objects::{Curve, Surface};
pub fn surface_surface(a: &Surface, b: &Surface) -> Option<Curve<3>> {
let (a_normal, a_distance) = extract_plane(a);
let (b_normal, b_distance) = extract_plane(b);
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 };
Some(Curve::Line(Line { origin, direction }))
}
fn extract_plane(surface: &Surface) -> (Vector<3>, Scalar) {
let Surface::SweptCurve(surface) = surface;
let line = match surface.curve {
Curve::Line(line) => line,
_ => todo!("Only plane-plane intersection is currently supported."),
};
let a = line.origin;
let b = line.origin + line.direction;
let c = line.origin + surface.path;
let normal = (b - a).cross(&(c - a)).normalize();
let distance = normal.dot(&a.coords);
(normal, distance)
}
#[cfg(test)]
mod tests {
use fj_math::Transform;
use crate::objects::{Curve, Surface};
use super::surface_surface;
#[test]
fn plane_plane() {
let xy = Surface::xy_plane();
let xz = Surface::xz_plane();
assert_eq!(surface_surface(&xy, &xy), None);
assert_eq!(
surface_surface(
&xy,
&xy.transform(&Transform::translation([0., 0., 1.]))
),
None,
);
assert_eq!(surface_surface(&xy, &xz), Some(Curve::x_axis()));
}
}