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 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#[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 pub fn len(&self) -> usize {
60 self.triangles.len()
61 }
62
63 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 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 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 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 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}