1use super::helper::Float;
2use super::segment_intersection::{intersection, LineIntersection};
3use super::signed_area::signed_area;
4use super::sweep_event::SweepEvent;
5use std::cmp::Ordering;
6use std::rc::Rc;
7
8use super::helper;
9
10pub fn compare_segments<F>(se1_l: &Rc<SweepEvent<F>>, se2_l: &Rc<SweepEvent<F>>) -> Ordering
11where
12 F: Float,
13{
14 debug_assert!(
15 se1_l.is_left(),
16 "compare_segments requires left-events, got a right-event."
17 );
18 debug_assert!(
19 se2_l.is_left(),
20 "compare_segments requires left-events, got a right-event."
21 );
22 debug_assert!(
23 se1_l.get_other_event().is_some(),
24 "missing right-event in compare_segments"
25 );
26 debug_assert!(
27 se2_l.get_other_event().is_some(),
28 "missing right-event in compare_segments"
29 );
30
31 if Rc::ptr_eq(&se1_l, &se2_l) {
32 return Ordering::Equal;
33 }
34
35 let (se_old_l, se_new_l, less_if) = if se1_l.is_before(&se2_l) {
40 (se1_l, se2_l, helper::less_if as fn(bool) -> Ordering)
41 } else {
42 (se2_l, se1_l, helper::less_if_inversed as fn(bool) -> Ordering)
43 };
44
45 if let (Some(se_old_r), Some(se_new_r)) = (se_old_l.get_other_event(), se_new_l.get_other_event()) {
46 let sa_l = signed_area(se_old_l.point, se_old_r.point, se_new_l.point);
47 let sa_r = signed_area(se_old_l.point, se_old_r.point, se_new_r.point);
48 if sa_l != 0. || sa_r != 0. {
49 if se_old_l.point == se_new_l.point {
53 return less_if(se_old_l.is_below(se_new_r.point));
54 }
55
56 if se_old_l.point.x == se_new_l.point.x {
58 return less_if(se_old_l.point.y < se_new_l.point.y);
59 }
60
61 if (sa_l > 0.) == (sa_r > 0.) {
64 return less_if(sa_l > 0.);
65 }
66
67 if sa_l == 0. {
69 return less_if(sa_r > 0.);
70 }
71
72 let inter = intersection(se_old_l.point, se_old_r.point, se_new_l.point, se_new_r.point);
75 match inter {
76 LineIntersection::None => return less_if(sa_l > 0.),
77 LineIntersection::Point(p) => {
78 if p == se_new_l.point {
79 return less_if(sa_r > 0.);
80 } else {
81 return less_if(sa_l > 0.);
82 }
83 }
84 _ => {} }
86 }
87
88 if se_old_l.is_subject == se_new_l.is_subject {
90 if se_old_l.point == se_new_l.point {
91 less_if(se_old_l.contour_id < se_new_l.contour_id)
96 } else {
97 less_if(true)
100 }
101 } else {
102 less_if(se_old_l.is_subject)
103 }
104 } else {
105 debug_assert!(false, "Other events should always be defined in compare_segment.");
106 less_if(true)
107 }
108}
109
110#[cfg(test)]
111mod test {
112 use super::super::sweep_event::SweepEvent;
113 use super::compare_segments;
114 use crate::splay::SplaySet;
115 use geo_types::Coordinate;
116 use std::cmp::Ordering;
117 use std::rc::{Rc, Weak};
118
119 macro_rules! assert_ordering {
120 ($se1:expr, $se2:expr, $ordering:expr) => {
121 let inverse_ordering = match $ordering {
122 Ordering::Less => Ordering::Greater,
123 Ordering::Greater => Ordering::Less,
124 _ => Ordering::Equal,
125 };
126 assert_eq!(
127 compare_segments(&$se1, &$se2),
128 $ordering,
129 "Comparing se1/se2 with expected value {:?}",
130 $ordering
131 );
132 assert_eq!(
133 compare_segments(&$se2, &$se1),
134 inverse_ordering,
135 "Comparing se2/se1 with expected value {:?}",
136 inverse_ordering
137 );
138 };
139 }
140
141 fn make_simple(
142 contour_id: u32,
143 x: f64,
144 y: f64,
145 other_x: f64,
146 other_y: f64,
147 is_subject: bool,
148 ) -> (Rc<SweepEvent<f64>>, Rc<SweepEvent<f64>>) {
149 let other = SweepEvent::new_rc(
150 contour_id,
151 Coordinate { x: other_x, y: other_y },
152 false,
153 Weak::new(),
154 is_subject,
155 true,
156 );
157 let event = SweepEvent::new_rc(
158 contour_id,
159 Coordinate { x, y },
160 true,
161 Rc::downgrade(&other),
162 is_subject,
163 true,
164 );
165 assert!(event.is_before(&other));
167
168 (event, other)
169 }
170
171 #[test]
172 fn not_collinear_shared_left_right_first() {
173 let (se1, _other1) = make_simple(0, 0.0, 0.0, 1.0, 1.0, false);
174 let (se2, _other2) = make_simple(0, 0.0, 0.0, 2.0, 3.0, false);
175
176 let mut tree = SplaySet::new(compare_segments);
177
178 tree.insert(se1);
179 tree.insert(se2);
180
181 let min_other = tree.min().unwrap().get_other_event().unwrap();
182 let max_other = tree.max().unwrap().get_other_event().unwrap();
183
184 assert_eq!(max_other.point, Coordinate { x: 2.0, y: 3.0 });
185 assert_eq!(min_other.point, Coordinate { x: 1.0, y: 1.0 });
186 }
187
188 #[test]
189 fn not_collinear_different_left_point_right_sort_y() {
190 let (se1, _other1) = make_simple(0, 0.0, 1.0, 1.0, 1.0, false);
191 let (se2, _other2) = make_simple(0, 0.0, 2.0, 2.0, 3.0, false);
192
193 let mut tree = SplaySet::new(compare_segments);
194
195 tree.insert(se1);
196 tree.insert(se2);
197
198 let min_other = tree.min().unwrap().get_other_event().unwrap();
199 let max_other = tree.max().unwrap().get_other_event().unwrap();
200
201 assert_eq!(min_other.point, Coordinate { x: 1.0, y: 1.0 });
202 assert_eq!(max_other.point, Coordinate { x: 2.0, y: 3.0 });
203 }
204
205 #[test]
206 fn not_collinear_order_in_sweep_line() {
207 let (se1, _other1) = make_simple(0, 0.0, 1.0, 2.0, 1.0, false);
208 let (se2, _other2) = make_simple(0, -1.0, 0.0, 2.0, 3.0, false);
209 let (se3, _other3) = make_simple(0, 0.0, 1.0, 3.0, 4.0, false);
210 let (se4, _other4) = make_simple(0, -1.0, 0.0, 3.0, 1.0, false);
211
212 assert_eq!(se1.cmp(&se2), Ordering::Less);
213 assert!(!se2.is_below(se1.point));
214 assert!(se2.is_above(se1.point));
215
216 assert_ordering!(se1, se2, Ordering::Less);
217
218 assert_eq!(se3.cmp(&se4), Ordering::Less);
219 assert!(!se4.is_above(se3.point));
220 }
221
222 #[test]
223 fn not_collinear_first_point_is_below() {
224 let (se2, _other2) = make_simple(0, 1.0, 1.0, 5.0, 1.0, false);
225 let (se1, _other1) = make_simple(0, -1.0, 0.0, 2.0, 3.0, false);
226
227 assert!(!se1.is_below(se2.point));
228 assert_ordering!(se1, se2, Ordering::Greater);
229 }
230
231 #[test]
232 fn collinear_segments() {
233 let (se1, _other1) = make_simple(0, 1.0, 1.0, 5.0, 1.0, true);
234 let (se2, _other2) = make_simple(0, 2.0, 01.0, 3.0, 1.0, false);
235
236 assert_ne!(se1.is_subject, se2.is_subject);
237 assert_ordering!(se1, se2, Ordering::Less);
238 }
239
240 #[test]
241 fn collinear_shared_left_point() {
242 {
243 let (se1, _other2) = make_simple(1, 0.0, 1.0, 5.0, 1.0, false);
244 let (se2, _other1) = make_simple(2, 0.0, 1.0, 3.0, 1.0, false);
245
246 assert_eq!(se1.is_subject, se2.is_subject);
247 assert_eq!(se1.point, se2.point);
248
249 assert_ordering!(se1, se2, Ordering::Less);
250 }
251 {
252 let (se1, _other2) = make_simple(2, 0.0, 1.0, 5.0, 1.0, false);
253 let (se2, _other1) = make_simple(1, 0.0, 1.0, 3.0, 1.0, false);
254
255 assert_ordering!(se1, se2, Ordering::Greater);
256 }
257 }
258
259 #[test]
260 fn collinear_same_polygon_different_left() {
261 let (se1, _other2) = make_simple(0, 1.0, 1.0, 5.0, 1.0, true);
262 let (se2, _other1) = make_simple(0, 2.0, 1.0, 3.0, 1.0, true);
263
264 assert_eq!(se1.is_subject, se2.is_subject);
265 assert_ne!(se1.point, se2.point);
266 assert_ordering!(se1, se2, Ordering::Less);
267 }
268
269 #[test]
270 fn t_shaped_cases() {
271 let (se1, _other1) = make_simple(0, 0.0, 0.0, 1.0, 1.0, true);
274 let (se2, _other2) = make_simple(0, 0.5, 0.5, 1.0, 0.0, true);
275 assert_ordering!(se1, se2, Ordering::Greater);
276
277 let (se1, _other1) = make_simple(0, 0.0, 1.0, 1.0, 0.0, true);
280 let (se2, _other2) = make_simple(0, 0.5, 0.5, 1.0, 1.0, true);
281 assert_ordering!(se1, se2, Ordering::Less);
282
283 let (se1, _other1) = make_simple(0, 0.0, 1.0, 1.0, 1.0, true);
285 let (se2, _other2) = make_simple(0, 0.5, 0.0, 0.5, 1.0, true);
286 assert_ordering!(se1, se2, Ordering::Greater);
287
288 let (se1, _other1) = make_simple(0, 0.0, 0.0, 1.0, 0.0, true);
290 let (se2, _other2) = make_simple(0, 0.5, 0.0, 0.5, 1.0, true);
291 assert_ordering!(se1, se2, Ordering::Less);
292 }
293
294 #[test]
295 fn vertical_segment() {
296 let (se1, _other1) = make_simple(0, 0.0, -1.0, 0.0, 1.0, true);
298
299 let (se2, _other2) = make_simple(0, -1.0, 1.0, 0.0, 1.0, true);
301 assert_ordering!(se1, se2, Ordering::Less);
302 let (se2, _other2) = make_simple(0, 0.0, 1.0, 1.0, 1.0, true);
303 assert_ordering!(se1, se2, Ordering::Less);
304 let (se2, _other2) = make_simple(0, -1.0, 2.0, 0.0, 2.0, true);
305 assert_ordering!(se1, se2, Ordering::Less);
306 let (se2, _other2) = make_simple(0, 0.0, 2.0, 1.0, 2.0, true);
307 assert_ordering!(se1, se2, Ordering::Less);
308 let (se2, _other2) = make_simple(0, 0.0, 1.0, 0.0, 2.0, true);
309 assert_ordering!(se1, se2, Ordering::Less);
310
311 let (se2, _other2) = make_simple(0, -1.0, -1.0, 0.0, -1.0, true);
313 assert_ordering!(se1, se2, Ordering::Greater);
314 let (se2, _other2) = make_simple(0, 0.0, -1.0, 1.0, -1.0, true);
315 assert_ordering!(se1, se2, Ordering::Greater);
316 let (se2, _other2) = make_simple(0, -1.0, -2.0, 0.0, -2.0, true);
317 assert_ordering!(se1, se2, Ordering::Greater);
318 let (se2, _other2) = make_simple(0, 0.0, -2.0, 1.0, -2.0, true);
319 assert_ordering!(se1, se2, Ordering::Greater);
320 let (se2, _other2) = make_simple(0, 0.0, -2.0, 0.0, -1.0, true);
321 assert_ordering!(se1, se2, Ordering::Greater);
322
323 let (se2, _other2) = make_simple(0, 0.0, -0.5, 0.0, 0.5, true);
325 assert_ordering!(se1, se2, Ordering::Less);
326 }
331}