Checks if the collapse of the given half-edge is topologically legal
(&self, half_edge: HalfEdge)
| 202 | |
| 203 | /// Checks if the collapse of the given half-edge is topologically legal |
| 204 | pub fn is_collapse_ok(&self, half_edge: HalfEdge) -> Result<(), IllegalHalfEdgeCollapse> { |
| 205 | // Based on PMP library: |
| 206 | // https://github.com/pmp-library/pmp-library/blob/86099e4e274c310d23e8c46c4829f881242814d3/src/pmp/SurfaceMesh.cpp#L755 |
| 207 | |
| 208 | let v0v1 = half_edge; |
| 209 | let v1v0 = self.opposite(v0v1); |
| 210 | |
| 211 | let v0 = v1v0.to; // From vertex |
| 212 | let v1 = v0v1.to; // To vertex |
| 213 | |
| 214 | // Checks if edges to opposite vertex of half-edge are boundary edges and returns opposite vertex |
| 215 | let check_opposite_vertex = |
| 216 | |he: HalfEdge| -> Result<Option<usize>, IllegalHalfEdgeCollapse> { |
| 217 | if !he.is_boundary() { |
| 218 | let h1 = self.next(he); |
| 219 | let h2 = self.next(h1); |
| 220 | |
| 221 | if self.opposite(h1).is_boundary() && self.opposite(h2).is_boundary() { |
| 222 | return Err(IllegalHalfEdgeCollapse::BoundaryCollapse); |
| 223 | } |
| 224 | |
| 225 | // Return the opposite vertex |
| 226 | Ok(Some(h1.to)) |
| 227 | } else { |
| 228 | Ok(None) |
| 229 | } |
| 230 | }; |
| 231 | |
| 232 | // Notation: |
| 233 | // v_pos -> vertex opposite to the half-edge to collapse (v0v1) |
| 234 | // v_neg -> vertex opposite to the opposite half-edge to collapse (v1v0) |
| 235 | let v_pos = check_opposite_vertex(v0v1)?; |
| 236 | let v_neg = check_opposite_vertex(v1v0)?; |
| 237 | |
| 238 | if v_pos.is_none() || v_neg.is_none() { |
| 239 | return Err(IllegalHalfEdgeCollapse::FacelessEdge); |
| 240 | } |
| 241 | |
| 242 | // Test intersection of the one-rings of v0 and v1 |
| 243 | for &he in &self.vertex_half_edge_map[v0] { |
| 244 | let he = &self.half_edges[he]; |
| 245 | let vv = he.to; |
| 246 | if vv != v1 |
| 247 | && Some(vv) != v_pos |
| 248 | && Some(vv) != v_neg |
| 249 | && self.half_edge(vv, v1).is_some() |
| 250 | { |
| 251 | return Err(IllegalHalfEdgeCollapse::IntersectionOfOneRing); |
| 252 | } |
| 253 | } |
| 254 | |
| 255 | Ok(()) |
| 256 | } |
| 257 | |
| 258 | pub fn try_half_edge_collapse( |
| 259 | &mut self, |
no test coverage detected