58 #ifndef SP_MODIFIED_BUTTERFLY_H 59 #define SP_MODIFIED_BUTTERFLY_H 62 #include <OpenMesh/Core/Utils/vector_cast.hh> 63 #include <OpenMesh/Core/Utils/Property.hh> 66 #if defined(OM_CC_MIPS) 76 namespace Subdivider {
91 template <
typename MeshType,
typename RealType =
double>
96 typedef RealType real_t;
97 typedef MeshType mesh_t;
100 typedef std::vector< std::vector<real_t> > weights_t;
101 typedef std::vector<real_t> weight_t;
120 const char *
name()
const override {
return "Uniform Spectral"; }
126 weights.resize(_max_valence);
129 weights[3].resize(4);
130 weights[3][0] = real_t(5.0)/12;
131 weights[3][1] = real_t(-1.0)/12;
132 weights[3][2] = real_t(-1.0)/12;
133 weights[3][3] = real_t(3.0)/4;
135 weights[4].resize(5);
136 weights[4][0] = real_t(3.0)/8;
138 weights[4][2] = real_t(-1.0)/8;
140 weights[4][4] = real_t(3.0)/4;
142 for(
unsigned int K = 5; K<_max_valence; ++K)
144 weights[K].resize(K+1);
146 double invK = 1.0/
static_cast<double>(K);
148 for(
unsigned int j=0; j<K; ++j)
150 weights[K][j] =
static_cast<real_t
>((0.25 + cos(2.0*M_PI*static_cast<double>(j)*invK) + 0.5*cos(4.0*M_PI*static_cast<double>(j)*invK))*invK);
151 sum += weights[K][j];
153 weights[K][K] =
static_cast<real_t
>(1.0) - sum;
163 _m.add_property( vp_pos_ );
164 _m.add_property( ep_pos_ );
171 _m.remove_property( vp_pos_ );
172 _m.remove_property( ep_pos_ );
177 bool subdivide( MeshType& _m,
size_t _n ,
const bool _update_points =
true)
override 183 for (
size_t i=0; i < _n; ++i)
187 typename mesh_t::VertexIter initialVerticesEnd = _m.vertices_end();
188 for (
auto vh : _m.vertices())
189 _m.property( vp_pos_, vh ) = _m.point(vh);
192 for (
auto eh : _m.edges())
193 compute_midpoint( _m, eh);
200 for (
auto eh : _m.edges())
207 for (
auto fh : _m.faces())
212 for (
auto vh : _m.vertices())
213 _m.set_point(vh, _m.property( vp_pos_, vh ) );
215 #if defined(_DEBUG) || defined(DEBUG) 226 void split_face(mesh_t& _m,
const typename mesh_t::FaceHandle& _fh)
228 typename mesh_t::HalfedgeHandle
229 heh1(_m.halfedge_handle(_fh)),
230 heh2(_m.next_halfedge_handle(_m.next_halfedge_handle(heh1))),
231 heh3(_m.next_halfedge_handle(_m.next_halfedge_handle(heh2)));
234 corner_cutting( _m, heh1 );
235 corner_cutting( _m, heh2 );
236 corner_cutting( _m, heh3 );
240 void corner_cutting(mesh_t& _m,
const typename mesh_t::HalfedgeHandle& _he)
243 typename mesh_t::HalfedgeHandle
246 heh6(_m.next_halfedge_handle(heh1));
249 for (; _m.next_halfedge_handle(_m.next_halfedge_handle(heh5)) != heh1;
250 heh5 = _m.next_halfedge_handle(heh5))
254 vh1 = _m.to_vertex_handle(heh1),
255 vh2 = _m.to_vertex_handle(heh5);
257 typename mesh_t::HalfedgeHandle
258 heh2(_m.next_halfedge_handle(heh5)),
259 heh3(_m.new_edge( vh1, vh2)),
260 heh4(_m.opposite_halfedge_handle(heh3));
276 typename mesh_t::FaceHandle fh_old(_m.face_handle(heh6));
277 typename mesh_t::FaceHandle fh_new(_m.new_face());
281 _m.set_next_halfedge_handle(heh4, heh6);
282 _m.set_next_halfedge_handle(heh5, heh4);
284 _m.set_face_handle(heh4, fh_old);
285 _m.set_face_handle(heh5, fh_old);
286 _m.set_face_handle(heh6, fh_old);
287 _m.set_halfedge_handle(fh_old, heh4);
290 _m.set_next_halfedge_handle(heh1, heh3);
291 _m.set_next_halfedge_handle(heh3, heh2);
293 _m.set_face_handle(heh1, fh_new);
294 _m.set_face_handle(heh2, fh_new);
295 _m.set_face_handle(heh3, fh_new);
297 _m.set_halfedge_handle(fh_new, heh1);
301 void split_edge(mesh_t& _m,
const typename mesh_t::EdgeHandle& _eh)
303 typename mesh_t::HalfedgeHandle
304 heh = _m.halfedge_handle(_eh, 0),
305 opp_heh = _m.halfedge_handle(_eh, 1);
307 typename mesh_t::HalfedgeHandle new_heh, opp_new_heh, t_heh;
310 typename mesh_t::Point zero(0,0,0);
313 vh = _m.new_vertex( zero );
316 _m.property( vp_pos_, vh ) = _m.property( ep_pos_, _eh );
320 if (_m.is_boundary(_eh))
323 _m.next_halfedge_handle(t_heh) != opp_heh;
324 t_heh = _m.opposite_halfedge_handle(_m.next_halfedge_handle(t_heh)))
329 for (t_heh = _m.next_halfedge_handle(opp_heh);
330 _m.next_halfedge_handle(t_heh) != opp_heh;
331 t_heh = _m.next_halfedge_handle(t_heh) )
335 new_heh = _m.new_edge(vh, vh1);
336 opp_new_heh = _m.opposite_halfedge_handle(new_heh);
337 _m.set_vertex_handle( heh, vh );
339 _m.set_next_halfedge_handle(t_heh, opp_new_heh);
340 _m.set_next_halfedge_handle(new_heh, _m.next_halfedge_handle(heh));
341 _m.set_next_halfedge_handle(heh, new_heh);
342 _m.set_next_halfedge_handle(opp_new_heh, opp_heh);
344 if (_m.face_handle(opp_heh).is_valid())
346 _m.set_face_handle(opp_new_heh, _m.face_handle(opp_heh));
347 _m.set_halfedge_handle(_m.face_handle(opp_new_heh), opp_new_heh);
350 _m.set_face_handle( new_heh, _m.face_handle(heh) );
351 _m.set_halfedge_handle( vh, new_heh);
354 if ( !_m.is_boundary(heh) )
355 _m.set_halfedge_handle( _m.face_handle(heh), heh );
357 _m.set_halfedge_handle( vh1, opp_new_heh );
360 _m.adjust_outgoing_halfedge( vh );
361 _m.adjust_outgoing_halfedge( vh1 );
366 void compute_midpoint(mesh_t& _m,
const typename mesh_t::EdgeHandle& _eh)
368 typename mesh_t::HalfedgeHandle heh, opp_heh;
370 heh = _m.halfedge_handle( _eh, 0);
371 opp_heh = _m.halfedge_handle( _eh, 1);
373 typename mesh_t::Point pos(0,0,0);
379 if (_m.is_boundary(_eh) )
382 pos += _m.point(a_1);
383 pos *=
static_cast<RealType
>(9.0/16.0);
384 typename mesh_t::Point tpos;
385 if(_m.is_boundary(heh))
387 tpos = _m.point(_m.to_vertex_handle(_m.next_halfedge_handle(heh)));
388 tpos += _m.point(_m.to_vertex_handle(_m.opposite_halfedge_handle(_m.prev_halfedge_handle(heh))));
392 assert(_m.is_boundary(opp_heh));
393 tpos = _m.point(_m.to_vertex_handle(_m.next_halfedge_handle(opp_heh)));
394 tpos += _m.point(_m.to_vertex_handle(_m.opposite_halfedge_handle(_m.prev_halfedge_handle(opp_heh))));
396 tpos *=
static_cast<RealType
>(-1.0/16.0);
401 int valence_a_0 = _m.valence(a_0);
402 int valence_a_1 = _m.valence(a_1);
403 assert(valence_a_0>2);
404 assert(valence_a_1>2);
406 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)) )
408 real_t alpha = real_t(1.0/2);
409 real_t beta = real_t(1.0/8);
410 real_t gamma = real_t(-1.0/16);
414 typename mesh_t::HalfedgeHandle t_he;
416 t_he = _m.next_halfedge_handle(_m.opposite_halfedge_handle(heh));
417 b_0 = _m.to_vertex_handle(t_he);
418 if(!_m.is_boundary(_m.opposite_halfedge_handle(t_he)))
420 t_he = _m.next_halfedge_handle(_m.opposite_halfedge_handle(t_he));
421 c_0 = _m.to_vertex_handle(t_he);
424 t_he = _m.opposite_halfedge_handle(_m.prev_halfedge_handle(heh));
425 b_1 = _m.to_vertex_handle(t_he);
426 if(!_m.is_boundary(t_he))
428 t_he = _m.opposite_halfedge_handle(_m.prev_halfedge_handle(t_he));
429 c_1 = _m.to_vertex_handle(t_he);
432 t_he = _m.next_halfedge_handle(_m.opposite_halfedge_handle(opp_heh));
433 assert(b_1.idx()==_m.to_vertex_handle(t_he).idx());
434 if(!_m.is_boundary(_m.opposite_halfedge_handle(t_he)))
436 t_he = _m.next_halfedge_handle(_m.opposite_halfedge_handle(t_he));
437 c_2 = _m.to_vertex_handle(t_he);
440 t_he = _m.opposite_halfedge_handle(_m.prev_halfedge_handle(opp_heh));
441 assert(b_0==_m.to_vertex_handle(t_he));
442 if(!_m.is_boundary(t_he))
444 t_he = _m.opposite_halfedge_handle(_m.prev_halfedge_handle(t_he));
445 c_3 = _m.to_vertex_handle(t_he);
450 assert(a_0.is_valid());
451 assert(a_1.is_valid());
452 assert(b_0.is_valid());
453 assert(b_1.is_valid());
457 pos += _m.point(a_1);
460 typename mesh_t::Point tpos ( _m.point(b_0) );
461 tpos += _m.point(b_1);
465 typename mesh_t::Point pc_0, pc_1, pc_2, pc_3;
467 pc_0 = _m.point(c_0);
470 pc_0 = _m.point(a_1) + _m.point(b_0) - _m.point(a_0);
473 pc_1 = _m.point(c_1);
476 pc_1 = _m.point(a_1) + _m.point(b_1) - _m.point(a_0);
479 pc_2 = _m.point(c_2);
482 pc_2 = _m.point(a_0) + _m.point(b_1) - _m.point(a_1);
485 pc_3 = _m.point(c_3);
488 pc_3 = _m.point(a_0) + _m.point(b_0) - _m.point(a_1);
499 RealType normFactor =
static_cast<RealType
>(0.0);
501 if(valence_a_0!=6 && !_m.is_boundary(a_0))
503 assert((
int)weights[valence_a_0].size()==valence_a_0+1);
504 typename mesh_t::HalfedgeHandle t_he = opp_heh;
505 for(
int i = 0; i < valence_a_0 ; t_he=_m.next_halfedge_handle(_m.opposite_halfedge_handle(t_he)), ++i)
507 pos += weights[valence_a_0][i] * _m.point(_m.to_vertex_handle(t_he));
509 assert(t_he==opp_heh);
512 pos += weights[valence_a_0][valence_a_0] * _m.point(a_0);
516 if(valence_a_1!=6 && !_m.is_boundary(a_1))
518 assert((
int)weights[valence_a_1].size()==valence_a_1+1);
519 typename mesh_t::HalfedgeHandle t_he = heh;
520 for(
int i = 0; i < valence_a_1 ; t_he=_m.next_halfedge_handle(_m.opposite_halfedge_handle(t_he)), ++i)
522 pos += weights[valence_a_1][i] * _m.point(_m.to_vertex_handle(t_he));
526 pos += weights[valence_a_1][valence_a_1] * _m.point(a_1);
530 assert(normFactor>0.1);
536 _m.property( ep_pos_, _eh ) = pos;
bool subdivide(MeshType &_m, size_t _n, const bool _update_points=true) override
Subdivide mesh _m _n times.
Definition: ModifiedButterFlyT.hh:177
Modified Butterfly subdivision algorithm.
Definition: ModifiedButterFlyT.hh:92
bool cleanup(mesh_t &_m) override
Cleanup mesh after usage, e.g. remove added properties.
Definition: ModifiedButterFlyT.hh:169
const char * name() const override
Return name of subdivision algorithm.
Definition: ModifiedButterFlyT.hh:120
Abstract base class for uniform subdivision algorithms.
Definition: SubdividerT.hh:88
bool prepare(mesh_t &_m) override
Prepare mesh, e.g. add properties.
Definition: ModifiedButterFlyT.hh:161
void init_weights(size_t _max_valence=30)
Pre-compute weights.
Definition: ModifiedButterFlyT.hh:124
Check integrity of mesh.
Definition: MeshCheckerT.hh:73
Contains all the mesh ingredients like the polygonal mesh, the triangle mesh, different mesh kernels ...
Definition: MeshItems.hh:59
Kernel::VertexHandle VertexHandle
Handle for referencing the corresponding item.
Definition: PolyMeshT.hh:136