geo/algorithm/monotone/
segment.rs

1use std::cell::{Ref, RefCell};
2use std::{cmp::Ordering, fmt::Debug, rc::Rc};
3
4use crate::sweep::{Event, EventType, LineOrPoint, SweepPoint};
5use crate::GeoNum;
6
7/// A segment in the sweep line algorithm.
8///
9/// Consists of a line and a payload.
10#[derive(Debug, Clone, Copy)]
11pub(crate) struct Segment<T: GeoNum, P> {
12    line: LineOrPoint<T>,
13    payload: P,
14}
15
16impl<T: GeoNum, P> Segment<T, P> {}
17
18impl<T: GeoNum, P> PartialOrd for Segment<T, P> {
19    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
20        self.line.partial_cmp(&other.line)
21    }
22}
23
24impl<T: GeoNum, P> PartialEq for Segment<T, P> {
25    fn eq(&self, other: &Self) -> bool {
26        self.partial_cmp(other) == Some(Ordering::Equal)
27    }
28}
29
30impl<T: GeoNum> From<LineOrPoint<T>> for Segment<T, ()> {
31    fn from(line: LineOrPoint<T>) -> Self {
32        Segment { line, payload: () }
33    }
34}
35
36impl<T: GeoNum, P> From<(LineOrPoint<T>, P)> for Segment<T, P> {
37    fn from((line, payload): (LineOrPoint<T>, P)) -> Self {
38        Segment { line, payload }
39    }
40}
41
42#[derive(Debug)]
43pub(crate) struct RcSegment<T: GeoNum, P>(Rc<RefCell<Segment<T, P>>>);
44
45impl<T: GeoNum, P> Clone for RcSegment<T, P> {
46    fn clone(&self) -> Self {
47        Self(self.0.clone())
48    }
49}
50
51impl<T: GeoNum, P: Clone + Debug> RcSegment<T, P> {
52    pub(crate) fn split_at(&self, pt: SweepPoint<T>) -> Self {
53        debug!("Splitting segment {:?} at {:?}", self, pt);
54        let mut borrow = RefCell::borrow_mut(&self.0);
55        let right = borrow.line.right();
56        borrow.line = LineOrPoint::from((borrow.line.left(), pt));
57
58        let new_seg = Segment::from((LineOrPoint::from((pt, right)), borrow.payload.clone()));
59        Self(Rc::new(new_seg.into()))
60    }
61}
62
63impl<T: GeoNum, P> RcSegment<T, P> {
64    pub(crate) fn payload(&self) -> Ref<P> {
65        let borrow = RefCell::borrow(&self.0);
66        Ref::map(borrow, |s| &s.payload)
67    }
68
69    pub(crate) fn line(&self) -> LineOrPoint<T> {
70        RefCell::borrow(&self.0).line
71    }
72
73    #[inline]
74    pub fn events(&self) -> [Event<T, RcSegment<T, P>>; 2] {
75        let geom = RefCell::borrow(&self.0).line;
76        let left = geom.left();
77        let right = geom.right();
78        [
79            Event {
80                point: left,
81                ty: if geom.is_line() {
82                    EventType::LineLeft
83                } else {
84                    EventType::PointLeft
85                },
86                payload: self.clone(),
87            },
88            Event {
89                point: right,
90                ty: if geom.is_line() {
91                    EventType::LineRight
92                } else {
93                    EventType::PointRight
94                },
95                payload: self.clone(),
96            },
97        ]
98    }
99}
100
101impl<T: GeoNum, P> From<Segment<T, P>> for RcSegment<T, P> {
102    fn from(value: Segment<T, P>) -> Self {
103        RcSegment(Rc::new(value.into()))
104    }
105}
106
107// Implement partial eq, partial ord, and eq for RcSegment
108impl<T: GeoNum, P> PartialEq for RcSegment<T, P> {
109    fn eq(&self, other: &Self) -> bool {
110        self.0.eq(&other.0)
111    }
112}
113
114impl<T: GeoNum, P> PartialOrd for RcSegment<T, P> {
115    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
116        self.0.partial_cmp(&other.0)
117    }
118}