1pub fn convex_parts_overlap(a: &[[i64; 2]], b: &[[i64; 2]]) -> bool {
8 crate::sat::sat_overlaps(a, b)
9}
10
11pub fn find_overlapping_parts(
14 a_parts: &[Vec<[i64; 2]>],
15 b_parts: &[Vec<[i64; 2]>],
16) -> Vec<(usize, usize)> {
17 let mut overlaps = Vec::new();
18
19 for (i, a) in a_parts.iter().enumerate() {
20 for (j, b) in b_parts.iter().enumerate() {
21 if convex_parts_overlap(a, b) {
22 overlaps.push((i, j));
23 }
24 }
25 }
26
27 overlaps
28}
29
30pub fn parts_overlap(a_parts: &[Vec<[i64; 2]>], b_parts: &[Vec<[i64; 2]>]) -> bool {
32 for a in a_parts {
33 for b in b_parts {
34 if convex_parts_overlap(a, b) {
35 return true;
36 }
37 }
38 }
39 false
40}
41
42#[cfg(test)]
43mod tests {
44 use super::*;
45
46 const M: i64 = 1_000_000;
47
48 fn square(ox: i64, oy: i64, size: i64) -> Vec<[i64; 2]> {
49 vec![
50 [ox, oy],
51 [ox + size, oy],
52 [ox + size, oy + size],
53 [ox, oy + size],
54 ]
55 }
56
57 #[test]
58 fn adjacent_squares_no_overlap() {
59 let a = square(0, 0, M);
61 let b = square(M, 0, M);
62 assert!(
63 !convex_parts_overlap(&a, &b),
64 "adjacent parts sharing an edge must NOT overlap"
65 );
66 }
67
68 #[test]
69 fn one_pixel_penetration_is_overlap() {
70 let a = square(0, 0, M);
71 let b = square(M - 1, 0, M);
72
73 assert!(
74 convex_parts_overlap(&a, &b),
75 "a 1-unit interior intersection must count as overlap"
76 );
77 }
78
79 #[test]
80 fn overlapping_squares_overlap() {
81 let a = square(0, 0, 3 * M);
83 let b = square(2 * M, 2 * M, 3 * M);
84 assert!(convex_parts_overlap(&a, &b));
85 }
86
87 #[test]
88 fn separated_squares_no_overlap() {
89 let a = square(0, 0, M);
90 let b = square(3 * M, 0, M);
91 assert!(!convex_parts_overlap(&a, &b));
92 }
93
94 #[test]
95 fn identical_squares_overlap() {
96 let square = square(0, 0, M);
97 assert!(convex_parts_overlap(&square, &square));
98 }
99
100 #[test]
101 fn contained_square_overlaps() {
102 let outer = square(0, 0, 10 * M);
103 let inner = square(2 * M, 2 * M, 3 * M);
104 assert!(convex_parts_overlap(&outer, &inner));
105 }
106
107 #[test]
108 fn parts_overlap_multipart() {
109 let a_parts = vec![vec![[0, 0], [10 * M, 0], [10 * M, 10 * M], [0, 10 * M]]];
110 let b_parts_overlap = vec![vec![
111 [5 * M, 5 * M],
112 [15 * M, 5 * M],
113 [15 * M, 15 * M],
114 [5 * M, 15 * M],
115 ]];
116 let b_parts_adjacent = vec![vec![
117 [10 * M, 0],
118 [20 * M, 0],
119 [20 * M, 10 * M],
120 [10 * M, 10 * M],
121 ]];
122 assert!(parts_overlap(&a_parts, &b_parts_overlap));
123 assert!(!parts_overlap(&a_parts, &b_parts_adjacent));
124 }
125
126 #[test]
127 fn find_overlapping_parts_returns_empty_when_disjoint() {
128 let a_parts = vec![
129 vec![[0, 0], [M, 0], [M, M], [0, M]],
130 vec![[3 * M, 0], [4 * M, 0], [4 * M, M], [3 * M, M]],
131 vec![[6 * M, 0], [7 * M, 0], [7 * M, M], [6 * M, M]],
132 ];
133 let b_parts = vec![
134 vec![[0, 3 * M], [M, 3 * M], [M, 4 * M], [0, 4 * M]],
135 vec![
136 [3 * M, 3 * M],
137 [4 * M, 3 * M],
138 [4 * M, 4 * M],
139 [3 * M, 4 * M],
140 ],
141 vec![
142 [6 * M, 3 * M],
143 [7 * M, 3 * M],
144 [7 * M, 4 * M],
145 [6 * M, 4 * M],
146 ],
147 ];
148
149 assert!(find_overlapping_parts(&a_parts, &b_parts).is_empty());
150 }
151
152 #[test]
153 fn find_overlapping_parts_returns_matching_indices() {
154 let a_parts = vec![
155 vec![[0, 0], [M, 0], [M, M], [0, M]],
156 vec![[3 * M, 0], [4 * M, 0], [4 * M, M], [3 * M, M]],
157 vec![[6 * M, 0], [7 * M, 0], [7 * M, M], [6 * M, M]],
158 ];
159 let b_parts = vec![
160 vec![[0, 3 * M], [M, 3 * M], [M, 4 * M], [0, 4 * M]],
161 vec![
162 [3 * M, 3 * M],
163 [4 * M, 3 * M],
164 [4 * M, 4 * M],
165 [3 * M, 4 * M],
166 ],
167 vec![
168 [6 * M - 1, 0],
169 [7 * M - 1, 0],
170 [7 * M - 1, M],
171 [6 * M - 1, M],
172 ],
173 ];
174
175 assert_eq!(find_overlapping_parts(&a_parts, &b_parts), vec![(2, 2)]);
176 }
177
178 #[test]
179 fn parts_overlap_false_when_all_pairs_separated() {
180 let a_parts = vec![
181 vec![[0, 0], [M, 0], [M, M], [0, M]],
182 vec![[3 * M, 0], [4 * M, 0], [4 * M, M], [3 * M, M]],
183 ];
184 let b_parts = vec![
185 vec![[0, 3 * M], [M, 3 * M], [M, 4 * M], [0, 4 * M]],
186 vec![
187 [3 * M, 3 * M],
188 [4 * M, 3 * M],
189 [4 * M, 4 * M],
190 [3 * M, 4 * M],
191 ],
192 ];
193
194 assert!(!parts_overlap(&a_parts, &b_parts));
195 }
196
197 #[test]
198 fn parts_overlap_true_when_one_pair_overlaps() {
199 let a_parts = vec![
200 vec![[0, 0], [M, 0], [M, M], [0, M]],
201 vec![[3 * M, 0], [4 * M, 0], [4 * M, M], [3 * M, M]],
202 ];
203 let b_parts = vec![
204 vec![[0, 3 * M], [M, 3 * M], [M, 4 * M], [0, 4 * M]],
205 vec![[M - 1, 0], [2 * M - 1, 0], [2 * M - 1, M], [M - 1, M]],
206 ];
207
208 assert!(parts_overlap(&a_parts, &b_parts));
209 }
210}