Developer Documentation

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

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