00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00051
00052
00053
00054
00055
00056
00057
00058 #ifndef SP_MODIFIED_BUTTERFLY_H
00059 #define SP_MODIFIED_BUTTERFLY_H
00060
00061 #include <OpenMesh/Tools/Subdivider/Uniform/SubdividerT.hh>
00062 #include <OpenMesh/Core/Utils/vector_cast.hh>
00063 #include <OpenMesh/Core/Utils/Property.hh>
00064
00065 #include <vector>
00066 #if defined(OM_CC_MIPS)
00067 # include <math.h>
00068 #else
00069 # include <cmath>
00070 #endif
00071
00072
00073
00074
00075 namespace OpenMesh {
00076 namespace Subdivider {
00077 namespace Uniform {
00078
00079
00080
00081
00082
00091 template <typename MeshType, typename RealType = float>
00092 class ModifiedButterflyT : public SubdividerT<MeshType, RealType>
00093 {
00094 public:
00095
00096 typedef RealType real_t;
00097 typedef MeshType mesh_t;
00098 typedef SubdividerT< mesh_t, real_t > parent_t;
00099
00100 typedef std::vector< std::vector<real_t> > weights_t;
00101 typedef std::vector<real_t> weight_t;
00102
00103 public:
00104
00105
00106 ModifiedButterflyT() : parent_t()
00107 { init_weights(); }
00108
00109
00110 ModifiedButterflyT( mesh_t& _m) : parent_t(_m)
00111 { init_weights(); }
00112
00113
00114 ~ModifiedButterflyT() {}
00115
00116
00117 public:
00118
00119
00120 const char *name() const { return "Uniform Spectral"; }
00121
00122
00124 void init_weights(size_t _max_valence=20)
00125 {
00126 weights.resize(_max_valence);
00127
00128
00129 weights[3].resize(4);
00130 weights[3][0] = real_t(5.0)/12;
00131 weights[3][1] = real_t(-1.0)/12;
00132 weights[3][2] = real_t(-1.0)/12;
00133 weights[3][3] = real_t(3.0)/4;
00134
00135 weights[4].resize(5);
00136 weights[4][0] = real_t(3.0)/8;
00137 weights[4][1] = 0;
00138 weights[4][2] = real_t(-1.0)/8;
00139 weights[4][3] = 0;
00140 weights[4][4] = real_t(3.0)/4;
00141
00142 for(unsigned int K = 5; K<_max_valence; ++K)
00143 {
00144 weights[K].resize(K+1);
00145
00146 real_t invK = 1.0/real_t(K);
00147 real_t sum = 0;
00148 for(unsigned int j=0; j<K; ++j)
00149 {
00150 weights[K][j] = (0.25 + cos(2.0*M_PI*j*invK) + 0.5*cos(4.0*M_PI*j*invK))*invK;
00151 sum += weights[K][j];
00152 }
00153 weights[K][K] = (real_t)1.0 - sum;
00154 }
00155 }
00156
00157
00158 protected:
00159
00160
00161 bool prepare( mesh_t& _m )
00162 {
00163 _m.add_property( vp_pos_ );
00164 _m.add_property( ep_pos_ );
00165 return true;
00166 }
00167
00168
00169 bool cleanup( mesh_t& _m )
00170 {
00171 _m.remove_property( vp_pos_ );
00172 _m.remove_property( ep_pos_ );
00173 return true;
00174 }
00175
00176
00177 bool subdivide( mesh_t& _m, size_t _n)
00178 {
00179 typename mesh_t::FaceIter fit, f_end;
00180 typename mesh_t::EdgeIter eit, e_end;
00181 typename mesh_t::VertexIter vit;
00182
00183
00184 for (size_t i=0; i < _n; ++i)
00185 {
00186
00187
00188 typename mesh_t::VertexIter initialVerticesEnd = _m.vertices_end();
00189 for ( vit = _m.vertices_begin(); vit != initialVerticesEnd; ++vit)
00190 _m.property( vp_pos_, vit.handle() ) = _m.point(vit.handle());
00191
00192
00193 for (eit=_m.edges_begin(); eit != _m.edges_end(); ++eit)
00194 compute_midpoint( _m, eit.handle() );
00195
00196
00197
00198
00199
00200
00201 e_end = _m.edges_end();
00202 for (eit=_m.edges_begin(); eit != e_end; ++eit)
00203 split_edge(_m, eit.handle() );
00204
00205
00206
00207
00208
00209 f_end = _m.faces_end();
00210 for (fit = _m.faces_begin(); fit != f_end; ++fit)
00211 split_face(_m, fit.handle() );
00212
00213
00214
00215 for ( vit = _m.vertices_begin();
00216 vit != _m.vertices_end(); ++vit)
00217 _m.set_point(vit, _m.property( vp_pos_, vit ) );
00218
00219 #if defined(_DEBUG) || defined(DEBUG)
00220
00221 assert( OpenMesh::Utils::MeshCheckerT<mesh_t>(_m).check() );
00222 #endif
00223 }
00224
00225 return true;
00226 }
00227
00228 private:
00229
00230 void split_face(mesh_t& _m, const typename mesh_t::FaceHandle& _fh)
00231 {
00232 typename mesh_t::HalfedgeHandle
00233 heh1(_m.halfedge_handle(_fh)),
00234 heh2(_m.next_halfedge_handle(_m.next_halfedge_handle(heh1))),
00235 heh3(_m.next_halfedge_handle(_m.next_halfedge_handle(heh2)));
00236
00237
00238 corner_cutting( _m, heh1 );
00239 corner_cutting( _m, heh2 );
00240 corner_cutting( _m, heh3 );
00241 }
00242
00243
00244 void corner_cutting(mesh_t& _m, const typename mesh_t::HalfedgeHandle& _he)
00245 {
00246
00247 typename mesh_t::HalfedgeHandle
00248 heh1(_he),
00249 heh5(heh1),
00250 heh6(_m.next_halfedge_handle(heh1));
00251
00252
00253 for (; _m.next_halfedge_handle(_m.next_halfedge_handle(heh5)) != heh1;
00254 heh5 = _m.next_halfedge_handle(heh5))
00255 {}
00256
00257 typename mesh_t::VertexHandle
00258 vh1 = _m.to_vertex_handle(heh1),
00259 vh2 = _m.to_vertex_handle(heh5);
00260
00261 typename mesh_t::HalfedgeHandle
00262 heh2(_m.next_halfedge_handle(heh5)),
00263 heh3(_m.new_edge( vh1, vh2)),
00264 heh4(_m.opposite_halfedge_handle(heh3));
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280 typename mesh_t::FaceHandle fh_old(_m.face_handle(heh6));
00281 typename mesh_t::FaceHandle fh_new(_m.new_face());
00282
00283
00284
00285 _m.set_next_halfedge_handle(heh4, heh6);
00286 _m.set_next_halfedge_handle(heh5, heh4);
00287
00288 _m.set_face_handle(heh4, fh_old);
00289 _m.set_face_handle(heh5, fh_old);
00290 _m.set_face_handle(heh6, fh_old);
00291 _m.set_halfedge_handle(fh_old, heh4);
00292
00293
00294 _m.set_next_halfedge_handle(heh1, heh3);
00295 _m.set_next_halfedge_handle(heh3, heh2);
00296
00297 _m.set_face_handle(heh1, fh_new);
00298 _m.set_face_handle(heh2, fh_new);
00299 _m.set_face_handle(heh3, fh_new);
00300
00301 _m.set_halfedge_handle(fh_new, heh1);
00302 }
00303
00304
00305 void split_edge(mesh_t& _m, const typename mesh_t::EdgeHandle& _eh)
00306 {
00307 typename mesh_t::HalfedgeHandle
00308 heh = _m.halfedge_handle(_eh, 0),
00309 opp_heh = _m.halfedge_handle(_eh, 1);
00310
00311 typename mesh_t::HalfedgeHandle new_heh, opp_new_heh, t_heh;
00312 typename mesh_t::VertexHandle vh;
00313 typename mesh_t::VertexHandle vh1(_m.to_vertex_handle(heh));
00314 typename mesh_t::Point zero(0,0,0);
00315
00316
00317 vh = _m.new_vertex( zero );
00318
00319
00320 _m.property( vp_pos_, vh ) = _m.property( ep_pos_, _eh );
00321
00322
00323
00324 if (_m.is_boundary(_eh))
00325 {
00326 for (t_heh = heh;
00327 _m.next_halfedge_handle(t_heh) != opp_heh;
00328 t_heh = _m.opposite_halfedge_handle(_m.next_halfedge_handle(t_heh)))
00329 {}
00330 }
00331 else
00332 {
00333 for (t_heh = _m.next_halfedge_handle(opp_heh);
00334 _m.next_halfedge_handle(t_heh) != opp_heh;
00335 t_heh = _m.next_halfedge_handle(t_heh) )
00336 {}
00337 }
00338
00339 new_heh = _m.new_edge(vh, vh1);
00340 opp_new_heh = _m.opposite_halfedge_handle(new_heh);
00341 _m.set_vertex_handle( heh, vh );
00342
00343 _m.set_next_halfedge_handle(t_heh, opp_new_heh);
00344 _m.set_next_halfedge_handle(new_heh, _m.next_halfedge_handle(heh));
00345 _m.set_next_halfedge_handle(heh, new_heh);
00346 _m.set_next_halfedge_handle(opp_new_heh, opp_heh);
00347
00348 if (_m.face_handle(opp_heh).is_valid())
00349 {
00350 _m.set_face_handle(opp_new_heh, _m.face_handle(opp_heh));
00351 _m.set_halfedge_handle(_m.face_handle(opp_new_heh), opp_new_heh);
00352 }
00353
00354 _m.set_face_handle( new_heh, _m.face_handle(heh) );
00355 _m.set_halfedge_handle( vh, new_heh);
00356 _m.set_halfedge_handle( _m.face_handle(heh), heh );
00357 _m.set_halfedge_handle( vh1, opp_new_heh );
00358
00359
00360 _m.adjust_outgoing_halfedge( vh );
00361 _m.adjust_outgoing_halfedge( vh1 );
00362 }
00363
00364 private:
00365
00366 void compute_midpoint(mesh_t& _m, const typename mesh_t::EdgeHandle& _eh)
00367 {
00368 typename mesh_t::HalfedgeHandle heh, opp_heh;
00369
00370 heh = _m.halfedge_handle( _eh, 0);
00371 opp_heh = _m.halfedge_handle( _eh, 1);
00372
00373 typename mesh_t::Point pos(0,0,0);
00374
00375 typename mesh_t::VertexHandle a_0(_m.to_vertex_handle(heh));
00376 typename mesh_t::VertexHandle a_1(_m.to_vertex_handle(opp_heh));
00377
00378
00379 if (_m.is_boundary(_eh) )
00380 {
00381 pos = _m.point(a_0);
00382 pos += _m.point(a_1);
00383 pos *= 9.0/16;
00384 typename mesh_t::Point tpos;
00385 if(_m.is_boundary(heh))
00386 {
00387 tpos = _m.point(_m.to_vertex_handle(_m.next_halfedge_handle(heh)));
00388 tpos += _m.point(_m.to_vertex_handle(_m.opposite_halfedge_handle(_m.prev_halfedge_handle(heh))));
00389 }
00390 else
00391 {
00392 assert(_m.is_boundary(opp_heh));
00393 tpos = _m.point(_m.to_vertex_handle(_m.next_halfedge_handle(opp_heh)));
00394 tpos += _m.point(_m.to_vertex_handle(_m.opposite_halfedge_handle(_m.prev_halfedge_handle(opp_heh))));
00395 }
00396 tpos *= -1.0/16;
00397 pos += tpos;
00398 }
00399 else
00400 {
00401 int valence_a_0 = _m.valence(a_0);
00402 int valence_a_1 = _m.valence(a_1);
00403 assert(valence_a_0>2);
00404 assert(valence_a_1>2);
00405
00406 if( (valence_a_0==6 && valence_a_1==6) || (_m.is_boundary(a_0) && valence_a_1==6) || (_m.is_boundary(a_1) && valence_a_0==6) || (_m.is_boundary(a_0) && _m.is_boundary(a_1)) )
00407 {
00408 real_t alpha = real_t(1.0/2);
00409 real_t beta = real_t(1.0/8);
00410 real_t gamma = real_t(-1.0/16);
00411
00412
00413 typename mesh_t::VertexHandle b_0, b_1, c_0, c_1, c_2, c_3;
00414 typename mesh_t::HalfedgeHandle t_he;
00415
00416 t_he = _m.next_halfedge_handle(_m.opposite_halfedge_handle(heh));
00417 b_0 = _m.to_vertex_handle(t_he);
00418 if(!_m.is_boundary(_m.opposite_halfedge_handle(t_he)))
00419 {
00420 t_he = _m.next_halfedge_handle(_m.opposite_halfedge_handle(t_he));
00421 c_0 = _m.to_vertex_handle(t_he);
00422 }
00423
00424 t_he = _m.opposite_halfedge_handle(_m.prev_halfedge_handle(heh));
00425 b_1 = _m.to_vertex_handle(t_he);
00426 if(!_m.is_boundary(t_he))
00427 {
00428 t_he = _m.opposite_halfedge_handle(_m.prev_halfedge_handle(t_he));
00429 c_1 = _m.to_vertex_handle(t_he);
00430 }
00431
00432 t_he = _m.next_halfedge_handle(_m.opposite_halfedge_handle(opp_heh));
00433 assert(b_1.idx()==_m.to_vertex_handle(t_he).idx());
00434 if(!_m.is_boundary(_m.opposite_halfedge_handle(t_he)))
00435 {
00436 t_he = _m.next_halfedge_handle(_m.opposite_halfedge_handle(t_he));
00437 c_2 = _m.to_vertex_handle(t_he);
00438 }
00439
00440 t_he = _m.opposite_halfedge_handle(_m.prev_halfedge_handle(opp_heh));
00441 assert(b_0==_m.to_vertex_handle(t_he));
00442 if(!_m.is_boundary(t_he))
00443 {
00444 t_he = _m.opposite_halfedge_handle(_m.prev_halfedge_handle(t_he));
00445 c_3 = _m.to_vertex_handle(t_he);
00446 }
00447
00448
00449
00450 assert(a_0.is_valid());
00451 assert(a_1.is_valid());
00452 assert(b_0.is_valid());
00453 assert(b_1.is_valid());
00454
00455
00456 pos = _m.point(a_0);
00457 pos += _m.point(a_1);
00458 pos *= alpha;
00459
00460 typename mesh_t::Point tpos ( _m.point(b_0) );
00461 tpos += _m.point(b_1);
00462 tpos *= beta;
00463 pos += tpos;
00464
00465 typename mesh_t::Point pc_0, pc_1, pc_2, pc_3;
00466 if(c_0.is_valid())
00467 pc_0 = _m.point(c_0);
00468 else
00469 {
00470 pc_0 = _m.point(a_1) + _m.point(b_0) - _m.point(a_0);
00471 }
00472 if(c_1.is_valid())
00473 pc_1 = _m.point(c_1);
00474 else
00475 {
00476 pc_1 = _m.point(a_1) + _m.point(b_1) - _m.point(a_0);
00477 }
00478 if(c_2.is_valid())
00479 pc_2 = _m.point(c_2);
00480 else
00481 {
00482 pc_2 = _m.point(a_0) + _m.point(b_1) - _m.point(a_1);
00483 }
00484 if(c_3.is_valid())
00485 pc_3 = _m.point(c_3);
00486 else
00487 {
00488 pc_3 = _m.point(a_0) + _m.point(b_0) - _m.point(a_1);
00489 }
00490 tpos = pc_0;
00491 tpos += pc_1;
00492 tpos += pc_2;
00493 tpos += pc_3;
00494 tpos *= gamma;
00495 pos += tpos;
00496 }
00497 else
00498 {
00499 double normFactor = 0.0;
00500
00501 if(valence_a_0!=6 && !_m.is_boundary(a_0))
00502 {
00503 assert((int)weights[valence_a_0].size()==valence_a_0+1);
00504 typename mesh_t::HalfedgeHandle t_he = opp_heh;
00505 for(int i = 0; i < valence_a_0 ; t_he=_m.next_halfedge_handle(_m.opposite_halfedge_handle(t_he)), ++i)
00506 {
00507 pos += weights[valence_a_0][i] * _m.point(_m.to_vertex_handle(t_he));
00508 }
00509 assert(t_he==opp_heh);
00510
00511
00512 pos += weights[valence_a_0][valence_a_0] * _m.point(a_0);
00513 ++normFactor;
00514 }
00515
00516 if(valence_a_1!=6 && !_m.is_boundary(a_1))
00517 {
00518 assert((int)weights[valence_a_1].size()==valence_a_1+1);
00519 typename mesh_t::HalfedgeHandle t_he = heh;
00520 for(int i = 0; i < valence_a_1 ; t_he=_m.next_halfedge_handle(_m.opposite_halfedge_handle(t_he)), ++i)
00521 {
00522 pos += weights[valence_a_1][i] * _m.point(_m.to_vertex_handle(t_he));
00523 }
00524 assert(t_he==heh);
00525
00526 pos += weights[valence_a_1][valence_a_1] * _m.point(a_1);
00527 ++normFactor;
00528 }
00529
00530 assert(normFactor>0.1);
00531
00532
00533 pos /= normFactor;
00534 }
00535 }
00536 _m.property( ep_pos_, _eh ) = pos;
00537 }
00538
00539 private:
00540
00541 OpenMesh::VPropHandleT< typename mesh_t::Point > vp_pos_;
00542 OpenMesh::EPropHandleT< typename mesh_t::Point > ep_pos_;
00543
00544 weights_t weights;
00545
00546 };
00547
00548 }
00549 }
00550 }
00551 #endif
00552