Developer Documentation

PolyConnectivity.cc
1 /* ========================================================================= *
2 * *
3 * OpenMesh *
4 * Copyright (c) 2001-2015, RWTH-Aachen University *
5 * Department of Computer Graphics and Multimedia *
6 * All rights reserved. *
7 * www.openmesh.org *
8 * *
9 *---------------------------------------------------------------------------*
10 * This file is part of OpenMesh. *
11 *---------------------------------------------------------------------------*
12 * *
13 * Redistribution and use in source and binary forms, with or without *
14 * modification, are permitted provided that the following conditions *
15 * are met: *
16 * *
17 * 1. Redistributions of source code must retain the above copyright notice, *
18 * this list of conditions and the following disclaimer. *
19 * *
20 * 2. Redistributions in binary form must reproduce the above copyright *
21 * notice, this list of conditions and the following disclaimer in the *
22 * documentation and/or other materials provided with the distribution. *
23 * *
24 * 3. Neither the name of the copyright holder nor the names of its *
25 * contributors may be used to endorse or promote products derived from *
26 * this software without specific prior written permission. *
27 * *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39 * *
40 * ========================================================================= */
41
42
43
44 //== IMPLEMENTATION ==========================================================
45 #include <OpenMesh/Core/Mesh/PolyConnectivity.hh>
46 #include <set>
47
48 namespace OpenMesh {
49
50 const PolyConnectivity::VertexHandle PolyConnectivity::InvalidVertexHandle;
51 const PolyConnectivity::HalfedgeHandle PolyConnectivity::InvalidHalfedgeHandle;
52 const PolyConnectivity::EdgeHandle PolyConnectivity::InvalidEdgeHandle;
53 const PolyConnectivity::FaceHandle PolyConnectivity::InvalidFaceHandle;
54
55 //-----------------------------------------------------------------------------
56
57 PolyConnectivity::HalfedgeHandle
58 PolyConnectivity::find_halfedge(VertexHandle _start_vh, VertexHandle _end_vh ) const
59 {
60 assert(_start_vh.is_valid() && _end_vh.is_valid());
61
62 for (ConstVertexOHalfedgeIter voh_it = cvoh_iter(_start_vh); voh_it.is_valid(); ++voh_it)
63 if (to_vertex_handle(*voh_it) == _end_vh)
64 return *voh_it;
65
66 return InvalidHalfedgeHandle;
67 }
68
69
70 bool PolyConnectivity::is_boundary(FaceHandle _fh, bool _check_vertex) const
71 {
72 for (ConstFaceEdgeIter cfeit = cfe_iter( _fh ); cfeit.is_valid(); ++cfeit)
73 if (is_boundary( *cfeit ) )
74 return true;
75
76 if (_check_vertex)
77 {
78 for (ConstFaceVertexIter cfvit = cfv_iter( _fh ); cfvit.is_valid(); ++cfvit)
79 if (is_boundary( *cfvit ) )
80 return true;
81 }
82 return false;
83 }
84
85 bool PolyConnectivity::is_manifold(VertexHandle _vh) const
86 {
87 /* The vertex is non-manifold if more than one gap exists, i.e.
88 more than one outgoing boundary halfedge. If (at least) one
89 boundary halfedge exists, the vertex' halfedge must be a
90 boundary halfedge. If iterating around the vertex finds another
91 boundary halfedge, the vertex is non-manifold. */
92
93 ConstVertexOHalfedgeIter vh_it(*this, _vh);
94 if (vh_it.is_valid())
95 for (++vh_it; vh_it.is_valid(); ++vh_it)
96 if (is_boundary(*vh_it))
97 return false;
98 return true;
99 }
100
101 //-----------------------------------------------------------------------------
102 void PolyConnectivity::adjust_outgoing_halfedge(VertexHandle _vh)
103 {
104 for (ConstVertexOHalfedgeIter vh_it=cvoh_iter(_vh); vh_it.is_valid(); ++vh_it)
105 {
106 if (is_boundary(*vh_it))
107 {
108 set_halfedge_handle(_vh, *vh_it);
109 break;
110 }
111 }
112 }
113
114 //-----------------------------------------------------------------------------
115
116 SmartFaceHandle
117 PolyConnectivity::add_face(const VertexHandle* _vertex_handles, size_t _vhs_size)
118 {
119 VertexHandle vh;
120 size_t i, ii, n(_vhs_size);
121 HalfedgeHandle inner_next, inner_prev,
122 outer_next, outer_prev,
123 boundary_next, boundary_prev,
124 patch_start, patch_end;
125
126
127 // Check sufficient working storage available
128 if (edgeData_.size() < n)
129 {
130 edgeData_.resize(n);
131 next_cache_.resize(6*n);
132 }
133
134 size_t next_cache_count = 0;
135
136 // don't allow degenerated faces
137 assert (n > 2);
138
139 // test for topological errors
140 for (i=0, ii=1; i<n; ++i, ++ii, ii%=n)
141 {
142 if ( !is_boundary(_vertex_handles[i]) )
143 {
144 omerr() << "PolyMeshT::add_face: complex vertex\n";
145 return make_smart(InvalidFaceHandle, this);
146 }
147
148 // Initialise edge attributes
149 edgeData_[i].halfedge_handle = find_halfedge(_vertex_handles[i],
150 _vertex_handles[ii]);
151 edgeData_[i].is_new = !edgeData_[i].halfedge_handle.is_valid();
152 edgeData_[i].needs_adjust = false;
153
154 if (!edgeData_[i].is_new && !is_boundary(edgeData_[i].halfedge_handle))
155 {
156 omerr() << "PolyMeshT::add_face: complex edge\n";
157 return make_smart(InvalidFaceHandle, this);
158 }
159 }
160
161 // re-link patches if necessary
162 for (i=0, ii=1; i<n; ++i, ++ii, ii%=n)
163 {
164 if (!edgeData_[i].is_new && !edgeData_[ii].is_new)
165 {
166 inner_prev = edgeData_[i].halfedge_handle;
167 inner_next = edgeData_[ii].halfedge_handle;
168
169
170 if (next_halfedge_handle(inner_prev) != inner_next)
171 {
172 // here comes the ugly part... we have to relink a whole patch
173
174 // search a free gap
175 // free gap will be between boundary_prev and boundary_next
176 outer_prev = opposite_halfedge_handle(inner_next);
177 outer_next = opposite_halfedge_handle(inner_prev);
178 boundary_prev = outer_prev;
179 do
180 boundary_prev =
181 opposite_halfedge_handle(next_halfedge_handle(boundary_prev));
182 while (!is_boundary(boundary_prev));
183 boundary_next = next_halfedge_handle(boundary_prev);
184
185 // ok ?
186 if (boundary_prev == inner_prev)
187 {
188 omerr() << "PolyMeshT::add_face: patch re-linking failed\n";
189 return make_smart(InvalidFaceHandle, this);
190 }
191
192 assert(is_boundary(boundary_prev));
193 assert(is_boundary(boundary_next));
194
195 // other halfedges' handles
196 patch_start = next_halfedge_handle(inner_prev);
197 patch_end = prev_halfedge_handle(inner_next);
198
199 assert(boundary_prev.is_valid());
200 assert(patch_start.is_valid());
201 assert(patch_end.is_valid());
202 assert(boundary_next.is_valid());
203 assert(inner_prev.is_valid());
204 assert(inner_next.is_valid());
205
206 // relink
207 next_cache_[next_cache_count++] = std::make_pair(boundary_prev, patch_start);
208 next_cache_[next_cache_count++] = std::make_pair(patch_end, boundary_next);
209 next_cache_[next_cache_count++] = std::make_pair(inner_prev, inner_next);
210 }
211 }
212 }
213
214 // create missing edges
215 for (i=0, ii=1; i<n; ++i, ++ii, ii%=n)
216 if (edgeData_[i].is_new)
217 edgeData_[i].halfedge_handle = new_edge(_vertex_handles[i], _vertex_handles[ii]);
218
219 // create the face
220 FaceHandle fh(new_face());
221 set_halfedge_handle(fh, edgeData_[n-1].halfedge_handle);
222
223 // setup halfedges
224 for (i=0, ii=1; i<n; ++i, ++ii, ii%=n)
225 {
226 vh = _vertex_handles[ii];
227
228 inner_prev = edgeData_[i].halfedge_handle;
229 inner_next = edgeData_[ii].halfedge_handle;
230 assert(inner_prev.is_valid());
231 assert(inner_next.is_valid());
232
233 size_t id = 0;
234 if (edgeData_[i].is_new) id |= 1;
235 if (edgeData_[ii].is_new) id |= 2;
236
237
238 if (id)
239 {
240 outer_prev = opposite_halfedge_handle(inner_next);
241 outer_next = opposite_halfedge_handle(inner_prev);
242 assert(outer_prev.is_valid());
243 assert(outer_next.is_valid());
244
245 // set outer links
246 switch (id)
247 {
248 case 1: // prev is new, next is old
249 boundary_prev = prev_halfedge_handle(inner_next);
250 assert(boundary_prev.is_valid());
251 next_cache_[next_cache_count++] = std::make_pair(boundary_prev, outer_next);
252 set_halfedge_handle(vh, outer_next);
253 break;
254
255 case 2: // next is new, prev is old
256 boundary_next = next_halfedge_handle(inner_prev);
257 assert(boundary_next.is_valid());
258 next_cache_[next_cache_count++] = std::make_pair(outer_prev, boundary_next);
259 set_halfedge_handle(vh, boundary_next);
260 break;
261
262 case 3: // both are new
263 if (!halfedge_handle(vh).is_valid())
264 {
265 set_halfedge_handle(vh, outer_next);
266 next_cache_[next_cache_count++] = std::make_pair(outer_prev, outer_next);
267 }
268 else
269 {
270 boundary_next = halfedge_handle(vh);
271 boundary_prev = prev_halfedge_handle(boundary_next);
272 assert(boundary_prev.is_valid());
273 assert(boundary_next.is_valid());
274 next_cache_[next_cache_count++] = std::make_pair(boundary_prev, outer_next);
275 next_cache_[next_cache_count++] = std::make_pair(outer_prev, boundary_next);
276 }
277 break;
278 }
279
280 // set inner link
281 next_cache_[next_cache_count++] = std::make_pair(inner_prev, inner_next);
282 }
283 else edgeData_[ii].needs_adjust = (halfedge_handle(vh) == inner_next);
284
285
286 // set face handle
287 set_face_handle(edgeData_[i].halfedge_handle, fh);
288 }
289
290 // process next halfedge cache
291 for (i = 0; i < next_cache_count; ++i)
292 set_next_halfedge_handle(next_cache_[i].first, next_cache_[i].second);
293
294
295 // adjust vertices' halfedge handle
296 for (i=0; i<n; ++i)
297 if (edgeData_[i].needs_adjust)
298 adjust_outgoing_halfedge(_vertex_handles[i]);
299
300 return make_smart(fh, this);
301 }
302
303 //-----------------------------------------------------------------------------
304
305 SmartFaceHandle PolyConnectivity::add_face(VertexHandle _vh0, VertexHandle _vh1, VertexHandle _vh2, VertexHandle _vh3)
306 {
307 VertexHandle vhs[4] = { _vh0, _vh1, _vh2, _vh3 };
308 return add_face(vhs, 4);
309 }
310
311 //-----------------------------------------------------------------------------
312
313 SmartFaceHandle PolyConnectivity::add_face(VertexHandle _vh0, VertexHandle _vh1, VertexHandle _vh2)
314 {
315 VertexHandle vhs[3] = { _vh0, _vh1, _vh2 };
316 return add_face(vhs, 3);
317 }
318
319 //-----------------------------------------------------------------------------
320
321 SmartFaceHandle PolyConnectivity::add_face(const std::vector<VertexHandle>& _vhandles)
322 { return add_face(&_vhandles.front(), _vhandles.size()); }
323
324 //-----------------------------------------------------------------------------
325
326 SmartFaceHandle PolyConnectivity::add_face(const std::vector<SmartVertexHandle>& _vhandles)
327 {
328 std::vector<VertexHandle> vhandles(_vhandles.begin(), _vhandles.end());
329 return add_face(&vhandles.front(), vhandles.size());
330 }
331
332
333 //-----------------------------------------------------------------------------
334 bool PolyConnectivity::is_collapse_ok(HalfedgeHandle v0v1)
335 {
336 //is edge already deleteed?
337 if (status(edge_handle(v0v1)).deleted())
338 {
339 return false;
340 }
341
342 HalfedgeHandle v1v0(opposite_halfedge_handle(v0v1));
343 VertexHandle v0(to_vertex_handle(v1v0));
344 VertexHandle v1(to_vertex_handle(v0v1));
345
346 bool v0v1_triangle = false;
347 bool v1v0_triangle = false;
348
349 if (!is_boundary(v0v1))
350 v0v1_triangle = valence(face_handle(v0v1)) == 3;
351
352 if (!is_boundary(v1v0))
353 v1v0_triangle = valence(face_handle(v1v0)) == 3;
354
355 //in a quadmesh we dont have the "next" or "previous" vhandle, so we need to look at previous and next on both sides
356 //VertexHandle v_01_p = from_vertex_handle(prev_halfedge_handle(v0v1));
357 VertexHandle v_01_n = to_vertex_handle(next_halfedge_handle(v0v1));
358
359 //VertexHandle v_10_p = from_vertex_handle(prev_halfedge_handle(v1v0));
360 VertexHandle v_10_n = to_vertex_handle(next_halfedge_handle(v1v0));
361
362 //are the vertices already deleted ?
363 if (status(v0).deleted() || status(v1).deleted())
364 {
365 return false;
366 }
367
368 //the edges v1-vl and vl-v0 must not be both boundary edges
369 //this test makes only sense in a polymesh if the side face is a triangle
370 VertexHandle vl;
371 if (!is_boundary(v0v1))
372 {
373 if (v0v1_triangle)
374 {
375 HalfedgeHandle h1 = next_halfedge_handle(v0v1);
376 HalfedgeHandle h2 = next_halfedge_handle(h1);
377
378 vl = to_vertex_handle(h1);
379
380 if (is_boundary(opposite_halfedge_handle(h1)) && is_boundary(opposite_halfedge_handle(h2)))
381 return false;
382 }
383 }
384
385 //the edges v0-vr and vr-v1 must not be both boundary edges
386 //this test makes only sense in a polymesh if the side face is a triangle
387 VertexHandle vr;
388 if (!is_boundary(v1v0))
389 {
390 if (v1v0_triangle)
391 {
392 HalfedgeHandle h1 = next_halfedge_handle(v1v0);
393 HalfedgeHandle h2 = next_halfedge_handle(h1);
394
395 vr = to_vertex_handle(h1);
396
397 if (is_boundary(opposite_halfedge_handle(h1)) && is_boundary(opposite_halfedge_handle(h2)))
398 return false;
399 }
400 }
401
402 // if vl and vr are equal and valid (e.g. triangle case) -> fail
403 if ( vl.is_valid() && (vl == vr)) return false;
404
405 // edge between two boundary vertices should be a boundary edge
406 if ( is_boundary(v0) && is_boundary(v1) && !is_boundary(v0v1) && !is_boundary(v1v0))
407 return false;
408
409 VertexVertexIter vv_it;
410 // test intersection of the one-rings of v0 and v1
411 for (vv_it = vv_iter(v0); vv_it.is_valid(); ++vv_it)
412 {
413 status(*vv_it).set_tagged(false);
414 }
415
416 for (vv_it = vv_iter(v1); vv_it.is_valid(); ++vv_it)
417 {
418 status(*vv_it).set_tagged(true);
419 }
420
421 for (vv_it = vv_iter(v0); vv_it.is_valid(); ++vv_it)
422 {
423 if (status(*vv_it).tagged() &&
424 !(*vv_it == v_01_n && v0v1_triangle) &&
425 !(*vv_it == v_10_n && v1v0_triangle)
426 )
427 {
428 return false;
429 }
430 }
431
432 //test for a face on the backside/other side that might degenerate
433 if (v0v1_triangle)
434 {
435 HalfedgeHandle one, two;
436 one = next_halfedge_handle(v0v1);
437 two = next_halfedge_handle(one);
438
439 one = opposite_halfedge_handle(one);
440 two = opposite_halfedge_handle(two);
441
442 if (face_handle(one) == face_handle(two) && valence(face_handle(one)) != 3)
443 {
444 return false;
445 }
446 }
447
448 if (v1v0_triangle)
449 {
450 HalfedgeHandle one, two;
451 one = next_halfedge_handle(v1v0);
452 two = next_halfedge_handle(one);
453
454 one = opposite_halfedge_handle(one);
455 two = opposite_halfedge_handle(two);
456
457 if (face_handle(one) == face_handle(two) && valence(face_handle(one)) != 3)
458 {
459 return false;
460 }
461 }
462
463 if (status(*vv_it).tagged() && v_01_n == v_10_n && v0v1_triangle && v1v0_triangle)
464 {
465 return false;
466 }
467
468 // passed all tests
469 return true;
470 }
471
472 //-----------------------------------------------------------------------------
473
474 void PolyConnectivity::delete_vertex(VertexHandle _vh, bool _delete_isolated_vertices)
475 {
476 // store incident faces
477 std::vector<FaceHandle> face_handles;
478 face_handles.reserve(8);
479 for (VFIter vf_it(vf_iter(_vh)); vf_it.is_valid(); ++vf_it)
480 face_handles.push_back(*vf_it);
481
482
483 // delete collected faces
484 std::vector<FaceHandle>::iterator fh_it(face_handles.begin()),
485 fh_end(face_handles.end());
486
487 for (; fh_it!=fh_end; ++fh_it)
488 delete_face(*fh_it, _delete_isolated_vertices);
489
490 status(_vh).set_deleted(true);
491 }
492
493 //-----------------------------------------------------------------------------
494
495 void PolyConnectivity::delete_edge(EdgeHandle _eh, bool _delete_isolated_vertices)
496 {
497 FaceHandle fh0(face_handle(halfedge_handle(_eh, 0)));
498 FaceHandle fh1(face_handle(halfedge_handle(_eh, 1)));
499
500 if (fh0.is_valid()) delete_face(fh0, _delete_isolated_vertices);
501 if (fh1.is_valid()) delete_face(fh1, _delete_isolated_vertices);
502
503 // If there is no face, we delete the edge
504 // here
505 if ( ! fh0.is_valid() && !fh1.is_valid()) {
506 // mark edge deleted if the mesh has a edge status
507 if ( has_edge_status() )
508 status(_eh).set_deleted(true);
509
510 // mark corresponding halfedges as deleted
511 // As the deleted edge is boundary,
512 // all corresponding halfedges will also be deleted.
513 if ( has_halfedge_status() ) {
514 status(halfedge_handle(_eh, 0)).set_deleted(true);
515 status(halfedge_handle(_eh, 1)).set_deleted(true);
516 }
517 }
518 }
519
520 //-----------------------------------------------------------------------------
521
522 void PolyConnectivity::delete_face(FaceHandle _fh, bool _delete_isolated_vertices)
523 {
524 assert(_fh.is_valid() && !status(_fh).deleted());
525
526 // mark face deleted
527 status(_fh).set_deleted(true);
528
529
530 // this vector will hold all boundary edges of face _fh
531 // these edges will be deleted
532 std::vector<EdgeHandle> deleted_edges;
533 deleted_edges.reserve(3);
534
535
536 // this vector will hold all vertices of face _fh
537 // for updating their outgoing halfedge
538 std::vector<VertexHandle> vhandles;
539 vhandles.reserve(3);
540
541
542 // for all halfedges of face _fh do:
543 // 1) invalidate face handle.
544 // 2) collect all boundary halfedges, set them deleted
545 // 3) store vertex handles
546 HalfedgeHandle hh;
547 for (FaceHalfedgeIter fh_it(fh_iter(_fh)); fh_it.is_valid(); ++fh_it)
548 {
549 hh = *fh_it;
550
551 set_boundary(hh);//set_face_handle(hh, InvalidFaceHandle);
552
553 if (is_boundary(opposite_halfedge_handle(hh)))
554 deleted_edges.push_back(edge_handle(hh));
555
556 vhandles.push_back(to_vertex_handle(hh));
557 }
558
559
560 // delete all collected (half)edges
561 // these edges were all boundary
562 // delete isolated vertices (if _delete_isolated_vertices is true)
563 if (!deleted_edges.empty())
564 {
565 std::vector<EdgeHandle>::iterator del_it(deleted_edges.begin()),
566 del_end(deleted_edges.end());
567 HalfedgeHandle h0, h1, next0, next1, prev0, prev1;
568 VertexHandle v0, v1;
569
570 for (; del_it!=del_end; ++del_it)
571 {
572 h0 = halfedge_handle(*del_it, 0);
573 v0 = to_vertex_handle(h0);
574 next0 = next_halfedge_handle(h0);
575 prev0 = prev_halfedge_handle(h0);
576
577 h1 = halfedge_handle(*del_it, 1);
578 v1 = to_vertex_handle(h1);
579 next1 = next_halfedge_handle(h1);
580 prev1 = prev_halfedge_handle(h1);
581
582 // adjust next and prev handles
583 set_next_halfedge_handle(prev0, next1);
584 set_next_halfedge_handle(prev1, next0);
585
586 // mark edge deleted if the mesh has a edge status
587 if ( has_edge_status() )
588 status(*del_it).set_deleted(true);
589
590
591 // mark corresponding halfedges as deleted
592 // As the deleted edge is boundary,
593 // all corresponding halfedges will also be deleted.
594 if ( has_halfedge_status() ) {
595 status(h0).set_deleted(true);
596 status(h1).set_deleted(true);
597 }
598
599 // update v0
600 if (halfedge_handle(v0) == h1)
601 {
602 // isolated ?
603 if (next0 == h1)
604 {
605 if (_delete_isolated_vertices)
606 status(v0).set_deleted(true);
607 set_isolated(v0);
608 }
609 else set_halfedge_handle(v0, next0);
610 }
611
612 // update v1
613 if (halfedge_handle(v1) == h0)
614 {
615 // isolated ?
616 if (next1 == h0)
617 {
618 if (_delete_isolated_vertices)
619 status(v1).set_deleted(true);
620 set_isolated(v1);
621 }
622 else set_halfedge_handle(v1, next1);
623 }
624 }
625 }
626
627 // update outgoing halfedge handles of remaining vertices
628 std::vector<VertexHandle>::iterator v_it(vhandles.begin()),
629 v_end(vhandles.end());
630 for (; v_it!=v_end; ++v_it)
631 adjust_outgoing_halfedge(*v_it);
632 }
633
634
635 //-----------------------------------------------------------------------------
636 void PolyConnectivity::collapse(HalfedgeHandle _hh)
637 {
638 HalfedgeHandle h0 = _hh;
639 HalfedgeHandle h1 = next_halfedge_handle(h0);
640 HalfedgeHandle o0 = opposite_halfedge_handle(h0);
641 HalfedgeHandle o1 = next_halfedge_handle(o0);
642
643 // remove edge
644 collapse_edge(h0);
645
646 // remove loops
647 if (next_halfedge_handle(next_halfedge_handle(h1)) == h1)
648 collapse_loop(next_halfedge_handle(h1));
649 if (next_halfedge_handle(next_halfedge_handle(o1)) == o1)
650 collapse_loop(o1);
651 }
652
653 //-----------------------------------------------------------------------------
654 void PolyConnectivity::collapse_edge(HalfedgeHandle _hh)
655 {
656 HalfedgeHandle h = _hh;
657 HalfedgeHandle hn = next_halfedge_handle(h);
658 HalfedgeHandle hp = prev_halfedge_handle(h);
659
660 HalfedgeHandle o = opposite_halfedge_handle(h);
661 HalfedgeHandle on = next_halfedge_handle(o);
662 HalfedgeHandle op = prev_halfedge_handle(o);
663
664 FaceHandle fh = face_handle(h);
665 FaceHandle fo = face_handle(o);
666
667 VertexHandle vh = to_vertex_handle(h);
668 VertexHandle vo = to_vertex_handle(o);
669
670
671
672 // halfedge -> vertex
673 for (VertexIHalfedgeIter vih_it(vih_iter(vo)); vih_it.is_valid(); ++vih_it)
674 set_vertex_handle(*vih_it, vh);
675
676
677 // halfedge -> halfedge
678 set_next_halfedge_handle(hp, hn);
679 set_next_halfedge_handle(op, on);
680
681
682 // face -> halfedge
683 if (fh.is_valid()) set_halfedge_handle(fh, hn);
684 if (fo.is_valid()) set_halfedge_handle(fo, on);
685
686
687 // vertex -> halfedge
688 if (halfedge_handle(vh) == o) set_halfedge_handle(vh, hn);
689 adjust_outgoing_halfedge(vh);
690 set_isolated(vo);
691
692 // delete stuff
693 status(edge_handle(h)).set_deleted(true);
694 status(vo).set_deleted(true);
695 if (has_halfedge_status())
696 {
697 status(h).set_deleted(true);
698 status(o).set_deleted(true);
699 }
700 }
701
702 //-----------------------------------------------------------------------------
703 void PolyConnectivity::collapse_loop(HalfedgeHandle _hh)
704 {
705 HalfedgeHandle h0 = _hh;
706 HalfedgeHandle h1 = next_halfedge_handle(h0);
707
708 HalfedgeHandle o0 = opposite_halfedge_handle(h0);
709 HalfedgeHandle o1 = opposite_halfedge_handle(h1);
710
711 VertexHandle v0 = to_vertex_handle(h0);
712 VertexHandle v1 = to_vertex_handle(h1);
713
714 FaceHandle fh = face_handle(h0);
715 FaceHandle fo = face_handle(o0);
716
717
718
719 // is it a loop ?
720 assert ((next_halfedge_handle(h1) == h0) && (h1 != o0));
721
722
723 // halfedge -> halfedge
724 set_next_halfedge_handle(h1, next_halfedge_handle(o0));
725 set_next_halfedge_handle(prev_halfedge_handle(o0), h1);
726
727
728 // halfedge -> face
729 set_face_handle(h1, fo);
730
731
732 // vertex -> halfedge
733 set_halfedge_handle(v0, h1); adjust_outgoing_halfedge(v0);
734 set_halfedge_handle(v1, o1); adjust_outgoing_halfedge(v1);
735
736
737 // face -> halfedge
738 if (fo.is_valid() && halfedge_handle(fo) == o0)
739 {
740 set_halfedge_handle(fo, h1);
741 }
742
743 // delete stuff
744 if (fh.is_valid())
745 {
746 set_halfedge_handle(fh, InvalidHalfedgeHandle);
747 status(fh).set_deleted(true);
748 }
749 status(edge_handle(h0)).set_deleted(true);
750 if (has_halfedge_status())
751 {
752 status(h0).set_deleted(true);
753 status(o0).set_deleted(true);
754 }
755 }
756
757 //-----------------------------------------------------------------------------
758 bool PolyConnectivity::is_simple_link(EdgeHandle _eh) const
759 {
760 HalfedgeHandle heh0 = halfedge_handle(_eh, 0);
761 HalfedgeHandle heh1 = halfedge_handle(_eh, 1);
762
763 //FaceHandle fh0 = face_handle(heh0);//fh0 or fh1 might be a invalid,
764 FaceHandle fh1 = face_handle(heh1);//i.e., representing the boundary
765
766 HalfedgeHandle next_heh = next_halfedge_handle(heh0);
767 while (next_heh != heh0)
768 {//check if there are no other edges shared between fh0 & fh1
769 if (opposite_face_handle(next_heh) == fh1)
770 {
771 return false;
772 }
773 next_heh = next_halfedge_handle(next_heh);
774 }
775 return true;
776 }
777
778 //-----------------------------------------------------------------------------
779 bool PolyConnectivity::is_simply_connected(FaceHandle _fh) const
780 {
781 std::set<FaceHandle> nb_fhs;
782 for (ConstFaceFaceIter cff_it = cff_iter(_fh); cff_it.is_valid(); ++cff_it)
783 {
784 if (nb_fhs.find(*cff_it) == nb_fhs.end())
785 {
786 nb_fhs.insert(*cff_it);
787 }
788 else
789 {//there is more than one link
790 return false;
791 }
792 }
793 return true;
794 }
795
796 //-----------------------------------------------------------------------------
797 PolyConnectivity::FaceHandle
798 PolyConnectivity::remove_edge(EdgeHandle _eh)
799 {
800 //don't allow "dangling" vertices and edges
801 assert(!status(_eh).deleted() && is_simple_link(_eh));
802
803 HalfedgeHandle heh0 = halfedge_handle(_eh, 0);
804 HalfedgeHandle heh1 = halfedge_handle(_eh, 1);
805
806 //deal with the faces
807 FaceHandle rem_fh = face_handle(heh0), del_fh = face_handle(heh1);
808 if (!del_fh.is_valid())
809 {//boundary case - we must delete the rem_fh
810 std::swap(del_fh, rem_fh);
811 }
812 assert(del_fh.is_valid());
813 /* for (FaceHalfedgeIter fh_it = fh_iter(del_fh); fh_it; ++fh_it)
814 {//set the face handle of the halfedges of del_fh to point to rem_fh
815 set_face_handle(fh_it, rem_fh);
816 } */
817 //fix the halfedge relations
818 HalfedgeHandle prev_heh0 = prev_halfedge_handle(heh0);
819 HalfedgeHandle prev_heh1 = prev_halfedge_handle(heh1);
820
821 HalfedgeHandle next_heh0 = next_halfedge_handle(heh0);
822 HalfedgeHandle next_heh1 = next_halfedge_handle(heh1);
823
824 set_next_halfedge_handle(prev_heh0, next_heh1);
825 set_next_halfedge_handle(prev_heh1, next_heh0);
826 //correct outgoing vertex handles for the _eh vertices (if needed)
827 VertexHandle vh0 = to_vertex_handle(heh0);
828 VertexHandle vh1 = to_vertex_handle(heh1);
829
830 if (halfedge_handle(vh0) == heh1)
831 {
832 set_halfedge_handle(vh0, next_heh0);
833 }
834 if (halfedge_handle(vh1) == heh0)
835 {
836 set_halfedge_handle(vh1, next_heh1);
837 }
838
839 //correct the hafledge handle of rem_fh if needed and preserve its first vertex
840 if (halfedge_handle(rem_fh) == heh0)
841 {//rem_fh is the face at heh0
842 set_halfedge_handle(rem_fh, prev_heh1);
843 }
844 else if (halfedge_handle(rem_fh) == heh1)
845 {//rem_fh is the face at heh1
846 set_halfedge_handle(rem_fh, prev_heh0);
847 }
848 for (FaceHalfedgeIter fh_it = fh_iter(rem_fh); fh_it.is_valid(); ++fh_it)
849 {//set the face handle of the halfedges of del_fh to point to rem_fh
850 set_face_handle(*fh_it, rem_fh);
851 }
852
853 status(_eh).set_deleted(true);
854 status(del_fh).set_deleted(true);
855 return rem_fh;//returns the remaining face handle
856 }
857
858 //-----------------------------------------------------------------------------
859 void PolyConnectivity::reinsert_edge(EdgeHandle _eh)
860 {
861 //this does not work without prev_halfedge_handle
862 assert_compile(sizeof(Halfedge) == sizeof(Halfedge_with_prev));
863 //shoudl be deleted
864 assert(status(_eh).deleted());
865 status(_eh).set_deleted(false);
866
867 HalfedgeHandle heh0 = halfedge_handle(_eh, 0);
868 HalfedgeHandle heh1 = halfedge_handle(_eh, 1);
869 FaceHandle rem_fh = face_handle(heh0), del_fh = face_handle(heh1);
870 if (!del_fh.is_valid())
871 {//boundary case - we must delete the rem_fh
872 std::swap(del_fh, rem_fh);
873 }
874 assert(status(del_fh).deleted());
875 status(del_fh).set_deleted(false);
876
877 //restore halfedge relations
878 HalfedgeHandle prev_heh0 = prev_halfedge_handle(heh0);
879 HalfedgeHandle prev_heh1 = prev_halfedge_handle(heh1);
880
881 HalfedgeHandle next_heh0 = next_halfedge_handle(heh0);
882 HalfedgeHandle next_heh1 = next_halfedge_handle(heh1);
883
884 set_next_halfedge_handle(prev_heh0, heh0);
885 set_prev_halfedge_handle(next_heh0, heh0);
886
887 set_next_halfedge_handle(prev_heh1, heh1);
888 set_prev_halfedge_handle(next_heh1, heh1);
889
890 for (FaceHalfedgeIter fh_it = fh_iter(del_fh); fh_it.is_valid(); ++fh_it)
891 {//reassign halfedges to del_fh
892 set_face_handle(*fh_it, del_fh);
893 }
894
895 if (face_handle(halfedge_handle(rem_fh)) == del_fh)
896 {//correct the halfedge handle of rem_fh
897 if (halfedge_handle(rem_fh) == prev_heh0)
898 {//rem_fh is the face at heh1
899 set_halfedge_handle(rem_fh, heh1);
900 }
901 else
902 {//rem_fh is the face at heh0
903 assert(halfedge_handle(rem_fh) == prev_heh1);
904 set_halfedge_handle(rem_fh, heh0);
905 }
906 }
907 }
908
909 //-----------------------------------------------------------------------------
910 PolyConnectivity::HalfedgeHandle
911 PolyConnectivity::insert_edge(HalfedgeHandle _prev_heh, HalfedgeHandle _next_heh)
912 {
913 assert(face_handle(_prev_heh) == face_handle(_next_heh));//only the manifold case
914 assert(next_halfedge_handle(_prev_heh) != _next_heh);//this can not be done
915 VertexHandle vh0 = to_vertex_handle(_prev_heh);
916 VertexHandle vh1 = from_vertex_handle(_next_heh);
917 //create the link between vh0 and vh1
918 HalfedgeHandle heh0 = new_edge(vh0, vh1);
919 HalfedgeHandle heh1 = opposite_halfedge_handle(heh0);
920 HalfedgeHandle next_prev_heh = next_halfedge_handle(_prev_heh);
921 HalfedgeHandle prev_next_heh = prev_halfedge_handle(_next_heh);
922 set_next_halfedge_handle(_prev_heh, heh0);
923 set_next_halfedge_handle(heh0, _next_heh);
924 set_next_halfedge_handle(prev_next_heh, heh1);
925 set_next_halfedge_handle(heh1, next_prev_heh);
926
927 //now set the face handles - the new face is assigned to heh0
928 FaceHandle new_fh = new_face();
929 set_halfedge_handle(new_fh, heh0);
930 for (FaceHalfedgeIter fh_it = fh_iter(new_fh); fh_it.is_valid(); ++fh_it)
931 {
932 set_face_handle(*fh_it, new_fh);
933 }
934 FaceHandle old_fh = face_handle(next_prev_heh);
935 set_face_handle(heh1, old_fh);
936 if (old_fh.is_valid() && face_handle(halfedge_handle(old_fh)) == new_fh)
937 {//fh pointed to one of the halfedges now assigned to new_fh
938 set_halfedge_handle(old_fh, heh1);
939 }
940 adjust_outgoing_halfedge(vh0);
941 adjust_outgoing_halfedge(vh1);
942 return heh0;
943 }
944
945 //-----------------------------------------------------------------------------
946 void PolyConnectivity::triangulate(FaceHandle _fh)
947 {
948 /*
949 Split an arbitrary face into triangles by connecting
950 each vertex of fh after its second to vh.
951
952 - fh will remain valid (it will become one of the
953 triangles)
954 - the halfedge handles of the new triangles will
955 point to the old halfedges
956 */
957
958 HalfedgeHandle base_heh(halfedge_handle(_fh));
959 VertexHandle start_vh = from_vertex_handle(base_heh);
960 HalfedgeHandle prev_heh(prev_halfedge_handle(base_heh));
961 HalfedgeHandle next_heh(next_halfedge_handle(base_heh));
962
963 while (to_vertex_handle(next_halfedge_handle(next_heh)) != start_vh)
964 {
965 HalfedgeHandle next_next_heh(next_halfedge_handle(next_heh));
966
967 FaceHandle new_fh = new_face();
968 set_halfedge_handle(new_fh, base_heh);
969
970 HalfedgeHandle new_heh = new_edge(to_vertex_handle(next_heh), start_vh);
971
972 set_next_halfedge_handle(base_heh, next_heh);
973 set_next_halfedge_handle(next_heh, new_heh);
974 set_next_halfedge_handle(new_heh, base_heh);
975
976 set_face_handle(base_heh, new_fh);
977 set_face_handle(next_heh, new_fh);
978 set_face_handle(new_heh, new_fh);
979
980 copy_all_properties(prev_heh, new_heh, true);
981 copy_all_properties(prev_heh, opposite_halfedge_handle(new_heh), true);
982 copy_all_properties(_fh, new_fh, true);
983
984 base_heh = opposite_halfedge_handle(new_heh);
985 next_heh = next_next_heh;
986 }
987 set_halfedge_handle(_fh, base_heh); //the last face takes the handle _fh
988
989 set_next_halfedge_handle(base_heh, next_heh);
990 set_next_halfedge_handle(next_halfedge_handle(next_heh), base_heh);
991
992 set_face_handle(base_heh, _fh);
993 }
994
995 //-----------------------------------------------------------------------------
996 void PolyConnectivity::triangulate()
997 {
998 /* The iterators will stay valid, even though new faces are added,
999 because they are now implemented index-based instead of
1000 pointer-based.
1001 */
1002 FaceIter f_it(faces_begin()), f_end(faces_end());
1003 for (; f_it!=f_end; ++f_it)
1004 triangulate(*f_it);
1005 }
1006
1007 //-----------------------------------------------------------------------------
1008 void PolyConnectivity::split(FaceHandle fh, VertexHandle vh)
1009 {
1010 HalfedgeHandle hend = halfedge_handle(fh);
1011 HalfedgeHandle hh = next_halfedge_handle(hend);
1012
1013 HalfedgeHandle hold = new_edge(to_vertex_handle(hend), vh);
1014
1015 set_next_halfedge_handle(hend, hold);
1016 set_face_handle(hold, fh);
1017
1018 hold = opposite_halfedge_handle(hold);
1019
1020 while (hh != hend) {
1021
1022 HalfedgeHandle hnext = next_halfedge_handle(hh);
1023
1024 FaceHandle fnew = new_face();
1025 set_halfedge_handle(fnew, hh);
1026
1027 HalfedgeHandle hnew = new_edge(to_vertex_handle(hh), vh);
1028
1029 set_next_halfedge_handle(hnew, hold);
1030 set_next_halfedge_handle(hold, hh);
1031 set_next_halfedge_handle(hh, hnew);
1032
1033 set_face_handle(hnew, fnew);
1034 set_face_handle(hold, fnew);
1035 set_face_handle(hh, fnew);
1036
1037 hold = opposite_halfedge_handle(hnew);
1038
1039 hh = hnext;
1040 }
1041
1042 set_next_halfedge_handle(hold, hend);
1043 set_next_halfedge_handle(next_halfedge_handle(hend), hold);
1044
1045 set_face_handle(hold, fh);
1046
1047 set_halfedge_handle(vh, hold);
1048 }
1049
1050
1051 void PolyConnectivity::split_copy(FaceHandle fh, VertexHandle vh) {
1052
1053 // Split the given face (fh will still be valid)
1054 split(fh, vh);
1055
1056 // Copy the property of the original face to all new faces
1057 for(VertexFaceIter vf_it = vf_iter(vh); vf_it.is_valid(); ++vf_it)
1058 copy_all_properties(fh, *vf_it, true);
1059 }
1060
1061 //-----------------------------------------------------------------------------
1062 uint PolyConnectivity::valence(VertexHandle _vh) const
1063 {
1064 uint count(0);
1065 for (ConstVertexVertexIter vv_it=cvv_iter(_vh); vv_it.is_valid(); ++vv_it)
1066 ++count;
1067 return count;
1068 }
1069
1070 //-----------------------------------------------------------------------------
1071 uint PolyConnectivity::valence(FaceHandle _fh) const
1072 {
1073 uint count(0);
1074 for (ConstFaceVertexIter fv_it=cfv_iter(_fh); fv_it.is_valid(); ++fv_it)
1075 ++count;
1076 return count;
1077 }
1078
1079 //-----------------------------------------------------------------------------
1080 void PolyConnectivity::split_edge(EdgeHandle _eh, VertexHandle _vh)
1081 {
1082 HalfedgeHandle h0 = halfedge_handle(_eh, 0);
1083 HalfedgeHandle h1 = halfedge_handle(_eh, 1);
1084
1085 VertexHandle vfrom = from_vertex_handle(h0);
1086
1087 HalfedgeHandle ph0 = prev_halfedge_handle(h0);
1088 //HalfedgeHandle ph1 = prev_halfedge_handle(h1);
1089
1090 //HalfedgeHandle nh0 = next_halfedge_handle(h0);
1091 HalfedgeHandle nh1 = next_halfedge_handle(h1);
1092
1093 bool boundary0 = is_boundary(h0);
1094 bool boundary1 = is_boundary(h1);
1095
1096 //add the new edge
1097 HalfedgeHandle new_e = new_edge(from_vertex_handle(h0), _vh);
1098
1099 //fix the vertex of the opposite halfedge
1100 set_vertex_handle(h1, _vh);
1101
1102 //fix the halfedge connectivity
1103 set_next_halfedge_handle(new_e, h0);
1104 set_next_halfedge_handle(h1, opposite_halfedge_handle(new_e));
1105
1106 set_next_halfedge_handle(ph0, new_e);
1107 set_next_halfedge_handle(opposite_halfedge_handle(new_e), nh1);
1108
1109 // set_prev_halfedge_handle(new_e, ph0);
1110 // set_prev_halfedge_handle(opposite_halfedge_handle(new_e), h1);
1111
1112 // set_prev_halfedge_handle(nh1, opposite_halfedge_handle(new_e));
1113 // set_prev_halfedge_handle(h0, new_e);
1114
1115 if (!boundary0)
1116 {
1117 set_face_handle(new_e, face_handle(h0));
1118 }
1119 else
1120 {
1121 set_boundary(new_e);
1122 }
1123
1124 if (!boundary1)
1125 {
1126 set_face_handle(opposite_halfedge_handle(new_e), face_handle(h1));
1127 }
1128 else
1129 {
1130 set_boundary(opposite_halfedge_handle(new_e));
1131 }
1132
1133 set_halfedge_handle( _vh, h0 );
1134 adjust_outgoing_halfedge( _vh );
1135
1136 if (halfedge_handle(vfrom) == h0)
1137 {
1138 set_halfedge_handle(vfrom, new_e);
1139 adjust_outgoing_halfedge( vfrom );
1140 }
1141 }
1142
1143 //-----------------------------------------------------------------------------
1144
1145 void PolyConnectivity::split_edge_copy(EdgeHandle _eh, VertexHandle _vh)
1146 {
1147 // Split the edge (handle is kept!)
1148 split_edge(_eh, _vh);
1149
1150 // Navigate to the new edge
1151 EdgeHandle eh0 = edge_handle( next_halfedge_handle( halfedge_handle(_eh, 1) ) );
1152
1153 // Copy the property from the original to the new edge
1154 copy_all_properties(_eh, eh0, true);
1155 }
1156
1157 } // namespace OpenMesh
1158
OpenMesh::EdgeHandle
Handle for a edge entity.
Definition: Handles.hh:134
OpenMesh::FaceHandle
Handle for a face entity.
Definition: Handles.hh:141
OpenMesh::Attributes::StatusInfo::tagged
bool tagged() const
is tagged ?
Definition: Status.hh:133
OpenMesh::PolyConnectivity::is_manifold
bool is_manifold(VertexHandle _vh) const
Is (the mesh at) vertex _vh two-manifold ?
Definition: PolyConnectivity.cc:85
OpenMesh::PolyConnectivity::split_copy
void split_copy(FaceHandle _fh, VertexHandle _vh)
Face split (= 1-to-n split).
Definition: PolyConnectivity.cc:1051
OpenMesh::Attributes::StatusInfo::set_tagged
void set_tagged(bool _b)
set tagged
Definition: Status.hh:135
OpenMesh::PolyConnectivity::collapse
void collapse(HalfedgeHandle _heh)
Definition: PolyConnectivity.cc:636
OpenMesh::PolyConnectivity::adjust_outgoing_halfedge
void adjust_outgoing_halfedge(VertexHandle _vh)
Definition: PolyConnectivity.cc:102
OpenMesh::PolyConnectivity::delete_vertex
void delete_vertex(VertexHandle _vh, bool _delete_isolated_vertices=true)
Definition: PolyConnectivity.cc:474
OpenMesh::HalfedgeHandle
Handle for a halfedge entity.
Definition: Handles.hh:127
OpenMesh::PolyConnectivity::split_edge
void split_edge(EdgeHandle _eh, VertexHandle _vh)
Definition: PolyConnectivity.cc:1080
OpenMesh::PolyConnectivity::remove_edge
FaceHandle remove_edge(EdgeHandle _eh)
Definition: PolyConnectivity.cc:798
OpenMesh::PolyConnectivity::vv_iter
VertexVertexIter vv_iter(VertexHandle _vh)
vertex - vertex circulator
Definition: PolyConnectivity_inline_impl.hh:242
OpenMesh::PolyConnectivity::faces_begin
FaceIter faces_begin()
Begin iterator for faces.
Definition: PolyConnectivity_inline_impl.hh:205
OpenMesh::PolyConnectivity::fh_iter
FaceHalfedgeIter fh_iter(FaceHandle _fh)
face - halfedge circulator
Definition: PolyConnectivity_inline_impl.hh:341
OpenMesh::PolyConnectivity::cvoh_iter
ConstVertexOHalfedgeIter cvoh_iter(VertexHandle _vh) const
const vertex - outgoing halfedge circulator
Definition: PolyConnectivity_inline_impl.hh:305
OpenMesh::PolyConnectivity::vf_iter
VertexFaceIter vf_iter(VertexHandle _vh)
vertex - face circulator
Definition: PolyConnectivity_inline_impl.hh:278
OpenMesh::PolyConnectivity::collapse_loop
void collapse_loop(HalfedgeHandle _hh)
Helper for halfedge collapse.
Definition: PolyConnectivity.cc:703
OpenMesh::PolyConnectivity::faces_end
FaceIter faces_end()
End iterator for faces.
Definition: PolyConnectivity_inline_impl.hh:211
OpenMesh::PolyConnectivity::vih_iter
VertexIHalfedgeIter vih_iter(VertexHandle _vh)
vertex - incoming halfedge circulator
Definition: PolyConnectivity_inline_impl.hh:251
OpenMesh::PolyConnectivity::is_simple_link
bool is_simple_link(EdgeHandle _eh) const
Definition: PolyConnectivity.cc:758
OpenMesh::VertexHandle
Handle for a vertex entity.
Definition: Handles.hh:120
OpenMesh::PolyConnectivity::cvv_iter
ConstVertexVertexIter cvv_iter(VertexHandle _vh) const
const vertex circulator
Definition: PolyConnectivity_inline_impl.hh:287
OpenMesh::ArrayKernel::status
const StatusInfo & status(VertexHandle _vh) const
Status Query API.
Definition: ArrayKernel.hh:501
OpenMesh::BaseHandle::is_valid
bool is_valid() const
The handle is valid iff the index is not negative.
Definition: Handles.hh:72
OpenMesh::PolyConnectivity::split
void split(FaceHandle _fh, VertexHandle _vh)
Face split (= 1-to-n split).
Definition: PolyConnectivity.cc:1008
OpenMesh::PolyConnectivity::delete_edge
void delete_edge(EdgeHandle _eh, bool _delete_isolated_vertices=true)
Definition: PolyConnectivity.cc:495
OpenMesh::PolyConnectivity::insert_edge
HalfedgeHandle insert_edge(HalfedgeHandle _prev_heh, HalfedgeHandle _next_heh)
Definition: PolyConnectivity.cc:911
OpenMesh
Definition: MeshItems.hh:59
OpenMesh::make_smart
SmartVertexHandle make_smart(VertexHandle _vh, const PolyConnectivity *_mesh)
Creats a SmartVertexHandle from a VertexHandle and a Mesh.
Definition: SmartHandles.hh:186
OpenMesh::PolyConnectivity::delete_face
void delete_face(FaceHandle _fh, bool _delete_isolated_vertices=true)
Definition: PolyConnectivity.cc:522
OpenMesh::PolyConnectivity::reinsert_edge
void reinsert_edge(EdgeHandle _eh)
Definition: PolyConnectivity.cc:859
OpenMesh::PolyConnectivity::cff_iter
ConstFaceFaceIter cff_iter(FaceHandle _fh) const
const face - face circulator
Definition: PolyConnectivity_inline_impl.hh:395
OpenMesh::Attributes::StatusInfo::set_deleted
void set_deleted(bool _b)
set deleted
Definition: Status.hh:105
OpenMesh::Iterators::GenericIteratorT
Definition: IteratorsT.hh:83
OpenMesh::PolyConnectivity::is_boundary
bool is_boundary(HalfedgeHandle _heh) const
Check if the halfedge is at the boundary.
Definition: PolyConnectivity.hh:1300
OpenMesh::PolyConnectivity::triangulate
void triangulate()
triangulate the entire mesh
Definition: PolyConnectivity.cc:996
OpenMesh::Iterators::GenericCirculatorT_DEPRECATED
Definition: CirculatorsT.hh:428
OpenMesh::PolyConnectivity::is_collapse_ok
bool is_collapse_ok(HalfedgeHandle _he)
Definition: PolyConnectivity.cc:334
OpenMesh::PolyConnectivity::fh_end
FaceHalfedgeIter fh_end(FaceHandle _fh)
face - halfedge circulator
Definition: PolyConnectivity_inline_impl.hh:691
OpenMesh::PolyConnectivity::InvalidVertexHandle
static const VertexHandle InvalidVertexHandle
Invalid handle.
Definition: PolyConnectivity.hh:118
OpenMesh::PolyConnectivity::collapse_edge
void collapse_edge(HalfedgeHandle _hh)
Helper for halfedge collapse.
Definition: PolyConnectivity.cc:654
OpenMesh::PolyConnectivity::find_halfedge
HalfedgeHandle find_halfedge(VertexHandle _start_vh, VertexHandle _end_vh) const
Find halfedge from _vh0 to _vh1. Returns invalid handle if not found.
Definition: PolyConnectivity.cc:58
OpenMesh::PolyConnectivity::valence
uint valence(VertexHandle _vh) const
Vertex valence.
Definition: PolyConnectivity.cc:1062
OpenMesh::PolyConnectivity::split_edge_copy
void split_edge_copy(EdgeHandle _eh, VertexHandle _vh)
Definition: PolyConnectivity.cc:1145
OpenMesh::SmartFaceHandle
Definition: SmartHandles.hh:162
OpenMesh::PolyConnectivity::add_face
SmartFaceHandle add_face(const std::vector< VertexHandle > &_vhandles)
Add and connect a new face.
Definition: PolyConnectivity.cc:321
OpenMesh::PolyConnectivity::InvalidHalfedgeHandle
static const HalfedgeHandle InvalidHalfedgeHandle
Invalid handle.
Definition: PolyConnectivity.hh:120
OpenMesh::PolyConnectivity::InvalidEdgeHandle
static const EdgeHandle InvalidEdgeHandle
Invalid handle.
Definition: PolyConnectivity.hh:122
OpenMesh::Attributes::StatusInfo::deleted
bool deleted() const
is deleted ?
Definition: Status.hh:103
OpenMesh::BaseKernel::copy_all_properties
void copy_all_properties(VertexHandle _vh_from, VertexHandle _vh_to, bool _copyBuildIn=false)
Definition: BaseKernel.hh:511
OpenMesh::PolyConnectivity::InvalidFaceHandle
static const FaceHandle InvalidFaceHandle
Invalid handle.
Definition: PolyConnectivity.hh:124
OpenMesh::PolyConnectivity::cfe_iter
ConstFaceEdgeIter cfe_iter(FaceHandle _fh) const
const face - edge circulator
Definition: PolyConnectivity_inline_impl.hh:386
OpenMesh::PolyConnectivity::cfv_iter
ConstFaceVertexIter cfv_iter(FaceHandle _fh) const
const face - vertex circulator
Definition: PolyConnectivity_inline_impl.hh:368
OpenMesh::PolyConnectivity::is_simply_connected
bool is_simply_connected(FaceHandle _fh) const
Definition: PolyConnectivity.cc:779
OpenMesh::PolyConnectivity::opposite_face_handle
FaceHandle opposite_face_handle(HalfedgeHandle _heh) const
returns the face handle of the opposite halfedge
Definition: PolyConnectivity.hh:1362