Skip to main content

i_overlay/split/
solver_tree.rs

1use crate::core::solver::Solver;
2use crate::geom::line_range::LineRange;
3use crate::geom::x_segment::XSegment;
4use crate::segm::segment::Segment;
5use crate::segm::winding::WindingCount;
6use crate::split::snap_radius::SnapRadius;
7use crate::split::solver::SplitSolver;
8use alloc::vec::Vec;
9use i_tree::ExpiredVal;
10use i_tree::seg::exp::{SegExpCollection, SegRange};
11use i_tree::seg::tree::SegExpTree;
12
13#[derive(Debug, Clone, Copy)]
14struct IdSegment {
15    id: usize,
16    x_segment: XSegment,
17}
18
19impl ExpiredVal<i32> for IdSegment {
20    #[inline]
21    fn expiration(&self) -> i32 {
22        self.x_segment.b.x
23    }
24}
25
26impl SplitSolver {
27    pub(super) fn tree_split<C: WindingCount>(
28        &mut self,
29        snap_radius: SnapRadius,
30        segments: &mut Vec<Segment<C>>,
31        solver: &Solver,
32    ) -> bool {
33        let range: SegRange<i32> = segments.ver_range().into();
34        let mut tree: SegExpTree<i32, i32, IdSegment> = if let Some(tree) = SegExpTree::new(range) {
35            tree
36        } else {
37            return self.list_split(snap_radius, segments, solver);
38        };
39
40        let mut reusable_buffer = Vec::new();
41
42        let mut need_to_fix = true;
43        let mut any_intersection = false;
44
45        let mut snap_radius = snap_radius;
46
47        while need_to_fix && segments.len() > 2 {
48            need_to_fix = false;
49            self.marks.clear();
50
51            let radius = snap_radius.radius();
52
53            for (i, si) in segments.iter().enumerate() {
54                let time = si.x_segment.a.x;
55                let si_range = si.x_segment.y_range().into();
56                for sj in tree.iter_by_range(si_range, time) {
57                    let (this_index, scan_index, this, scan) = if si.x_segment < sj.x_segment {
58                        (i, sj.id, &si.x_segment, &sj.x_segment)
59                    } else {
60                        (sj.id, i, &sj.x_segment, &si.x_segment)
61                    };
62
63                    let is_round =
64                        SplitSolver::cross(this_index, scan_index, this, scan, &mut self.marks, radius);
65
66                    need_to_fix = is_round || need_to_fix;
67                }
68
69                tree.insert_by_range(si_range, si.id_segment(i));
70            }
71
72            if self.marks.is_empty() {
73                return any_intersection;
74            }
75
76            any_intersection = true;
77            tree.clear();
78
79            self.apply(segments, &mut reusable_buffer, solver);
80
81            snap_radius.increment();
82        }
83
84        any_intersection
85    }
86}
87
88impl From<LineRange> for SegRange<i32> {
89    #[inline]
90    fn from(value: LineRange) -> Self {
91        Self {
92            min: value.min,
93            max: value.max,
94        }
95    }
96}
97
98trait VerticalRange {
99    fn ver_range(&self) -> LineRange;
100}
101
102impl<C: Send> VerticalRange for Vec<Segment<C>> {
103    fn ver_range(&self) -> LineRange {
104        let mut min_y = self[0].x_segment.a.y;
105        let mut max_y = min_y;
106
107        for edge in self.iter() {
108            min_y = min_y.min(edge.x_segment.a.y);
109            max_y = max_y.max(edge.x_segment.a.y);
110            min_y = min_y.min(edge.x_segment.b.y);
111            max_y = max_y.max(edge.x_segment.b.y);
112        }
113
114        LineRange {
115            min: min_y,
116            max: max_y,
117        }
118    }
119}
120
121impl<C: Send> Segment<C> {
122    #[inline]
123    fn id_segment(&self, id: usize) -> IdSegment {
124        IdSegment {
125            id,
126            x_segment: self.x_segment,
127        }
128    }
129}