#![allow(dead_code)]
use std::cmp::Ordering;
use crate::signed_area::signed_area;
use crate::sweep_event::SweepEvent;
pub(crate) fn compare_events(arena: &[SweepEvent], i1: usize, i2: usize) -> Ordering {
let e1 = &arena[i1];
let e2 = &arena[i2];
let p1 = e1.point;
let p2 = e2.point;
if p1[0] > p2[0] {
return Ordering::Greater;
}
if p1[0] < p2[0] {
return Ordering::Less;
}
if p1[1] != p2[1] {
return if p1[1] > p2[1] {
Ordering::Greater
} else {
Ordering::Less
};
}
special_cases(arena, e1, e2)
}
fn special_cases(arena: &[SweepEvent], e1: &SweepEvent, e2: &SweepEvent) -> Ordering {
if e1.left != e2.left {
return if e1.left {
Ordering::Greater
} else {
Ordering::Less
};
}
let o1 = arena[e1.other_event.expect("compare_events: e1 has no peer")].point;
let o2 = arena[e2.other_event.expect("compare_events: e2 has no peer")].point;
if signed_area(e1.point, o1, o2) != 0 {
return if !e1.is_below(o1, o2) {
Ordering::Greater
} else {
Ordering::Less
};
}
if !e1.is_subject() && e2.is_subject() {
Ordering::Greater
} else {
Ordering::Less
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::edge_type::EdgeType;
use crate::sweep_event::PolygonType;
fn add_segment(
arena: &mut Vec<SweepEvent>,
left_pt: [f64; 2],
right_pt: [f64; 2],
polygon_type: PolygonType,
) -> (usize, usize) {
let left_idx = arena.len();
arena.push(SweepEvent::new(
left_pt,
true,
polygon_type,
EdgeType::Normal,
));
let right_idx = arena.len();
arena.push(SweepEvent::new(
right_pt,
false,
polygon_type,
EdgeType::Normal,
));
arena[left_idx].other_event = Some(right_idx);
arena[right_idx].other_event = Some(left_idx);
(left_idx, right_idx)
}
fn add_bare_event(arena: &mut Vec<SweepEvent>, point: [f64; 2], left: bool) -> usize {
let idx = arena.len();
arena.push(SweepEvent::new(
point,
left,
PolygonType::Subject,
EdgeType::Normal,
));
idx
}
#[test]
fn compares_x_coordinates() {
let mut arena = Vec::new();
let e1 = add_bare_event(&mut arena, [0.0, 0.0], true);
let e2 = add_bare_event(&mut arena, [0.5, 0.5], true);
assert_eq!(compare_events(&arena, e1, e2), Ordering::Less);
assert_eq!(compare_events(&arena, e2, e1), Ordering::Greater);
}
#[test]
fn compares_y_coordinates_when_x_ties() {
let mut arena = Vec::new();
let e1 = add_bare_event(&mut arena, [0.0, 0.0], true);
let e2 = add_bare_event(&mut arena, [0.0, 0.5], true);
assert_eq!(compare_events(&arena, e1, e2), Ordering::Less);
assert_eq!(compare_events(&arena, e2, e1), Ordering::Greater);
}
#[test]
fn processes_right_endpoint_before_left_when_points_tie() {
let mut arena = Vec::new();
let e1 = add_bare_event(&mut arena, [0.0, 0.0], true);
let e2 = add_bare_event(&mut arena, [0.0, 0.0], false);
assert_eq!(compare_events(&arena, e1, e2), Ordering::Greater);
assert_eq!(compare_events(&arena, e2, e1), Ordering::Less);
}
#[test]
fn shared_start_not_collinear_processes_lower_edge_first() {
let mut arena = Vec::new();
let (e1, _) = add_segment(&mut arena, [0.0, 0.0], [1.0, 1.0], PolygonType::Subject);
let (e2, _) = add_segment(&mut arena, [0.0, 0.0], [2.0, 3.0], PolygonType::Subject);
assert_eq!(compare_events(&arena, e1, e2), Ordering::Less);
assert_eq!(compare_events(&arena, e2, e1), Ordering::Greater);
}
#[test]
fn collinear_subject_sorts_before_clipping() {
let mut arena = Vec::new();
let (e1, _) = add_segment(&mut arena, [0.0, 0.0], [1.0, 1.0], PolygonType::Subject);
let (e2, _) = add_segment(&mut arena, [0.0, 0.0], [2.0, 2.0], PolygonType::Clipping);
assert_eq!(compare_events(&arena, e1, e2), Ordering::Less);
assert_eq!(compare_events(&arena, e2, e1), Ordering::Greater);
}
}