OpenMesh
|
00001 /*===========================================================================*\ 00002 * * 00003 * OpenMesh * 00004 * Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen * 00005 * www.openmesh.org * 00006 * * 00007 *---------------------------------------------------------------------------* 00008 * This file is part of OpenMesh. * 00009 * * 00010 * OpenMesh is free software: you can redistribute it and/or modify * 00011 * it under the terms of the GNU Lesser General Public License as * 00012 * published by the Free Software Foundation, either version 3 of * 00013 * the License, or (at your option) any later version with the * 00014 * following exceptions: * 00015 * * 00016 * If other files instantiate templates or use macros * 00017 * or inline functions from this file, or you compile this file and * 00018 * link it with other files to produce an executable, this file does * 00019 * not by itself cause the resulting executable to be covered by the * 00020 * GNU Lesser General Public License. This exception does not however * 00021 * invalidate any other reasons why the executable file might be * 00022 * covered by the GNU Lesser General Public License. * 00023 * * 00024 * OpenMesh is distributed in the hope that it will be useful, * 00025 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00026 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00027 * GNU Lesser General Public License for more details. * 00028 * * 00029 * You should have received a copy of the GNU LesserGeneral Public * 00030 * License along with OpenMesh. If not, * 00031 * see <http://www.gnu.org/licenses/>. * 00032 * * 00033 \*==========================================================================*/ 00034 00035 /*==========================================================================*\ 00036 * * 00037 * $Revision: 410 $ * 00038 * $Date: 2010-06-17 12:45:58 +0200 (Do, 17. Jun 2010) $ * 00039 * * 00040 \*==========================================================================*/ 00041 00051 //============================================================================= 00052 // 00053 // CLASS InterpolatingSqrt3LGT 00054 // 00055 //============================================================================= 00056 00057 #ifndef OPENMESH_SUBDIVIDER_UNIFORM_INTERP_SQRT3T_LABSIK_GREINER_HH 00058 #define OPENMESH_SUBDIVIDER_UNIFORM_INTERP_SQRT3T_LABSIK_GREINER_HH 00059 00060 00061 //== INCLUDES ================================================================= 00062 00063 #include <OpenMesh/Core/Mesh/Handles.hh> 00064 #include <OpenMesh/Core/System/config.hh> 00065 #include <OpenMesh/Tools/Subdivider/Uniform/SubdividerT.hh> 00066 00067 #if defined(_DEBUG) || defined(DEBUG) 00068 // Makes life lot easier, when playing/messing around with low-level topology 00069 // changing methods of OpenMesh 00070 # include <OpenMesh/Tools/Utils/MeshCheckerT.hh> 00071 # define ASSERT_CONSISTENCY( T, m ) \ 00072 assert(OpenMesh::Utils::MeshCheckerT<T>(m).check()) 00073 #else 00074 # define ASSERT_CONSISTENCY( T, m ) 00075 #endif 00076 // -------------------- STL 00077 #include <vector> 00078 #if defined(OM_CC_MIPS) 00079 # include <math.h> 00080 #else 00081 # include <cmath> 00082 #endif 00083 00084 //#define MIRROR_TRIANGLES 00085 //#define MIN_NORM 00086 00087 //== NAMESPACE ================================================================ 00088 00089 namespace OpenMesh { // BEGIN_NS_OPENMESH 00090 namespace Subdivider { // BEGIN_NS_DECIMATER 00091 namespace Uniform { // BEGIN_NS_UNIFORM 00092 00093 00094 //== CLASS DEFINITION ========================================================= 00095 00096 00105 template <typename MeshType, typename RealType = float> 00106 class InterpolatingSqrt3LGT : public SubdividerT< MeshType, RealType > 00107 { 00108 public: 00109 00110 typedef RealType real_t; 00111 typedef MeshType mesh_t; 00112 typedef SubdividerT< mesh_t, real_t > parent_t; 00113 00114 typedef std::vector< std::vector<real_t> > weights_t; 00115 00116 public: 00117 00118 00119 InterpolatingSqrt3LGT(void) : parent_t() 00120 { init_weights(); } 00121 00122 InterpolatingSqrt3LGT(MeshType &_m) : parent_t(_m) 00123 { init_weights(); } 00124 00125 virtual ~InterpolatingSqrt3LGT() {} 00126 00127 00128 public: 00129 00130 00131 const char *name() const { return "Uniform Interpolating Sqrt3"; } 00132 00134 void init_weights(size_t _max_valence=50) 00135 { 00136 weights_.resize(_max_valence); 00137 00138 weights_[3].resize(4); 00139 weights_[3][0] = +4.0/27; 00140 weights_[3][1] = -5.0/27; 00141 weights_[3][2] = +4.0/27; 00142 weights_[3][3] = +8.0/9; 00143 00144 weights_[4].resize(5); 00145 weights_[4][0] = +2.0/9; 00146 weights_[4][1] = -1.0/9; 00147 weights_[4][2] = -1.0/9; 00148 weights_[4][3] = +2.0/9; 00149 weights_[4][4] = +7.0/9 ; 00150 00151 for(unsigned int K=5; K<_max_valence; ++K) 00152 { 00153 weights_[K].resize(K+1); 00154 double aH = 2.0*cos(M_PI/K)/3.0; 00155 weights_[K][K] = 1.0 - aH*aH; 00156 for(unsigned int i=0; i<K; ++i) 00157 { 00158 weights_[K][i] = (aH*aH + 2.0*aH*cos(2.0*i*M_PI/K + M_PI/K) + 2.0*aH*aH*cos(4.0*i*M_PI/K + 2.0*M_PI/K))/K; 00159 } 00160 } 00161 00162 //just to be sure: 00163 weights_[6].resize(0); 00164 00165 } 00166 00167 00168 protected: 00169 00170 00171 bool prepare( MeshType& _m ) 00172 { 00173 _m.request_edge_status(); 00174 _m.add_property( fp_pos_ ); 00175 _m.add_property( ep_nv_ ); 00176 _m.add_property( mp_gen_ ); 00177 _m.property( mp_gen_ ) = 0; 00178 00179 return _m.has_edge_status() 00180 && ep_nv_.is_valid() && mp_gen_.is_valid(); 00181 } 00182 00183 00184 bool cleanup( MeshType& _m ) 00185 { 00186 _m.release_edge_status(); 00187 _m.remove_property( fp_pos_ ); 00188 _m.remove_property( ep_nv_ ); 00189 _m.remove_property( mp_gen_ ); 00190 return true; 00191 } 00192 00193 00194 bool subdivide( MeshType& _m, size_t _n , const bool _update_points = true) 00195 { 00196 00198 00199 typename MeshType::VertexIter vit; 00200 typename MeshType::VertexVertexIter vvit; 00201 typename MeshType::EdgeIter eit; 00202 typename MeshType::FaceIter fit; 00203 typename MeshType::FaceVertexIter fvit; 00204 typename MeshType::FaceHalfedgeIter fheit; 00205 typename MeshType::VertexHandle vh; 00206 typename MeshType::HalfedgeHandle heh; 00207 typename MeshType::Point pos(0,0,0), zero(0,0,0); 00208 size_t &gen = _m.property( mp_gen_ ); 00209 00210 for (size_t l=0; l<_n; ++l) 00211 { 00212 // tag existing edges 00213 for (eit=_m.edges_begin(); eit != _m.edges_end();++eit) 00214 { 00215 _m.status( eit ).set_tagged( true ); 00216 if ( (gen%2) && _m.is_boundary(eit) ) 00217 compute_new_boundary_points( _m, eit ); // *) creates new vertices 00218 } 00219 00220 // insert new vertices, and store pos in vp_pos_ 00221 typename MeshType::FaceIter fend = _m.faces_end(); 00222 for (fit = _m.faces_begin();fit != fend; ++fit) 00223 { 00224 if (_m.is_boundary(fit)) 00225 { 00226 if(gen%2) 00227 _m.property(fp_pos_, fit.handle()).invalidate(); 00228 else 00229 { 00230 //find the interior boundary halfedge 00231 for( heh = _m.halfedge_handle(fit.handle()); !_m.is_boundary( _m.opposite_halfedge_handle(heh) ); heh = _m.next_halfedge_handle(heh) ) 00232 ; 00233 assert(_m.is_boundary( _m.opposite_halfedge_handle(heh) )); 00234 pos = zero; 00235 //check for two boundaries case: 00236 if( _m.is_boundary(_m.next_halfedge_handle(heh)) || _m.is_boundary(_m.prev_halfedge_handle(heh)) ) 00237 { 00238 if(_m.is_boundary(_m.prev_halfedge_handle(heh))) 00239 heh = _m.prev_halfedge_handle(heh); //ensure that the boundary halfedges are heh and heh->next 00240 //check for three boundaries case: 00241 if(_m.is_boundary(_m.next_halfedge_handle(_m.next_halfedge_handle(heh)))) 00242 { 00243 //three boundaries, use COG of triangle 00244 pos += real_t(1.0/3) * _m.point(_m.to_vertex_handle(heh)); 00245 pos += real_t(1.0/3) * _m.point(_m.to_vertex_handle(_m.next_halfedge_handle(heh))); 00246 pos += real_t(1.0/3) * _m.point(_m.to_vertex_handle(_m.prev_halfedge_handle(heh))); 00247 } 00248 else 00249 { 00250 #ifdef MIRROR_TRIANGLES 00251 //two boundaries, mirror two triangles 00252 pos += real_t(2.0/9) * _m.point(_m.to_vertex_handle(heh)); 00253 pos += real_t(4.0/9) * _m.point(_m.to_vertex_handle(_m.next_halfedge_handle(heh))); 00254 pos += real_t(4.0/9) * _m.point(_m.to_vertex_handle(_m.prev_halfedge_handle(heh))); 00255 pos += real_t(-1.0/9) * _m.point(_m.to_vertex_handle(_m.next_halfedge_handle(_m.opposite_halfedge_handle(_m.prev_halfedge_handle(heh))))); 00256 #else 00257 pos += real_t(7.0/24) * _m.point(_m.to_vertex_handle(heh)); 00258 pos += real_t(3.0/8) * _m.point(_m.to_vertex_handle(_m.next_halfedge_handle(heh))); 00259 pos += real_t(3.0/8) * _m.point(_m.to_vertex_handle(_m.prev_halfedge_handle(heh))); 00260 pos += real_t(-1.0/24) * _m.point(_m.to_vertex_handle(_m.next_halfedge_handle(_m.opposite_halfedge_handle(_m.prev_halfedge_handle(heh))))); 00261 #endif 00262 } 00263 } 00264 else 00265 { 00266 vh = _m.to_vertex_handle(_m.next_halfedge_handle(heh)); 00267 //check last vertex regularity 00268 if((_m.valence(vh) == 6) || _m.is_boundary(vh)) 00269 { 00270 #ifdef MIRROR_TRIANGLES 00271 //use regular rule and mirror one triangle 00272 pos += real_t(5.0/9) * _m.point(vh); 00273 pos += real_t(3.0/9) * _m.point(_m.to_vertex_handle(heh)); 00274 pos += real_t(3.0/9) * _m.point(_m.to_vertex_handle(_m.opposite_halfedge_handle(heh))); 00275 pos += real_t(-1.0/9) * _m.point(_m.to_vertex_handle(_m.next_halfedge_handle(_m.opposite_halfedge_handle(_m.next_halfedge_handle(heh))))); 00276 pos += real_t(-1.0/9) * _m.point(_m.to_vertex_handle(_m.next_halfedge_handle(_m.opposite_halfedge_handle(_m.prev_halfedge_handle(heh))))); 00277 #else 00278 #ifdef MIN_NORM 00279 pos += real_t(1.0/9) * _m.point(vh); 00280 pos += real_t(1.0/3) * _m.point(_m.to_vertex_handle(heh)); 00281 pos += real_t(1.0/3) * _m.point(_m.to_vertex_handle(_m.opposite_halfedge_handle(heh))); 00282 pos += real_t(1.0/9) * _m.point(_m.to_vertex_handle(_m.next_halfedge_handle(_m.opposite_halfedge_handle(_m.next_halfedge_handle(heh))))); 00283 pos += real_t(1.0/9) * _m.point(_m.to_vertex_handle(_m.next_halfedge_handle(_m.opposite_halfedge_handle(_m.prev_halfedge_handle(heh))))); 00284 #else 00285 pos += real_t(1.0/2) * _m.point(vh); 00286 pos += real_t(1.0/3) * _m.point(_m.to_vertex_handle(heh)); 00287 pos += real_t(1.0/3) * _m.point(_m.to_vertex_handle(_m.opposite_halfedge_handle(heh))); 00288 pos += real_t(-1.0/12) * _m.point(_m.to_vertex_handle(_m.next_halfedge_handle(_m.opposite_halfedge_handle(_m.next_halfedge_handle(heh))))); 00289 pos += real_t(-1.0/12) * _m.point(_m.to_vertex_handle(_m.next_halfedge_handle(_m.opposite_halfedge_handle(_m.prev_halfedge_handle(heh))))); 00290 #endif 00291 #endif 00292 } 00293 else 00294 { 00295 //irregular setting, use usual irregular rule 00296 unsigned int K = _m.valence(vh); 00297 pos += weights_[K][K]*_m.point(vh); 00298 heh = _m.opposite_halfedge_handle( _m.next_halfedge_handle(heh) ); 00299 for(unsigned int i = 0; i<K; ++i, heh = _m.opposite_halfedge_handle(_m.prev_halfedge_handle(heh)) ) 00300 { 00301 pos += weights_[K][i]*_m.point(_m.to_vertex_handle(heh)); 00302 } 00303 } 00304 } 00305 vh = _m.add_vertex( pos ); 00306 _m.property(fp_pos_, fit.handle()) = vh; 00307 } 00308 } 00309 else 00310 { 00311 pos = zero; 00312 int nOrdinary = 0; 00313 00314 //check number of extraordinary vertices 00315 for(fvit = _m.fv_iter( fit ); fvit; ++fvit) 00316 if( (_m.valence(fvit.handle())) == 6 || _m.is_boundary(fvit.handle()) ) 00317 ++nOrdinary; 00318 00319 if(nOrdinary==3) 00320 { 00321 for(fheit = _m.fh_iter( fit ); fheit; ++fheit) 00322 { 00323 //one ring vertex has weight 32/81 00324 heh = fheit.handle(); 00325 assert(_m.to_vertex_handle(heh).is_valid()); 00326 pos += real_t(32.0/81) * _m.point(_m.to_vertex_handle(heh)); 00327 //tip vertex has weight -1/81 00328 heh = _m.opposite_halfedge_handle(heh); 00329 assert(heh.is_valid()); 00330 assert(_m.next_halfedge_handle(heh).is_valid()); 00331 assert(_m.to_vertex_handle(_m.next_halfedge_handle(heh)).is_valid()); 00332 pos -= real_t(1.0/81) * _m.point(_m.to_vertex_handle(_m.next_halfedge_handle(heh))); 00333 //outer vertices have weight -2/81 00334 heh = _m.opposite_halfedge_handle(_m.prev_halfedge_handle(heh)); 00335 assert(heh.is_valid()); 00336 assert(_m.next_halfedge_handle(heh).is_valid()); 00337 assert(_m.to_vertex_handle(_m.next_halfedge_handle(heh)).is_valid()); 00338 pos -= real_t(2.0/81) * _m.point(_m.to_vertex_handle(_m.next_halfedge_handle(heh))); 00339 heh = _m.opposite_halfedge_handle(_m.prev_halfedge_handle(heh)); 00340 assert(heh.is_valid()); 00341 assert(_m.next_halfedge_handle(heh).is_valid()); 00342 assert(_m.to_vertex_handle(_m.next_halfedge_handle(heh)).is_valid()); 00343 pos -= real_t(2.0/81) * _m.point(_m.to_vertex_handle(_m.next_halfedge_handle(heh))); 00344 } 00345 } 00346 else 00347 { 00348 //only use irregular vertices: 00349 for(fheit = _m.fh_iter( fit ); fheit; ++fheit) 00350 { 00351 vh = _m.to_vertex_handle(fheit); 00352 if( (_m.valence(vh) != 6) && (!_m.is_boundary(vh)) ) 00353 { 00354 unsigned int K = _m.valence(vh); 00355 pos += weights_[K][K]*_m.point(vh); 00356 heh = _m.opposite_halfedge_handle( fheit.handle() ); 00357 for(unsigned int i = 0; i<K; ++i, heh = _m.opposite_halfedge_handle(_m.prev_halfedge_handle(heh)) ) 00358 { 00359 pos += weights_[K][i]*_m.point(_m.to_vertex_handle(heh)); 00360 } 00361 } 00362 } 00363 pos *= real_t(1.0/(3-nOrdinary)); 00364 } 00365 00366 vh = _m.add_vertex( pos ); 00367 _m.property(fp_pos_, fit.handle()) = vh; 00368 } 00369 } 00370 00371 //split faces 00372 for (fit = _m.faces_begin();fit != fend; ++fit) 00373 { 00374 if ( _m.is_boundary(fit) && (gen%2)) 00375 { 00376 boundary_split( _m, fit ); 00377 } 00378 else 00379 { 00380 assert(_m.property(fp_pos_, fit.handle()).is_valid()); 00381 _m.split( fit, _m.property(fp_pos_, fit.handle()) ); 00382 } 00383 } 00384 00385 // flip old edges 00386 for (eit=_m.edges_begin(); eit != _m.edges_end(); ++eit) 00387 if ( _m.status( eit ).tagged() && !_m.is_boundary( eit ) ) 00388 _m.flip(eit); 00389 00390 // Now we have an consistent mesh! 00391 ASSERT_CONSISTENCY( MeshType, _m ); 00392 00393 // increase generation by one 00394 ++gen; 00395 } 00396 return true; 00397 } 00398 00399 private: 00400 00401 // Pre-compute location of new boundary points for odd generations 00402 // and store them in the edge property ep_nv_; 00403 void compute_new_boundary_points( MeshType& _m, 00404 const typename MeshType::EdgeHandle& _eh) 00405 { 00406 assert( _m.is_boundary(_eh) ); 00407 00408 typename MeshType::HalfedgeHandle heh; 00409 typename MeshType::VertexHandle vh1, vh2, vh3, vh4, vhl, vhr; 00410 typename MeshType::Point zero(0,0,0), P1, P2, P3, P4; 00411 00412 /* 00413 // *---------*---------* 00414 // / \ / \ / \ 00415 // / \ / \ / \ 00416 // / \ / \ / \ 00417 // / \ / \ / \ 00418 // *---------*--#---#--*---------* 00419 // 00420 // ^ ^ ^ ^ ^ ^ 00421 // P1 P2 pl pr P3 P4 00422 */ 00423 // get halfedge pointing from P3 to P2 (outer boundary halfedge) 00424 00425 heh = _m.halfedge_handle(_eh, 00426 _m.is_boundary(_m.halfedge_handle(_eh,1))); 00427 00428 assert( _m.is_boundary( _m.next_halfedge_handle( heh ) ) ); 00429 assert( _m.is_boundary( _m.prev_halfedge_handle( heh ) ) ); 00430 00431 vh1 = _m.to_vertex_handle( _m.next_halfedge_handle( heh ) ); 00432 vh2 = _m.to_vertex_handle( heh ); 00433 vh3 = _m.from_vertex_handle( heh ); 00434 vh4 = _m.from_vertex_handle( _m.prev_halfedge_handle( heh )); 00435 00436 P1 = _m.point(vh1); 00437 P2 = _m.point(vh2); 00438 P3 = _m.point(vh3); 00439 P4 = _m.point(vh4); 00440 00441 vhl = _m.add_vertex(real_t(-5.0/81)*P1 + real_t(20.0/27)*P2 + real_t(10.0/27)*P3 + real_t(-4.0/81)*P4); 00442 vhr = _m.add_vertex(real_t(-5.0/81)*P4 + real_t(20.0/27)*P3 + real_t(10.0/27)*P2 + real_t(-4.0/81)*P1); 00443 00444 _m.property(ep_nv_, _eh).first = vhl; 00445 _m.property(ep_nv_, _eh).second = vhr; 00446 } 00447 00448 00449 void boundary_split( MeshType& _m, const typename MeshType::FaceHandle& _fh ) 00450 { 00451 assert( _m.is_boundary(_fh) ); 00452 00453 typename MeshType::VertexHandle vhl, vhr; 00454 typename MeshType::FaceEdgeIter fe_it; 00455 typename MeshType::HalfedgeHandle heh; 00456 00457 // find boundary edge 00458 for( fe_it=_m.fe_iter( _fh ); fe_it && !_m.is_boundary( fe_it ); ++fe_it ) {}; 00459 00460 // use precomputed, already inserted but not linked vertices 00461 vhl = _m.property(ep_nv_, fe_it).first; 00462 vhr = _m.property(ep_nv_, fe_it).second; 00463 00464 /* 00465 // *---------*---------* 00466 // / \ / \ / \ 00467 // / \ / \ / \ 00468 // / \ / \ / \ 00469 // / \ / \ / \ 00470 // *---------*--#---#--*---------* 00471 // 00472 // ^ ^ ^ ^ ^ ^ 00473 // P1 P2 pl pr P3 P4 00474 */ 00475 // get halfedge pointing from P2 to P3 (inner boundary halfedge) 00476 00477 heh = _m.halfedge_handle(fe_it, 00478 _m.is_boundary(_m.halfedge_handle(fe_it,0))); 00479 00480 typename MeshType::HalfedgeHandle pl_P3; 00481 00482 // split P2->P3 (heh) in P2->pl (heh) and pl->P3 00483 boundary_split( _m, heh, vhl ); // split edge 00484 pl_P3 = _m.next_halfedge_handle( heh ); // store next halfedge handle 00485 boundary_split( _m, heh ); // split face 00486 00487 // split pl->P3 in pl->pr and pr->P3 00488 boundary_split( _m, pl_P3, vhr ); 00489 boundary_split( _m, pl_P3 ); 00490 00491 assert( _m.is_boundary( vhl ) && _m.halfedge_handle(vhl).is_valid() ); 00492 assert( _m.is_boundary( vhr ) && _m.halfedge_handle(vhr).is_valid() ); 00493 } 00494 00495 void boundary_split(MeshType& _m, 00496 const typename MeshType::HalfedgeHandle& _heh, 00497 const typename MeshType::VertexHandle& _vh) 00498 { 00499 assert( _m.is_boundary( _m.edge_handle(_heh) ) ); 00500 00501 typename MeshType::HalfedgeHandle 00502 heh(_heh), 00503 opp_heh( _m.opposite_halfedge_handle(_heh) ), 00504 new_heh, opp_new_heh; 00505 typename MeshType::VertexHandle to_vh(_m.to_vertex_handle(heh)); 00506 typename MeshType::HalfedgeHandle t_heh; 00507 00508 /* 00509 * P5 00510 * * 00511 * /|\ 00512 * / \ 00513 * / \ 00514 * / \ 00515 * / \ 00516 * /_ heh new \ 00517 * *-----\*-----\*\-----* 00518 * ^ ^ t_heh 00519 * _vh to_vh 00520 * 00521 * P1 P2 P3 P4 00522 */ 00523 // Re-Setting Handles 00524 00525 // find halfedge point from P4 to P3 00526 for(t_heh = heh; 00527 _m.next_halfedge_handle(t_heh) != opp_heh; 00528 t_heh = _m.opposite_halfedge_handle(_m.next_halfedge_handle(t_heh))) 00529 {} 00530 00531 assert( _m.is_boundary( t_heh ) ); 00532 00533 new_heh = _m.new_edge( _vh, to_vh ); 00534 opp_new_heh = _m.opposite_halfedge_handle(new_heh); 00535 00536 // update halfedge connectivity 00537 _m.set_next_halfedge_handle(t_heh, opp_new_heh); // P4-P3 -> P3-P2 00538 _m.set_next_halfedge_handle(new_heh, _m.next_halfedge_handle(heh)); // P2-P3 -> P3-P5 00539 _m.set_next_halfedge_handle(heh, new_heh); // P1-P2 -> P2-P3 00540 _m.set_next_halfedge_handle(opp_new_heh, opp_heh); // P3-P2 -> P2-P1 00541 00542 // both opposite halfedges point to same face 00543 _m.set_face_handle(opp_new_heh, _m.face_handle(opp_heh)); 00544 00545 // let heh finally point to new inserted vertex 00546 _m.set_vertex_handle(heh, _vh); 00547 00548 // let heh and new_heh point to same face 00549 _m.set_face_handle(new_heh, _m.face_handle(heh)); 00550 00551 // let opp_new_heh be the new outgoing halfedge for to_vh 00552 // (replaces for opp_heh) 00553 _m.set_halfedge_handle( to_vh, opp_new_heh ); 00554 00555 // let opp_heh be the outgoing halfedge for _vh 00556 _m.set_halfedge_handle( _vh, opp_heh ); 00557 } 00558 00559 void boundary_split( MeshType& _m, 00560 const typename MeshType::HalfedgeHandle& _heh) 00561 { 00562 assert( _m.is_boundary( _m.opposite_halfedge_handle( _heh ) ) ); 00563 00564 typename MeshType::HalfedgeHandle 00565 heh(_heh), 00566 n_heh(_m.next_halfedge_handle(heh)); 00567 00568 typename MeshType::VertexHandle 00569 to_vh(_m.to_vertex_handle(heh)); 00570 00571 typename MeshType::HalfedgeHandle 00572 heh2(_m.new_edge(to_vh, 00573 _m.to_vertex_handle(_m.next_halfedge_handle(n_heh)))), 00574 heh3(_m.opposite_halfedge_handle(heh2)); 00575 00576 typename MeshType::FaceHandle 00577 new_fh(_m.new_face()), 00578 fh(_m.face_handle(heh)); 00579 00580 // Relink (half)edges 00581 _m.set_face_handle(heh, new_fh); 00582 _m.set_face_handle(heh2, new_fh); 00583 _m.set_next_halfedge_handle(heh2, _m.next_halfedge_handle(_m.next_halfedge_handle(n_heh))); 00584 _m.set_next_halfedge_handle(heh, heh2); 00585 _m.set_face_handle( _m.next_halfedge_handle(heh2), new_fh); 00586 00587 _m.set_next_halfedge_handle(heh3, n_heh); 00588 _m.set_next_halfedge_handle(_m.next_halfedge_handle(n_heh), heh3); 00589 _m.set_face_handle(heh3, fh); 00590 00591 _m.set_halfedge_handle( fh, n_heh); 00592 _m.set_halfedge_handle(new_fh, heh); 00593 00594 00595 } 00596 00597 private: 00598 00599 weights_t weights_; 00600 OpenMesh::FPropHandleT< typename MeshType::VertexHandle > fp_pos_; 00601 OpenMesh::EPropHandleT< std::pair< typename MeshType::VertexHandle, 00602 typename MeshType::VertexHandle> > ep_nv_; 00603 OpenMesh::MPropHandleT< size_t > mp_gen_; 00604 }; 00605 00606 00607 //============================================================================= 00608 } // END_NS_UNIFORM 00609 } // END_NS_SUBDIVIDER 00610 } // END_NS_OPENMESH 00611 //============================================================================= 00612 #endif // OPENMESH_SUBDIVIDER_UNIFORM_SQRT3T_HH 00613 //=============================================================================