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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
use fj_math::{Aabb, Line, Scalar, Segment, Vector};
pub fn line_segment(
line: &Line<2>,
segment: &Segment<2>,
) -> Option<LineSegmentIntersection> {
let [a, b] = segment.points();
let n = {
let ab = b - a;
Vector::from([ab.v, ab.u])
};
let n_dot_origin = n.dot(&(b - line.origin));
let n_dot_direction = n.dot(&line.direction);
if n_dot_origin == Scalar::ZERO && n_dot_direction == Scalar::ZERO {
return Some(LineSegmentIntersection::Coincident);
}
if n_dot_direction == Scalar::ZERO {
return None;
}
let t = n_dot_origin / n_dot_direction;
let point_is_on_segment = Aabb::<2>::from_points(segment.points())
.contains(line.point_from_line_coords([t]));
if !point_is_on_segment {
return None;
}
Some(LineSegmentIntersection::PointOnLine(t))
}
#[derive(Debug, Eq, PartialEq)]
pub enum LineSegmentIntersection {
PointOnLine(Scalar),
Coincident,
}
#[cfg(test)]
mod tests {
use fj_math::{Line, Point, Scalar, Segment, Vector};
use crate::algorithms::intersection::LineSegmentIntersection;
#[test]
fn line_segment() {
let line = Line {
origin: Point::origin(),
direction: Vector::unit_u(),
};
assert_eq!(
super::line_segment(
&line,
&Segment::from_points([[1., -1.], [1., 1.]]),
),
Some(LineSegmentIntersection::PointOnLine(Scalar::ONE)),
);
assert_eq!(
super::line_segment(
&line,
&Segment::from_points([[1., 0.], [2., 0.]]),
),
Some(LineSegmentIntersection::Coincident),
);
assert_eq!(
super::line_segment(
&line,
&Segment::from_points([[1., 1.], [1., 2.]]),
),
None,
);
assert_eq!(
super::line_segment(
&line,
&Segment::from_points([[1., -2.], [1., -1.]]),
),
None,
);
assert_eq!(
super::line_segment(
&line,
&Segment::from_points([[-1., 1.], [1., 1.]]),
),
None,
);
}
}