00001 #ifndef OPENTISSUE_CORE_CONTAINERS_MESH_POLYMESH_POLYMESH_MESH_H
00002 #define OPENTISSUE_CORE_CONTAINERS_MESH_POLYMESH_POLYMESH_MESH_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <OpenTissue/core/containers/mesh/polymesh/polymesh_vertex.h>
00013 #include <OpenTissue/core/containers/mesh/polymesh/polymesh_halfedge.h>
00014 #include <OpenTissue/core/containers/mesh/polymesh/polymesh_edge.h>
00015 #include <OpenTissue/core/containers/mesh/polymesh/polymesh_face.h>
00016 #include <OpenTissue/core/containers/mesh/polymesh/polymesh_core_access.h>
00017
00018 #include <OpenTissue/core/containers/mesh/polymesh/circulators/polymesh_circulators.h>
00019 #include <OpenTissue/core/containers/mesh/polymesh/util/polymesh_is_boundary.h>
00020 #include <OpenTissue/core/containers/mesh/polymesh/util/polymesh_valency.h>
00021
00022 #include <vector>
00023 #include <algorithm>
00024
00025 namespace OpenTissue
00026 {
00027 namespace polymesh
00028 {
00029 namespace detail
00030 {
00031
00041 template<
00042 typename M
00043 , typename V
00044 , typename H
00045 , typename E
00046 , typename F
00047 , template <typename, typename, typename,typename> class K
00048 >
00049 class PMesh : public K<
00050 PolyMeshVertex< PMesh<M,V,H,E,F,K> >
00051 , PolyMeshHalfEdge< PMesh<M,V,H,E,F,K> >
00052 , PolyMeshEdge< PMesh<M,V,H,E,F,K> >
00053 , PolyMeshFace< PMesh<M,V,H,E,F,K> >
00054 >
00055 {
00056 public:
00057
00058 typedef M math_types;
00059 typedef V vertex_traits;
00060 typedef H halfedge_traits;
00061 typedef E edge_traits;
00062 typedef F face_traits;
00063 typedef PMesh<M,V,H,E,F,K> mesh_type;
00064 typedef PolyMeshVertex<mesh_type> vertex_type;
00065 typedef PolyMeshHalfEdge<mesh_type> halfedge_type;
00066 typedef PolyMeshEdge<mesh_type> edge_type;
00067 typedef PolyMeshFace<mesh_type> face_type;
00068
00069 typedef K<vertex_type, halfedge_type, edge_type, face_type > kernel_type;
00070
00071 typedef typename kernel_type::vertex_handle vertex_handle;
00072 typedef typename kernel_type::halfedge_handle halfedge_handle;
00073 typedef typename kernel_type::edge_handle edge_handle;
00074 typedef typename kernel_type::face_handle face_handle;
00075
00076 typedef typename kernel_type::vertex_iterator vertex_iterator;
00077 typedef typename kernel_type::halfedge_iterator halfedge_iterator;
00078 typedef typename kernel_type::edge_iterator edge_iterator;
00079 typedef typename kernel_type::face_iterator face_iterator;
00080
00081 typedef typename kernel_type::opt_vertex_iter opt_vertex_iter;
00082 typedef typename kernel_type::opt_halfedge_iter opt_halfedge_iter;
00083
00084 typedef typename kernel_type::const_vertex_iterator const_vertex_iterator;
00085 typedef typename kernel_type::const_halfedge_iterator const_halfedge_iterator;
00086 typedef typename kernel_type::const_edge_iterator const_edge_iterator;
00087 typedef typename kernel_type::const_face_iterator const_face_iterator;
00088
00089 public:
00090
00091 typedef PolyMeshVertexVertexCirculator<PMesh,vertex_type> vertex_vertex_circulator;
00092 typedef PolyMeshVertexHalfedgeCirculator<PMesh,halfedge_type> vertex_halfedge_circulator;
00093 typedef PolyMeshVertexEdgeCirculator<PMesh,edge_type> vertex_edge_circulator;
00094 typedef PolyMeshVertexFaceCirculator<PMesh,face_type> vertex_face_circulator;
00095
00096 typedef PolyMeshVertexVertexCirculator<PMesh,vertex_type const> const_vertex_vertex_circulator;
00097 typedef PolyMeshVertexHalfedgeCirculator<PMesh,halfedge_type const> const_vertex_halfedge_circulator;
00098 typedef PolyMeshVertexEdgeCirculator<PMesh,edge_type const> const_vertex_edge_circulator;
00099 typedef PolyMeshVertexFaceCirculator<PMesh,face_type const> const_vertex_face_circulator;
00100
00101 typedef PolyMeshFaceVertexCirculator<PMesh,vertex_type> face_vertex_circulator;
00102 typedef PolyMeshFaceHalfedgeCirculator<PMesh,halfedge_type> face_halfedge_circulator;
00103 typedef PolyMeshFaceEdgeCirculator<PMesh,edge_type> face_edge_circulator;
00104 typedef PolyMeshFaceFaceCirculator<PMesh,face_type> face_face_circulator;
00105
00106 typedef PolyMeshFaceVertexCirculator<PMesh,vertex_type const> const_face_vertex_circulator;
00107 typedef PolyMeshFaceHalfedgeCirculator<PMesh,halfedge_type const> const_face_halfedge_circulator;
00108 typedef PolyMeshFaceEdgeCirculator<PMesh,edge_type const> const_face_edge_circulator;
00109 typedef PolyMeshFaceFaceCirculator<PMesh,face_type const> const_face_face_circulator;
00110
00111 private:
00112
00113 struct assign_owner
00114 {
00115 assign_owner(mesh_type * new_owner)
00116 : m_new_owner(new_owner)
00117 {}
00118
00119 template <typename feature_type>
00120 void operator() (feature_type & f)
00121 {
00122 polymesh_core_access::set_owner( (&f), m_new_owner);
00123 }
00124
00125 mesh_type * m_new_owner;
00126 };
00127
00128 public:
00129
00130 PMesh(){}
00131
00132 ~PMesh() { this->clear(); }
00133
00134 explicit PMesh(PMesh const & m) { (*this) = m; }
00135
00136 PMesh & operator=(PMesh const & mesh)
00137 {
00138 if ( this == &mesh ) return *this;
00139
00140 kernel_type::operator=(mesh);
00141
00142
00143 std::for_each( this->vertex_begin(), this->vertex_end(), assign_owner(this) );
00144 std::for_each( this->halfedge_begin(), this->halfedge_end(), assign_owner(this) );
00145 std::for_each( this->edge_begin(), this->edge_end(), assign_owner(this) );
00146 std::for_each( this->face_begin(), this->face_end(), assign_owner(this) );
00147
00148 return *this;
00149 }
00150
00151 public:
00152
00153 halfedge_iterator find_halfedge_iterator(vertex_iterator A, vertex_iterator B)
00154 {
00155 vertex_halfedge_circulator circulator( *A );
00156 vertex_halfedge_circulator end;
00157 for(;circulator!=end;++circulator)
00158 {
00159 if(circulator->get_destination_handle()==B->get_handle())
00160 return get_halfedge_iterator(circulator->get_handle());
00161 }
00162 return this->halfedge_end();
00163 }
00164
00165 halfedge_handle find_halfedge_handle(vertex_handle A, vertex_handle B)
00166 {
00167 if(!is_valid_vertex_handle(A))
00168 return this->null_halfedge_handle();
00169 if(!is_valid_vertex_handle(B))
00170 return this->null_halfedge_handle();
00171 vertex_iterator Ait = get_vertex_iterator(A);
00172 vertex_halfedge_circulator circulator( *Ait );
00173 vertex_halfedge_circulator end;
00174 for(;circulator!=end;++circulator)
00175 {
00176 if(circulator->get_destination_handle()==B)
00177 return circulator->get_handle();
00178 }
00179 return this->null_halfedge_handle();
00180 }
00181
00182 edge_handle find_edge_handle(vertex_handle A, vertex_handle B)
00183 {
00184 halfedge_handle h = find_halfedge_handle(A,B);
00185 if(h.is_null())
00186 return this->null_edge_handle();
00187 return get_halfedge_iterator(h)->get_edge_handle();
00188 }
00189
00190 private:
00191
00200 halfedge_iterator add_halfedge(vertex_iterator A,vertex_iterator B)
00201 {
00202 halfedge_iterator lookup = find_halfedge_iterator(A,B);
00203 if(lookup != this->halfedge_end() )
00204 return lookup;
00205
00206 halfedge_handle h = this->create_halfedge();
00207 halfedge_handle t = this->create_halfedge();
00208 edge_handle e = this->create_edge();
00209
00210 halfedge_iterator hit = get_halfedge_iterator(h);
00211 halfedge_iterator tit = get_halfedge_iterator(t);
00212 edge_iterator eit = get_edge_iterator(e);
00213
00214 polymesh_core_access::set_owner(hit,this);
00215 polymesh_core_access::set_next_handle(hit,this->null_halfedge_handle());
00216 polymesh_core_access::set_face_handle(hit,this->null_face_handle());
00217 polymesh_core_access::set_twin_handle(hit,t);
00218 polymesh_core_access::set_destination_handle(hit,B->get_handle());
00219 polymesh_core_access::set_edge_handle(hit,e);
00220
00221 polymesh_core_access::set_owner(tit,this);
00222 polymesh_core_access::set_next_handle(tit,this->null_halfedge_handle());
00223 polymesh_core_access::set_face_handle(tit,this->null_face_handle());
00224 polymesh_core_access::set_twin_handle(tit,h);
00225 polymesh_core_access::set_destination_handle(tit,A->get_handle());
00226 polymesh_core_access::set_edge_handle(tit,e);
00227
00228 polymesh_core_access::set_owner(eit,this);
00229 polymesh_core_access::set_halfedge0_handle(eit,h);
00230 polymesh_core_access::set_halfedge1_handle(eit,t);
00231
00232 return hit;
00233 }
00234
00235 public:
00236
00237 vertex_handle add_vertex()
00238 {
00239 vertex_handle v = this->create_vertex();
00240 vertex_iterator vit = get_vertex_iterator(v);
00241 polymesh_core_access::set_owner(vit,this);
00242 return v;
00243 }
00244
00245 template<typename vector3_type>
00246 vertex_handle add_vertex(vector3_type const & coord)
00247 {
00248 vertex_handle v = add_vertex();
00249 get_vertex_iterator(v)->m_coord = coord;
00250 return v;
00251 }
00252
00253 template<typename vertex_handle_iterator>
00254 face_handle add_face(vertex_handle_iterator begin,vertex_handle_iterator end)
00255 {
00256 if(begin==end)
00257 {
00258 assert(!"PMesh::insert_face(...): Could not create face, first and last vertex were the same.");
00259 return this->null_face_handle();
00260 }
00261
00262 std::size_t n = std::distance(begin,end);
00263 if(n<3)
00264 {
00265 assert(!"PMesh::insert_face(...): Could not create face, not enough vertices.");
00266 return this->null_face_handle();
00267 }
00268
00269
00270
00271
00272
00273 std::vector<opt_vertex_iter> V(n);
00274 std::size_t i=0,j=1;
00275
00276 for(vertex_handle_iterator vhit = begin;vhit!=end;++vhit)
00277 {
00278 vertex_handle v = *vhit;
00279 if(!is_valid_vertex_handle(v))
00280 {
00281 assert(!"PMesh::insert_face(...): Could not create face, invalid vertex handle encountered.");
00282 return this->null_face_handle();
00283 }
00284 vertex_iterator vit = get_vertex_iterator( *vhit );
00285 if(!is_boundary( *vit ))
00286 {
00287 assert(!"PMesh::insert_face(...): Could not create face, 2 manifold vertex encountered.");
00288 return this->null_face_handle();
00289 }
00290 V[i++] = vit;
00291 }
00292
00293
00294
00295
00296 std::vector<opt_halfedge_iter> E(n);
00297 std::vector<bool> is_new(n);
00298
00299 for (i=0, j=1; i<n; ++i, ++j, j%=n)
00300 {
00301
00302
00303
00304 vertex_iterator vi = V[i].get();
00305 vertex_iterator vj = V[j].get();
00306 halfedge_handle h = find_halfedge_handle(vi->get_handle(),vj->get_handle());
00307 if(h.is_null())
00308 {
00309
00310 is_new[i] = true;
00311 }
00312 else
00313 {
00314
00315 is_new[i] = false;
00316 halfedge_iterator hit = kernel_type::get_halfedge_iterator(h);
00317
00318 if(!is_boundary( *hit ))
00319 {
00320 assert(!"PMesh::insert_face(...): Could not create face, encountered halfedge belonging to another face.");
00321 return this->null_face_handle();
00322 }
00323 E[i] = hit;
00324 }
00325 }
00326
00327
00328 for (i=0, j=1; i<n; ++i, ++j, j%=n)
00329 {
00330 if ( (!is_new[i]) && (!is_new[j]) )
00331 {
00332
00333 halfedge_iterator inner_prev = E[i].get();
00334 halfedge_iterator inner_next = E[j].get();
00335 if ( inner_prev->get_next_handle() != inner_next->get_handle() )
00336 {
00337
00338
00339 halfedge_iterator outer_prev = inner_next->get_twin_iterator();
00340 halfedge_iterator outer_next = inner_prev->get_twin_iterator();
00341 halfedge_iterator boundary_prev = outer_prev;
00342 do
00343 {
00344 boundary_prev = boundary_prev->get_next_iterator()->get_twin_iterator( ) ;
00345 } while (!is_boundary( *boundary_prev ) || boundary_prev==inner_prev);
00346 if(!is_boundary( *boundary_prev ))
00347 {
00348 assert(!"PMesh::add_face(...): Could not create face, vertex neighborhood flawed.");
00349 return this->null_face_handle();
00350 }
00351 if (boundary_prev == inner_prev)
00352 {
00353 assert(!"PMesh::add_face(...): Could not create face, vertex neighborhood flawed.");
00354 return this->null_face_handle();
00355 }
00356 halfedge_iterator boundary_next = boundary_prev->get_next_iterator();
00357 if(!is_boundary( *boundary_next ))
00358 {
00359 assert(!"PMesh::add_face(...): Could not create face, vertex neighborhood flawed.");
00360 return this->null_face_handle();
00361 }
00362 if (boundary_next == inner_next)
00363 {
00364 assert(!"PMesh::add_face(...): Could not create face, vertex neighborhood flawed.");
00365 return this->null_face_handle();
00366 }
00367
00368 halfedge_iterator patch_start = inner_prev->get_next_iterator();
00369 halfedge_iterator patch_end = inner_next->get_prev_iterator();
00370
00371 polymesh_core_access::set_next_handle( boundary_prev, patch_start->get_handle() );
00372 polymesh_core_access::set_next_handle( patch_end, boundary_next->get_handle());
00373 polymesh_core_access::set_next_handle( inner_prev, inner_next->get_handle() );
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385 }
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399 }
00400 }
00401
00402
00403 for (i=0, j=1; i<n; ++i, ++j, j%=n)
00404 {
00405 if (is_new[i])
00406 {
00407
00408 E[i] = add_halfedge(V[i].get(),V[j].get());
00409 }
00410 }
00411
00412
00413 face_handle f = this->create_face();
00414 face_iterator fit = get_face_iterator(f);
00415 polymesh_core_access::set_owner(fit,this);
00416
00417
00418 halfedge_iterator enm1 = E[n-1].get();
00419 polymesh_core_access::set_border_halfedge_handle(fit,enm1->get_handle());
00420
00421
00422 std::vector<bool> needs_adjust(n, false);
00423
00424 for (i=0, j=1; i<n; ++i, ++j, j%=n)
00425 {
00426
00427 vertex_iterator v = V[j].get();
00428 halfedge_iterator inner_prev = E[i].get();
00429 halfedge_iterator inner_next = E[j].get();
00430
00431 int id = 0;
00432 if (is_new[i])
00433 id |= 1;
00434 if (is_new[j])
00435 id |= 2;
00436 if (id)
00437 {
00438 halfedge_iterator outer_prev = inner_next->get_twin_iterator();
00439 halfedge_iterator outer_next = inner_prev->get_twin_iterator();
00440
00441 switch (id)
00442 {
00443 case 1:
00444 {
00445
00446 halfedge_iterator boundary_prev = inner_next->get_prev_iterator();
00447 polymesh_core_access::set_next_handle(boundary_prev, outer_next->get_handle());
00448 polymesh_core_access::set_outgoing_halfedge_handle(v, outer_next->get_handle());
00449
00450 }
00451 break;
00452 case 2:
00453 {
00454
00455 halfedge_iterator boundary_next = inner_prev->get_next_iterator();
00456 polymesh_core_access::set_next_handle(outer_prev, boundary_next->get_handle());
00457 polymesh_core_access::set_outgoing_halfedge_handle(v, boundary_next->get_handle());
00458 }
00459 break;
00460 case 3:
00461 {
00462
00463 if (v->get_outgoing_halfedge_handle().is_null())
00464 {
00465 polymesh_core_access::set_outgoing_halfedge_handle(v, outer_next->get_handle());
00466 polymesh_core_access::set_next_handle(outer_prev, outer_next->get_handle());
00467 }
00468 else
00469 {
00470
00471 halfedge_iterator boundary_next = v->get_outgoing_halfedge_iterator();
00472 if(!boundary_next->get_face_handle().is_null())
00473 {
00474 assert(!"PMesh::add_face(...): Outgoing halfedge from vertex was not pointing to empty gap");
00475 return this->null_face_handle();
00476 }
00477 halfedge_iterator boundary_prev = boundary_next->get_prev_iterator();
00478 polymesh_core_access::set_next_handle(boundary_prev, outer_next->get_handle());
00479 polymesh_core_access::set_next_handle(outer_prev, boundary_next->get_handle());
00480 }
00481 }
00482 break;
00483 }
00484
00485 polymesh_core_access::set_next_handle( inner_prev, inner_next->get_handle() );
00486 }
00487 else
00488 {
00489 needs_adjust[j] = (v->get_outgoing_halfedge_handle() == inner_next->get_handle());
00490 }
00491
00492
00493 polymesh_core_access::set_face_handle(E[i].get(),f);
00494 }
00495
00496 for (i=0; i<n; ++i)
00497 if (needs_adjust[i])
00498
00499 polymesh_core_access::adjust_outgoing_halfedge_handle(V[i].get());
00500
00501 return f;
00502 }
00503
00504 face_handle add_face(vertex_handle const & v0,vertex_handle const & v1,vertex_handle const & v2)
00505 {
00506 vertex_handle handles[3];
00507 handles[0] = v0;
00508 handles[1] = v1;
00509 handles[2] = v2;
00510 return add_face(handles,handles+3);
00511 }
00512
00513 bool remove_vertex(vertex_handle const & v)
00514 {
00515
00516 if(!is_valid_vertex_handle(v))
00517 {
00518 assert(!"PMesh::remove_vertex(...): Invalid vertex handle");
00519 return false;
00520 }
00521 return remove_vertex( get_vertex_iterator(v) );
00522 }
00523
00524 bool remove_vertex(vertex_iterator v)
00525 {
00526
00527 halfedge_handle h = v->get_outgoing_halfedge_handle();
00528 if(!h.is_null())
00529 {
00530 assert(!"PMesh::remove_vertex(...): Could not remove vertex because it is bound to an edge");
00531 return false;
00532 }
00533
00534 erase_vertex(v->get_handle());
00535 return true;
00536 }
00537
00538 bool remove_edge(edge_handle const & e)
00539 {
00540
00541 if(!is_valid_edge_handle(e))
00542 {
00543 assert(!"PMesh::remove_edge(...): Invalid edge handle");
00544 return false;
00545 }
00546 return remove_edge( get_edge_iterator(e) );
00547 }
00548
00549 bool remove_edge(edge_iterator e)
00550 {
00551 halfedge_handle h0 = e->get_halfedge0_handle();
00552 halfedge_handle h1 = e->get_halfedge1_handle();
00553 halfedge_iterator h0it = get_halfedge_iterator(h0);
00554 halfedge_iterator h1it = get_halfedge_iterator(h1);
00555
00556
00557 if(!h0it->get_face_handle().is_null())
00558 {
00559
00560 return false;
00561 }
00562 if(!h1it->get_face_handle().is_null())
00563 {
00564
00565 return false;
00566 }
00567
00568
00569 vertex_handle A = h0it->get_destination_handle();
00570 vertex_handle B = h1it->get_destination_handle();
00571
00572 if(!is_valid_vertex_handle(A))
00573 {
00574 assert(!"PMesh::remove_edge(...): Illegal edge topology, invalid vertex handle encountered");
00575 return false;
00576 }
00577 if(!is_valid_vertex_handle(B))
00578 {
00579 assert(!"PMesh::remove_edge(...): Illegal edge topology, invalid vertex handle encountered");
00580 return false;
00581 }
00582
00583 vertex_iterator Ait = get_vertex_iterator(A);
00584 vertex_iterator Bit = get_vertex_iterator(B);
00585
00586 {
00587
00588 halfedge_handle h1_prev = h1it->get_prev_handle();
00589 halfedge_handle h0_next = h0it->get_next_handle();
00590 if(!is_valid_halfedge_handle(h1_prev))
00591 {
00592 assert(!"PMesh::remove_edge(...): Illegal edge topology, mesh is in-consistent, could not remove edge");
00593 return false;
00594 }
00595 if(!is_valid_halfedge_handle(h0_next))
00596 {
00597 assert(!"PMesh::remove_edge(...): Illegal edge topology, mesh is in-consistent, could not remove edge");
00598 return false;
00599 }
00600
00601 halfedge_iterator h0_next_it = get_halfedge_iterator(h0_next);
00602 halfedge_iterator h1_prev_it = get_halfedge_iterator(h1_prev);
00603
00604 polymesh_core_access::set_next_handle(h1_prev_it,h0_next);
00605
00606
00607
00608 if(h1_prev==h0)
00609 {
00610 polymesh_core_access::set_outgoing_halfedge_handle(Ait,this->null_halfedge_handle());
00611 }
00612
00613
00614 else if(h1 == Ait->get_outgoing_halfedge_handle())
00615 {
00616 polymesh_core_access::set_outgoing_halfedge_handle(Ait,h0_next);
00617 }
00618
00619 polymesh_core_access::adjust_outgoing_halfedge_handle(Ait);
00620 }
00621
00622 {
00623
00624 halfedge_handle h1_next = h1it->get_next_handle();
00625 halfedge_handle h0_prev = h0it->get_prev_handle();
00626
00627 if(!is_valid_halfedge_handle(h1_next))
00628 {
00629 assert(!"PMesh::remove_edge(...): Illegal edge topology, mesh is in-consistent, could not remove edge");
00630 return false;
00631 }
00632 if(!is_valid_halfedge_handle(h0_prev))
00633 {
00634 assert(!"PMesh::remove_edge(...): Illegal edge topology, mesh is in-consistent, could not remove edge");
00635 return false;
00636 }
00637
00638 halfedge_iterator h1_next_it = get_halfedge_iterator(h1_next);
00639 halfedge_iterator h0_prev_it = get_halfedge_iterator(h0_prev);
00640
00641 polymesh_core_access::set_next_handle(h0_prev_it,h1_next);
00642
00643
00644 if(h0_prev==h1)
00645 {
00646 polymesh_core_access::set_outgoing_halfedge_handle(Bit,this->null_halfedge_handle());
00647 }
00648
00649
00650 else if(h0 == Bit->get_outgoing_halfedge_handle())
00651 {
00652 polymesh_core_access::set_outgoing_halfedge_handle(Bit,h1_next);
00653 }
00654
00655 polymesh_core_access::adjust_outgoing_halfedge_handle(Bit);
00656 }
00657
00658 {
00659 polymesh_core_access::set_next_handle(h0it,this->null_halfedge_handle());
00660 polymesh_core_access::set_twin_handle(h0it,this->null_halfedge_handle());
00661 polymesh_core_access::set_destination_handle(h0it,this->null_vertex_handle());
00662 polymesh_core_access::set_edge_handle(h0it,this->null_edge_handle());
00663
00664 polymesh_core_access::set_next_handle(h1it,this->null_halfedge_handle());
00665 polymesh_core_access::set_twin_handle(h1it,this->null_halfedge_handle());
00666 polymesh_core_access::set_destination_handle(h1it,this->null_vertex_handle());
00667 polymesh_core_access::set_edge_handle(h1it,this->null_edge_handle());
00668
00669 polymesh_core_access::set_halfedge0_handle(e,this->null_halfedge_handle());
00670 polymesh_core_access::set_halfedge1_handle(e,this->null_halfedge_handle());
00671 }
00672
00673 {
00674 erase_edge(e->get_handle());
00675 erase_halfedge(h0);
00676 erase_halfedge(h1);
00677 }
00678 return true;
00679 }
00680
00681 bool remove_face(face_handle const & f)
00682 {
00683
00684 if(!is_valid_face_handle(f))
00685 return false;
00686
00687 return remove_face( get_face_iterator(f) );
00688 }
00689
00690 bool remove_face(face_iterator f)
00691 {
00692
00693 std::vector<edge_iterator> tmp;
00694
00695 face_halfedge_circulator h( *f ), hend;
00696 for(;h!=hend;++h)
00697 {
00698 polymesh_core_access::set_face_handle(h,this->null_face_handle());
00699 tmp.push_back(h->get_edge_iterator());
00700 }
00701
00702 face_vertex_circulator v( *f ), vend;
00703 for(;v!=vend;++v)
00704 {
00705 vertex_iterator iter = get_vertex_iterator(v->get_handle());
00706 polymesh_core_access::adjust_outgoing_halfedge_handle( iter );
00707 }
00708
00709 for(typename std::vector<edge_iterator>::iterator e= tmp.begin();e!=tmp.end();++e)
00710 {
00711 remove_edge( (*e) );
00712 }
00713
00714
00715 polymesh_core_access::set_border_halfedge_handle(f,this->null_halfedge_handle());
00716
00717 erase_face(f->get_handle());
00718 return true;
00719 }
00720
00721 };
00722
00723 }
00724 }
00725 }
00726
00727
00728 #endif