#![allow(dead_code)]
use std::cmp::Ordering;
use crate::compare_events::compare_events;
use crate::edge_type::EdgeType;
#[cfg(debug_assertions)]
use crate::equals::equals;
use crate::sweep_event::SweepEvent;
use crate::types::Position;
pub(crate) fn divide_segment(
arena: &mut Vec<SweepEvent>,
event_idx: usize,
p: Position,
) -> (usize, usize) {
let polygon_type = arena[event_idx].polygon_type;
let contour_id = arena[event_idx].contour_id;
let other_event_idx = arena[event_idx]
.other_event
.expect("divide_segment: event has no peer");
#[cfg(debug_assertions)]
if equals(arena[event_idx].point, arena[other_event_idx].point) {
eprintln!(
"divide_segment: collapsed segment at {:?}",
arena[event_idx].point,
);
}
let r_idx = arena.len();
let mut r = SweepEvent::new(p, false, polygon_type, EdgeType::Normal);
r.other_event = Some(event_idx);
r.contour_id = contour_id;
arena.push(r);
let l_idx = arena.len();
let mut l = SweepEvent::new(p, true, polygon_type, EdgeType::Normal);
l.other_event = Some(other_event_idx);
l.contour_id = contour_id;
arena.push(l);
if compare_events(arena, l_idx, other_event_idx) == Ordering::Greater {
arena[other_event_idx].left = true;
arena[l_idx].left = false;
}
arena[other_event_idx].other_event = Some(l_idx);
arena[event_idx].other_event = Some(r_idx);
(l_idx, r_idx)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::sweep_event::PolygonType;
fn add_segment(
arena: &mut Vec<SweepEvent>,
left_pt: Position,
right_pt: Position,
polygon_type: PolygonType,
) -> 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
}
#[test]
fn dividing_two_segments_at_their_intersection_produces_six_events() {
let mut arena = Vec::new();
let se1 = add_segment(&mut arena, [0.0, 0.0], [5.0, 5.0], PolygonType::Subject);
let se2 = add_segment(&mut arena, [0.0, 5.0], [5.0, 0.0], PolygonType::Clipping);
assert_eq!(arena.len(), 4);
let cross = [2.5, 2.5];
let (l1, r1) = divide_segment(&mut arena, se1, cross);
let (l2, r2) = divide_segment(&mut arena, se2, cross);
assert_eq!(arena.len(), 8);
for idx in [l1, r1, l2, r2] {
assert_eq!(arena[idx].point, cross);
}
}
#[test]
fn divide_segment_patches_links_correctly() {
let mut arena = Vec::new();
let se = add_segment(&mut arena, [0.0, 0.0], [10.0, 10.0], PolygonType::Subject);
let original_other = arena[se].other_event.unwrap();
let p = [3.0, 3.0];
let (l, r) = divide_segment(&mut arena, se, p);
assert_eq!(arena[r].other_event, Some(se));
assert_eq!(arena[l].other_event, Some(original_other));
assert_eq!(arena[se].other_event, Some(r));
assert_eq!(arena[original_other].other_event, Some(l));
}
#[test]
fn divide_segment_propagates_contour_id_and_polygon_type() {
let mut arena = Vec::new();
let se = add_segment(&mut arena, [0.0, 0.0], [4.0, 4.0], PolygonType::Clipping);
arena[se].contour_id = Some(7);
let (l, r) = divide_segment(&mut arena, se, [2.0, 2.0]);
assert_eq!(arena[l].contour_id, Some(7));
assert_eq!(arena[r].contour_id, Some(7));
assert_eq!(arena[l].polygon_type, PolygonType::Clipping);
assert_eq!(arena[r].polygon_type, PolygonType::Clipping);
}
#[test]
fn divided_events_are_left_right_at_split_point() {
let mut arena = Vec::new();
let se = add_segment(&mut arena, [0.0, 0.0], [10.0, 10.0], PolygonType::Subject);
let (l, r) = divide_segment(&mut arena, se, [3.0, 3.0]);
assert!(arena[l].left);
assert!(!arena[r].left);
}
}