Another project
1use bone_kernel::{Arc2, Circle2, Curve2, Curve2Kind, Line2, intersect_curves};
2use bone_types::{Angle, Length, Point2, Tolerance};
3use uom::si::angle::radian;
4use uom::si::length::millimeter;
5
6const TOL: Tolerance = Tolerance::new(1e-9);
7
8fn line(ax: f64, ay: f64, bx: f64, by: f64) -> Curve2Kind {
9 let Ok(l) = Line2::new(Point2::from_mm(ax, ay), Point2::from_mm(bx, by), TOL) else {
10 panic!("line endpoints distinct");
11 };
12 l.as_kind()
13}
14
15fn circle(cx: f64, cy: f64, r: f64) -> Curve2Kind {
16 let Ok(c) = Circle2::new(Point2::from_mm(cx, cy), Length::new::<millimeter>(r), TOL) else {
17 panic!("radius positive");
18 };
19 c.as_kind()
20}
21
22fn arc(cx: f64, cy: f64, r: f64, start: f64, sweep: f64) -> Curve2Kind {
23 let Ok(a) = Arc2::new(
24 Point2::from_mm(cx, cy),
25 Length::new::<millimeter>(r),
26 Angle::new::<radian>(start),
27 Angle::new::<radian>(sweep),
28 TOL,
29 ) else {
30 panic!("sweep nonzero");
31 };
32 a.as_kind()
33}
34
35fn row(label: &str, a: &Curve2Kind, b: &Curve2Kind) -> String {
36 format!("{label} = {}", intersect_curves(a, b, TOL))
37}
38
39#[test]
40fn intersection_matrix_surface() {
41 let line_diag = line(-5.0, -5.0, 5.0, 5.0);
42 let line_cross = line(-5.0, 5.0, 5.0, -5.0);
43 let line_parallel = line(-5.0, -4.0, 5.0, 6.0);
44 let line_coincident = line(-2.0, -2.0, 2.0, 2.0);
45 let line_collinear_touch = line(5.0, 5.0, 10.0, 10.0);
46 let line_miss = line(10.0, 10.0, 11.0, 11.0);
47 let line_tangent = line(-5.0, 3.0, 5.0, 3.0);
48 let line_through_circle = line(-5.0, 0.0, 5.0, 0.0);
49
50 let circle_unit = circle(0.0, 0.0, 3.0);
51 let circle_shift = circle(4.0, 0.0, 3.0);
52 let circle_contain = circle(0.0, 0.0, 1.0);
53 let circle_dup = circle(0.0, 0.0, 3.0);
54 let circle_far = circle(20.0, 0.0, 1.0);
55
56 let arc_right = arc(
57 0.0,
58 0.0,
59 3.0,
60 -core::f64::consts::FRAC_PI_2,
61 core::f64::consts::PI,
62 );
63 let arc_upper = arc(0.0, 0.0, 3.0, 0.0, core::f64::consts::PI);
64 let arc_other = arc(
65 4.0,
66 0.0,
67 3.0,
68 core::f64::consts::FRAC_PI_2,
69 core::f64::consts::PI,
70 );
71 let line_above_arc = line(-5.0, 5.0, 5.0, 5.0);
72
73 let arc_same_disjoint_q1 = arc(0.0, 0.0, 3.0, 0.0, core::f64::consts::FRAC_PI_2);
74 let arc_same_disjoint_q3 = arc(
75 0.0,
76 0.0,
77 3.0,
78 core::f64::consts::PI,
79 core::f64::consts::FRAC_PI_2,
80 );
81 let arc_same_touch_left = arc(0.0, 0.0, 3.0, 0.0, core::f64::consts::PI);
82 let arc_same_touch_right = arc(0.0, 0.0, 3.0, core::f64::consts::PI, core::f64::consts::PI);
83 let arc_same_partial_b = arc(
84 0.0,
85 0.0,
86 3.0,
87 core::f64::consts::FRAC_PI_2,
88 core::f64::consts::PI,
89 );
90 let arc_same_single_touch = arc(
91 0.0,
92 0.0,
93 3.0,
94 core::f64::consts::FRAC_PI_2,
95 core::f64::consts::FRAC_PI_2,
96 );
97
98 let rows = [
99 row("line_line_cross", &line_diag, &line_cross),
100 row("line_line_parallel_miss", &line_diag, &line_parallel),
101 row("line_line_coincident_overlap", &line_diag, &line_coincident),
102 row(
103 "line_line_collinear_touch",
104 &line_diag,
105 &line_collinear_touch,
106 ),
107 row("line_line_segment_miss", &line_diag, &line_miss),
108 row("line_circle_tangent", &line_tangent, &circle_unit),
109 row("line_circle_secant", &line_through_circle, &circle_unit),
110 row("line_arc_right_hit", &line_through_circle, &arc_right),
111 row("line_arc_upper_endpoints", &line_through_circle, &arc_upper),
112 row("line_arc_above_miss", &line_above_arc, &arc_upper),
113 row("circle_circle_two_points", &circle_unit, &circle_shift),
114 row("circle_circle_contained", &circle_unit, &circle_contain),
115 row("circle_circle_coincident", &circle_unit, &circle_dup),
116 row("circle_circle_disjoint", &circle_unit, &circle_far),
117 row("circle_arc_partial", &circle_shift, &arc_upper),
118 row("arc_arc_upper_vs_other", &arc_upper, &arc_other),
119 row(
120 "arc_arc_same_circle_disjoint",
121 &arc_same_disjoint_q1,
122 &arc_same_disjoint_q3,
123 ),
124 row(
125 "arc_arc_same_circle_two_touches",
126 &arc_same_touch_left,
127 &arc_same_touch_right,
128 ),
129 row(
130 "arc_arc_same_circle_partial_overlap",
131 &arc_upper,
132 &arc_same_partial_b,
133 ),
134 row(
135 "arc_arc_same_circle_single_touch",
136 &arc_same_disjoint_q1,
137 &arc_same_single_touch,
138 ),
139 ];
140
141 let surface = rows.join("\n");
142 insta::assert_snapshot!(surface);
143}