poly2tri_rs/
triangles.rs

1use crate::shape::InnerTriangle;
2
3#[derive(Debug, Hash, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
4pub struct TriangleId(usize);
5
6impl TriangleId {
7    pub const INVALID: TriangleId = TriangleId(usize::MAX);
8
9    /// whether id is invalid
10    pub fn invalid(&self) -> bool {
11        self.0 == Self::INVALID.0
12    }
13
14    pub fn get<'a, 'b>(&'a self, triangles: &'b TriangleStore) -> &'b InnerTriangle {
15        triangles.get_unchecked(*self)
16    }
17
18    pub fn try_get<'a, 'b>(&'a self, triangles: &'b TriangleStore) -> Option<&'b InnerTriangle> {
19        triangles.get(*self)
20    }
21
22    pub fn as_usize(&self) -> usize {
23        self.0
24    }
25
26    pub fn from_index(index: usize) -> Self {
27        Self(index)
28    }
29
30    pub fn into_option(self) -> Option<Self> {
31        if self.invalid() {
32            None
33        } else {
34            Some(self)
35        }
36    }
37}
38
39/// Triangle store, store triangles and their neighborhood relations
40// Note: For n vetexes, there will around n - 2 triangles, so space complexity is
41//       O(n).
42#[derive(Debug)]
43pub struct TriangleStore {
44    triangles: Vec<InnerTriangle>,
45}
46
47impl TriangleStore {
48    pub fn new() -> Self {
49        Self { triangles: vec![] }
50    }
51
52    pub fn with_capacity(capacity: usize) -> Self {
53        Self {
54            triangles: Vec::with_capacity(capacity),
55        }
56    }
57
58    /// Returns number of triangles
59    pub fn len(&self) -> usize {
60        self.triangles.len()
61    }
62
63    /// insert a new triangle
64    pub fn insert(&mut self, triangle: InnerTriangle) -> TriangleId {
65        let id = TriangleId::from_index(self.triangles.len());
66        self.triangles.push(triangle);
67        id
68    }
69
70    pub fn get(&self, id: TriangleId) -> Option<&InnerTriangle> {
71        if id == TriangleId::INVALID {
72            return None;
73        }
74        unsafe { Some(self.triangles.get_unchecked(id.as_usize())) }
75    }
76
77    pub fn get_unchecked(&self, id: TriangleId) -> &InnerTriangle {
78        debug_assert!(!id.invalid());
79        unsafe { self.triangles.get_unchecked(id.as_usize()) }
80    }
81
82    pub fn get_mut(&mut self, id: TriangleId) -> Option<&mut InnerTriangle> {
83        self.triangles.get_mut(id.as_usize())
84    }
85
86    pub(crate) unsafe fn get_mut_two(
87        &mut self,
88        id_0: TriangleId,
89        id_1: TriangleId,
90    ) -> (&mut InnerTriangle, &mut InnerTriangle) {
91        assert!(
92            id_0 != id_1
93                && id_0.as_usize() < self.triangles.len()
94                && id_1.as_usize() < self.triangles.len()
95        );
96
97        let slice: *mut InnerTriangle = self.triangles.as_mut_ptr();
98
99        // satefy: asserted that id_0 != id_1 && id_0 < len && id_1 < len
100        let ref_0 = unsafe { &mut *slice.add(id_0.as_usize()) };
101        let ref_1 = unsafe { &mut *slice.add(id_1.as_usize()) };
102
103        (ref_0, ref_1)
104    }
105
106    pub(crate) unsafe fn get_mut_six(
107        &mut self,
108        id_0: TriangleId,
109        id_1: TriangleId,
110        id_2: TriangleId,
111        id_3: TriangleId,
112        id_4: TriangleId,
113        id_5: TriangleId,
114    ) -> (
115        &mut InnerTriangle,
116        &mut InnerTriangle,
117        Option<&mut InnerTriangle>,
118        Option<&mut InnerTriangle>,
119        Option<&mut InnerTriangle>,
120        Option<&mut InnerTriangle>,
121    ) {
122        assert!(
123            id_0 != id_1
124                && id_0.as_usize() < self.triangles.len()
125                && id_1.as_usize() < self.triangles.len()
126        );
127
128        let slice: *mut InnerTriangle = self.triangles.as_mut_ptr();
129
130        // satefy: asserted that id_0 != id_1 && id_0 < len && id_1 < len
131        let ref_0 = unsafe { &mut *slice.add(id_0.as_usize()) };
132        let ref_1 = unsafe { &mut *slice.add(id_1.as_usize()) };
133        let ref_2 = if !id_2.invalid() {
134            Some(unsafe { &mut *slice.add(id_2.as_usize()) })
135        } else {
136            None
137        };
138
139        let ref_3 = if !id_3.invalid() {
140            Some(unsafe { &mut *slice.add(id_3.as_usize()) })
141        } else {
142            None
143        };
144
145        let ref_4 = if !id_4.invalid() {
146            Some(unsafe { &mut *slice.add(id_4.as_usize()) })
147        } else {
148            None
149        };
150
151        let ref_5 = if !id_5.invalid() {
152            Some(unsafe { &mut *slice.add(id_5.as_usize()) })
153        } else {
154            None
155        };
156
157        (ref_0, ref_1, ref_2, ref_3, ref_4, ref_5)
158    }
159
160    pub fn get_mut_unchecked(&mut self, id: TriangleId) -> &mut InnerTriangle {
161        unsafe { self.triangles.get_unchecked_mut(id.as_usize()) }
162    }
163
164    pub fn iter(&self) -> impl Iterator<Item = (TriangleId, &InnerTriangle)> {
165        self.triangles
166            .iter()
167            .enumerate()
168            .map(|(idx, t)| (TriangleId::from_index(idx), t))
169    }
170
171    /// mark two triangle as neighbor
172    pub fn mark_neighbor(&mut self, left: TriangleId, right: TriangleId) {
173        let (left_triangle, right_triangle) = unsafe { self.get_mut_two(left, right) };
174        Self::mark_neighbor_for_two_mut(left, right, left_triangle, right_triangle)
175    }
176
177    /// mark two triangle as neighbor
178    /// also clears delaunay flag for the common edge
179    pub fn mark_neighbor_for_two_mut(
180        left: TriangleId,
181        right: TriangleId,
182        left_triangle: &mut InnerTriangle,
183        right_triangle: &mut InnerTriangle,
184    ) {
185        let Some((l_ei, r_ei)) = left_triangle.common_edge_index(&right_triangle) else {
186            debug_assert!(false, "they are not neighbors");
187            return;
188        };
189
190        let is_constrained_edge =
191            left_triangle.is_constrained(l_ei) || right_triangle.is_constrained(r_ei);
192
193        left_triangle.neighbors[l_ei] = right;
194        left_triangle.set_constrained(l_ei, is_constrained_edge);
195        left_triangle.set_delaunay(l_ei, false);
196
197        right_triangle.neighbors[r_ei] = left;
198        right_triangle.set_constrained(r_ei, is_constrained_edge);
199        right_triangle.set_delaunay(r_ei, false);
200    }
201}
202
203#[cfg(test)]
204mod tests {
205    use crate::{points::PointsBuilder, shape::Point};
206
207    use super::*;
208
209    #[test]
210    fn test_triangles() {
211        let mut triangles = TriangleStore::new();
212        let mut points = PointsBuilder::default();
213
214        let p0 = points.add_steiner_point(Point::new(0., 0.));
215        let p1 = points.add_steiner_point(Point::new(2., 0.));
216        let p2 = points.add_steiner_point(Point::new(1., 2.));
217        let p3 = points.add_steiner_point(Point::new(4., 2.));
218
219        let t1 = triangles.insert(InnerTriangle::new(p0, p1, p2));
220        let t2 = triangles.insert(InnerTriangle::new(p2, p1, p3));
221
222        triangles.mark_neighbor(t1, t2);
223        {
224            let t = triangles.get(t1).unwrap();
225            assert_eq!(t.neighbors[0], t2);
226            let t = triangles.get(t2).unwrap();
227            assert_eq!(t.neighbors[2], t1);
228        }
229    }
230
231    #[test]
232    fn test_triangles_get_mut_two() {
233        let mut triangles = TriangleStore::new();
234        let mut points = PointsBuilder::default();
235
236        let p0 = points.add_steiner_point(Point::new(0., 0.));
237        let p1 = points.add_steiner_point(Point::new(2., 0.));
238        let p2 = points.add_steiner_point(Point::new(1., 2.));
239        let p3 = points.add_steiner_point(Point::new(4., 2.));
240
241        let t1 = triangles.insert(InnerTriangle::new(p0, p1, p2));
242        let t2 = triangles.insert(InnerTriangle::new(p1, p2, p3));
243
244        let (t1, t2) = unsafe { triangles.get_mut_two(t1, t2) };
245        assert_eq!(t1.points, [p0, p1, p2]);
246        assert_eq!(t2.points, [p1, p2, p3]);
247    }
248}