#![allow(dead_code)]
use crate::edge_type::EdgeType;
use crate::types::Position;
#[derive(Debug, Clone)]
pub(crate) struct SweepEvent {
pub point: Position,
pub left: bool,
pub other_event: Option<usize>,
pub polygon_type: PolygonType,
pub edge_type: EdgeType,
pub in_out: bool,
pub other_in_out: bool,
pub prev_in_result: Option<usize>,
pub result_transition: i32,
pub other_pos: i32,
pub output_contour_id: i32,
pub is_exterior_ring: bool,
pub contour_id: Option<i32>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum PolygonType {
Subject,
Clipping,
}
impl SweepEvent {
pub(crate) fn new(
point: Position,
left: bool,
polygon_type: PolygonType,
edge_type: EdgeType,
) -> Self {
Self {
point,
left,
other_event: None,
polygon_type,
edge_type,
in_out: false,
other_in_out: false,
prev_in_result: None,
result_transition: 0,
other_pos: -1,
output_contour_id: -1,
is_exterior_ring: true,
contour_id: None,
}
}
}
impl SweepEvent {
pub(crate) fn is_below(&self, other_point: Position, p: Position) -> bool {
let p0 = self.point;
let p1 = other_point;
if self.left {
(p0[0] - p[0]) * (p1[1] - p[1]) - (p1[0] - p[0]) * (p0[1] - p[1]) > 0.0
} else {
(p1[0] - p[0]) * (p0[1] - p[1]) - (p0[0] - p[0]) * (p1[1] - p[1]) > 0.0
}
}
pub(crate) fn is_above(&self, other_point: Position, p: Position) -> bool {
!self.is_below(other_point, p)
}
pub(crate) fn is_vertical(&self, other_point: Position) -> bool {
self.point[0] == other_point[0]
}
pub(crate) fn in_result(&self) -> bool {
self.result_transition != 0
}
pub(crate) fn is_subject(&self) -> bool {
self.polygon_type == PolygonType::Subject
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn new_event_initializes_to_upstream_defaults() {
let e = SweepEvent::new([3.0, 4.0], true, PolygonType::Subject, EdgeType::Normal);
assert_eq!(e.point, [3.0, 4.0]);
assert!(e.left);
assert_eq!(e.other_event, None);
assert!(matches!(e.polygon_type, PolygonType::Subject));
assert!(!e.in_out);
assert!(!e.other_in_out);
assert_eq!(e.prev_in_result, None);
assert_eq!(e.result_transition, 0);
assert_eq!(e.other_pos, -1);
assert_eq!(e.output_contour_id, -1);
assert!(e.is_exterior_ring);
assert_eq!(e.contour_id, None);
}
#[test]
fn is_below_when_query_is_above_segment() {
let e = SweepEvent::new([0.0, 0.0], true, PolygonType::Subject, EdgeType::Normal);
assert!(e.is_below([4.0, 4.0], [1.0, 3.0]));
assert!(!e.is_above([4.0, 4.0], [1.0, 3.0]));
}
#[test]
fn is_below_false_when_query_is_below_segment() {
let e = SweepEvent::new([0.0, 0.0], true, PolygonType::Subject, EdgeType::Normal);
assert!(!e.is_below([4.0, 4.0], [3.0, 1.0]));
assert!(e.is_above([4.0, 4.0], [3.0, 1.0]));
}
#[test]
fn is_below_flips_when_event_is_right_endpoint() {
let e = SweepEvent::new([4.0, 4.0], false, PolygonType::Subject, EdgeType::Normal);
assert!(e.is_below([0.0, 0.0], [1.0, 3.0]));
assert!(!e.is_below([0.0, 0.0], [3.0, 1.0]));
}
#[test]
fn is_vertical() {
let e = SweepEvent::new([5.0, 0.0], true, PolygonType::Subject, EdgeType::Normal);
assert!(e.is_vertical([5.0, 10.0]));
assert!(!e.is_vertical([5.1, 10.0]));
}
#[test]
fn in_result_tracks_result_transition() {
let mut e = SweepEvent::new([0.0, 0.0], true, PolygonType::Subject, EdgeType::Normal);
assert!(!e.in_result());
e.result_transition = 1;
assert!(e.in_result());
e.result_transition = -1;
assert!(e.in_result());
e.result_transition = 0;
assert!(!e.in_result());
}
}