#![allow(dead_code)]
use crate::compare_segments::compare_segments;
use crate::sweep_event::SweepEvent;
#[derive(Debug, Default)]
pub(crate) struct SweepLine {
events: Vec<usize>,
}
impl SweepLine {
pub(crate) fn new() -> Self {
Self { events: Vec::new() }
}
pub(crate) fn is_empty(&self) -> bool {
self.events.is_empty()
}
pub(crate) fn len(&self) -> usize {
self.events.len()
}
pub(crate) fn at(&self, position: usize) -> Option<usize> {
self.events.get(position).copied()
}
pub(crate) fn insert(&mut self, arena: &[SweepEvent], idx: usize) -> usize {
let pos = self
.events
.binary_search_by(|&existing| compare_segments(arena, existing, idx))
.unwrap_or_else(|p| p);
self.events.insert(pos, idx);
pos
}
pub(crate) fn position(&self, arena: &[SweepEvent], idx: usize) -> Option<usize> {
if let Ok(p) = self
.events
.binary_search_by(|&existing| compare_segments(arena, existing, idx))
{
if self.events[p] == idx {
return Some(p);
}
}
self.events.iter().position(|&e| e == idx)
}
pub(crate) fn remove(&mut self, arena: &[SweepEvent], idx: usize) -> bool {
match self.position(arena, idx) {
Some(pos) => {
self.events.remove(pos);
true
}
None => false,
}
}
pub(crate) fn remove_at(&mut self, position: usize) {
self.events.remove(position);
}
pub(crate) fn next(&self, position: usize) -> Option<usize> {
self.at(position + 1)
}
pub(crate) fn prev(&self, position: usize) -> Option<usize> {
position.checked_sub(1).and_then(|p| self.at(p))
}
pub(crate) fn min(&self) -> Option<usize> {
self.events.first().copied()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::edge_type::EdgeType;
use crate::sweep_event::PolygonType;
use crate::types::Position;
fn add_segment(arena: &mut Vec<SweepEvent>, left_pt: Position, right_pt: Position) -> usize {
let left_idx = arena.len();
arena.push(SweepEvent::new(
left_pt,
true,
PolygonType::Subject,
EdgeType::Normal,
));
let right_idx = arena.len();
arena.push(SweepEvent::new(
right_pt,
false,
PolygonType::Subject,
EdgeType::Normal,
));
arena[left_idx].other_event = Some(right_idx);
arena[right_idx].other_event = Some(left_idx);
left_idx
}
#[test]
fn empty_line_has_no_min() {
let sl = SweepLine::new();
assert!(sl.is_empty());
assert_eq!(sl.min(), None);
}
#[test]
fn insert_orders_by_compare_segments() {
let mut arena = Vec::new();
let lower = add_segment(&mut arena, [0.0, 0.0], [5.0, 1.0]);
let upper = add_segment(&mut arena, [0.0, 0.0], [5.0, 3.0]);
let mut sl = SweepLine::new();
sl.insert(&arena, upper);
sl.insert(&arena, lower);
assert_eq!(sl.at(0), Some(lower));
assert_eq!(sl.at(1), Some(upper));
assert_eq!(sl.min(), Some(lower));
}
#[test]
fn remove_takes_event_out_of_the_line() {
let mut arena = Vec::new();
let a = add_segment(&mut arena, [0.0, 0.0], [5.0, 1.0]);
let b = add_segment(&mut arena, [0.0, 0.0], [5.0, 3.0]);
let mut sl = SweepLine::new();
sl.insert(&arena, a);
sl.insert(&arena, b);
assert!(sl.remove(&arena, a));
assert_eq!(sl.len(), 1);
assert_eq!(sl.min(), Some(b));
assert!(!sl.remove(&arena, a));
}
#[test]
fn prev_and_next_navigate_neighbours() {
let mut arena = Vec::new();
let a = add_segment(&mut arena, [0.0, 0.0], [5.0, 1.0]);
let b = add_segment(&mut arena, [0.0, 0.0], [5.0, 2.0]);
let c = add_segment(&mut arena, [0.0, 0.0], [5.0, 3.0]);
let mut sl = SweepLine::new();
sl.insert(&arena, a);
sl.insert(&arena, b);
sl.insert(&arena, c);
let pos = sl.position(&arena, b).unwrap();
assert_eq!(sl.prev(pos), Some(a));
assert_eq!(sl.next(pos), Some(c));
}
#[test]
fn prev_at_position_zero_is_none() {
let mut arena = Vec::new();
let a = add_segment(&mut arena, [0.0, 0.0], [5.0, 1.0]);
let mut sl = SweepLine::new();
sl.insert(&arena, a);
assert_eq!(sl.prev(0), None);
}
}