1use super::{Mesh, F_HEAD, INVALID};
5
6impl Mesh {
7 pub fn tessellate_mono_region(&mut self, face: super::FaceIdx) -> bool {
10 use crate::geom::{edge_sign, vert_leq};
11
12 let mut up = match self.face_edge(face) {
13 Some(edge) => edge,
14 None => return false,
15 };
16 let up_lnext = match self.edge_lnext(up) {
17 Some(edge) => edge,
18 None => return false,
19 };
20 let up_lnext_lnext = match self.edge_lnext(up_lnext) {
21 Some(edge) => edge,
22 None => return false,
23 };
24 if up_lnext == up || up_lnext_lnext == up {
25 return false; }
27
28 let max_ring_iters = self.edges.len() + 2;
32 let mut ring_iter = 0usize;
33 loop {
34 let (up_dst_s, up_dst_t) = match self.dst_coords(up) {
35 Some(coords) => coords,
36 None => return false,
37 };
38 let (up_org_s, up_org_t) = match self.org_coords(up) {
39 Some(coords) => coords,
40 None => return false,
41 };
42 if !vert_leq(up_dst_s, up_dst_t, up_org_s, up_org_t) {
43 break;
44 }
45 up = match self.lprev_checked(up) {
46 Some(edge) => edge,
47 None => return false,
48 };
49 ring_iter += 1;
50 if ring_iter > max_ring_iters {
51 return false; }
53 }
54 ring_iter = 0;
55 loop {
56 let (up_org_s, up_org_t) = match self.org_coords(up) {
57 Some(coords) => coords,
58 None => return false,
59 };
60 let (up_dst_s, up_dst_t) = match self.dst_coords(up) {
61 Some(coords) => coords,
62 None => return false,
63 };
64 if !vert_leq(up_org_s, up_org_t, up_dst_s, up_dst_t) {
65 break;
66 }
67 up = match self.edge_lnext(up) {
68 Some(edge) => edge,
69 None => return false,
70 };
71 ring_iter += 1;
72 if ring_iter > max_ring_iters {
73 return false; }
75 }
76
77 let mut lo = match self.lprev_checked(up) {
78 Some(edge) => edge,
79 None => return false,
80 };
81
82 let max_tess_iters = self.edges.len() * 2 + 4;
83 let mut outer_iter = 0usize;
84 while match self.edge_lnext(up) {
85 Some(edge) => edge != lo,
86 None => return false,
87 } {
88 outer_iter += 1;
89 if outer_iter > max_tess_iters {
90 return false; }
92 let (up_dst_s, up_dst_t) = match self.dst_coords(up) {
93 Some(coords) => coords,
94 None => return false,
95 };
96 let (lo_org_s, lo_org_t) = match self.org_coords(lo) {
97 Some(coords) => coords,
98 None => return false,
99 };
100 if vert_leq(up_dst_s, up_dst_t, lo_org_s, lo_org_t) {
101 let mut inner_iter = 0usize;
103 while match self.edge_lnext(lo) {
104 Some(edge) => edge != up,
105 None => return false,
106 } {
107 inner_iter += 1;
108 if inner_iter > max_tess_iters {
109 return false;
110 }
111 let lo_lnext = match self.edge_lnext(lo) {
112 Some(edge) => edge,
113 None => return false,
114 };
115 let (lo_lnext_dst_s, lo_lnext_dst_t) = match self.dst_coords(lo_lnext) {
116 Some(coords) => coords,
117 None => return false,
118 };
119 let (lo_org2_s, lo_org2_t) = match self.org_coords(lo) {
120 Some(coords) => coords,
121 None => return false,
122 };
123 let (lo_dst_s, lo_dst_t) = match self.dst_coords(lo) {
124 Some(coords) => coords,
125 None => return false,
126 };
127 let goes_left = match self.edge_goes_left_checked(lo_lnext) {
128 Some(value) => value,
129 None => return false,
130 };
131 let sign_val = edge_sign(
132 lo_org2_s,
133 lo_org2_t,
134 lo_dst_s,
135 lo_dst_t,
136 lo_lnext_dst_s,
137 lo_lnext_dst_t,
138 );
139 if !goes_left && sign_val > 0.0 {
140 break;
141 }
142 let temp = match self.connect(lo_lnext, lo) {
143 Some(e) => e,
144 None => return false,
145 };
146 lo = match self.valid_edge(temp ^ 1) {
147 Some(edge) => edge,
148 None => return false,
149 };
150 }
151 lo = match self.lprev_checked(lo) {
152 Some(edge) => edge,
153 None => return false,
154 };
155 } else {
156 let mut inner_iter = 0usize;
158 while match self.edge_lnext(lo) {
159 Some(edge) => edge != up,
160 None => return false,
161 } {
162 inner_iter += 1;
163 if inner_iter > max_tess_iters {
164 return false;
165 }
166 let up_lprev = match self.lprev_checked(up) {
167 Some(edge) => edge,
168 None => return false,
169 };
170 let (up_lprev_org_s, up_lprev_org_t) = match self.org_coords(up_lprev) {
171 Some(coords) => coords,
172 None => return false,
173 };
174 let (up_dst2_s, up_dst2_t) = match self.dst_coords(up) {
175 Some(coords) => coords,
176 None => return false,
177 };
178 let (up_org2_s, up_org2_t) = match self.org_coords(up) {
179 Some(coords) => coords,
180 None => return false,
181 };
182 let goes_right = match self.edge_goes_right_checked(up_lprev) {
183 Some(value) => value,
184 None => return false,
185 };
186 let sign_val = edge_sign(
187 up_dst2_s,
188 up_dst2_t,
189 up_org2_s,
190 up_org2_t,
191 up_lprev_org_s,
192 up_lprev_org_t,
193 );
194 if !goes_right && sign_val < 0.0 {
195 break;
196 }
197 let temp = match self.connect(up, up_lprev) {
198 Some(e) => e,
199 None => return false,
200 };
201 up = match self.valid_edge(temp ^ 1) {
202 Some(edge) => edge,
203 None => return false,
204 };
205 }
206 up = match self.edge_lnext(up) {
207 Some(edge) => edge,
208 None => return false,
209 };
210 }
211 }
212
213 let mut lo_lnext = match self.edge_lnext(lo) {
215 Some(edge) => edge,
216 None => return false,
217 };
218 if lo_lnext == up {
219 return false; }
221 let mut fan_iter = 0usize;
222 while match self.edge_lnext(lo_lnext) {
223 Some(edge) => edge != up,
224 None => return false,
225 } {
226 fan_iter += 1;
227 if fan_iter > max_tess_iters {
228 return false;
229 }
230 let temp = match self.connect(lo_lnext, lo) {
231 Some(e) => e,
232 None => return false,
233 };
234 lo = match self.valid_edge(temp ^ 1) {
235 Some(edge) => edge,
236 None => return false,
237 };
238 lo_lnext = match self.edge_lnext(lo) {
239 Some(edge) => edge,
240 None => return false,
241 };
242 }
243
244 true
245 }
246
247 pub fn tessellate_interior(&mut self) -> bool {
249 let mut f = self.faces[F_HEAD as usize].next;
250 while f != F_HEAD {
251 if f == INVALID || f as usize >= self.faces.len() {
252 return false;
253 }
254 let next = self.faces[f as usize].next;
255 if self.faces[f as usize].inside {
256 if !self.tessellate_mono_region(f) {
257 self.faces[f as usize].inside = false;
262 }
263 }
264 f = next;
265 }
266 true
267 }
268
269 fn valid_edge(&self, edge: super::EdgeIdx) -> Option<super::EdgeIdx> {
270 if edge != INVALID && (edge as usize) < self.edges.len() {
271 Some(edge)
272 } else {
273 None
274 }
275 }
276
277 fn valid_vert(&self, vert: super::VertIdx) -> Option<super::VertIdx> {
278 if vert != INVALID && (vert as usize) < self.verts.len() {
279 Some(vert)
280 } else {
281 None
282 }
283 }
284
285 fn face_edge(&self, face: super::FaceIdx) -> Option<super::EdgeIdx> {
286 if face == INVALID || (face as usize) >= self.faces.len() {
287 return None;
288 }
289 self.valid_edge(self.faces[face as usize].an_edge)
290 }
291
292 fn edge_lnext(&self, edge: super::EdgeIdx) -> Option<super::EdgeIdx> {
293 let edge = self.valid_edge(edge)?;
294 self.valid_edge(self.edges[edge as usize].lnext)
295 }
296
297 fn dst_checked(&self, edge: super::EdgeIdx) -> Option<super::VertIdx> {
298 let sym = self.valid_edge(edge ^ 1)?;
299 self.valid_vert(self.edges[sym as usize].org)
300 }
301
302 fn org_coords(&self, edge: super::EdgeIdx) -> Option<(crate::geom::Real, crate::geom::Real)> {
303 let edge = self.valid_edge(edge)?;
304 let org = self.valid_vert(self.edges[edge as usize].org)?;
305 let vert = &self.verts[org as usize];
306 Some((vert.s, vert.t))
307 }
308
309 fn dst_coords(&self, edge: super::EdgeIdx) -> Option<(crate::geom::Real, crate::geom::Real)> {
310 let dst = self.dst_checked(edge)?;
311 let vert = &self.verts[dst as usize];
312 Some((vert.s, vert.t))
313 }
314
315 fn lprev_checked(&self, edge: super::EdgeIdx) -> Option<super::EdgeIdx> {
316 let edge = self.valid_edge(edge)?;
317 let onext = self.valid_edge(self.edges[edge as usize].onext)?;
318 self.valid_edge(onext ^ 1)
319 }
320
321 fn edge_goes_left_checked(&self, edge: super::EdgeIdx) -> Option<bool> {
322 let (ds, dt) = self.dst_coords(edge)?;
323 let (os, ot) = self.org_coords(edge)?;
324 Some(crate::geom::vert_leq(ds, dt, os, ot))
325 }
326
327 fn edge_goes_right_checked(&self, edge: super::EdgeIdx) -> Option<bool> {
328 let (os, ot) = self.org_coords(edge)?;
329 let (ds, dt) = self.dst_coords(edge)?;
330 Some(crate::geom::vert_leq(os, ot, ds, dt))
331 }
332}
333
334#[cfg(test)]
335mod tests {
336 use super::*;
337 use crate::mesh::{Face, HalfEdge};
338
339 #[test]
340 fn invalid_face_edge_returns_false() {
341 let mut mesh = Mesh::new();
342 mesh.faces.push(Face {
343 an_edge: INVALID,
344 inside: true,
345 ..Face::default()
346 });
347
348 assert!(!mesh.tessellate_mono_region(1));
349 }
350
351 #[test]
352 fn invalid_destination_vertex_returns_false() {
353 let mut mesh = Mesh::new();
354 mesh.faces.push(Face {
355 an_edge: 2,
356 inside: true,
357 ..Face::default()
358 });
359 mesh.edges.resize_with(7, HalfEdge::default);
360 mesh.edges[2].lnext = 4;
361 mesh.edges[4].lnext = 6;
362 mesh.edges[3].org = INVALID;
363
364 assert!(!mesh.tessellate_mono_region(1));
365 }
366}