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 unsigned int maxValence = 0;
184 for (
auto vertex : _m.vertices() ) {
185 maxValence = std::max(maxValence,_m.valence(vertex));
189 if (maxValence >= 30) {
194 for (
size_t i=0; i < _n; ++i)
198 for (
auto vh : _m.vertices())
199 _m.property( vp_pos_, vh ) = _m.point(vh);
202 for (
auto eh : _m.edges())
203 compute_midpoint( _m, eh);
210 for (
auto eh : _m.edges())
217 for (
auto fh : _m.faces())
222 for (
auto vh : _m.vertices())
223 _m.set_point(vh, _m.property( vp_pos_, vh ) );
225 #if defined(_DEBUG) || defined(DEBUG)
239 heh1(_m.halfedge_handle(_fh)),
240 heh2(_m.next_halfedge_handle(_m.next_halfedge_handle(heh1))),
241 heh3(_m.next_halfedge_handle(_m.next_halfedge_handle(heh2)));
244 corner_cutting( _m, heh1 );
245 corner_cutting( _m, heh2 );
246 corner_cutting( _m, heh3 );
256 heh6(_m.next_halfedge_handle(heh1));
259 for (; _m.next_halfedge_handle(_m.next_halfedge_handle(heh5)) != heh1;
260 heh5 = _m.next_halfedge_handle(heh5))
264 vh1 = _m.to_vertex_handle(heh1),
265 vh2 = _m.to_vertex_handle(heh5);
268 heh2(_m.next_halfedge_handle(heh5)),
269 heh3(_m.new_edge( vh1, vh2)),
270 heh4(_m.opposite_halfedge_handle(heh3));
291 _m.set_next_halfedge_handle(heh4, heh6);
292 _m.set_next_halfedge_handle(heh5, heh4);
294 _m.set_face_handle(heh4, fh_old);
295 _m.set_face_handle(heh5, fh_old);
296 _m.set_face_handle(heh6, fh_old);
297 _m.set_halfedge_handle(fh_old, heh4);
300 _m.set_next_halfedge_handle(heh1, heh3);
301 _m.set_next_halfedge_handle(heh3, heh2);
303 _m.set_face_handle(heh1, fh_new);
304 _m.set_face_handle(heh2, fh_new);
305 _m.set_face_handle(heh3, fh_new);
307 _m.set_halfedge_handle(fh_new, heh1);
314 heh = _m.halfedge_handle(_eh, 0),
315 opp_heh = _m.halfedge_handle(_eh, 1);
326 _m.property( vp_pos_, vh ) = _m.property( ep_pos_, _eh );
330 if (_m.is_boundary(_eh))
333 _m.next_halfedge_handle(t_heh) != opp_heh;
334 t_heh = _m.opposite_halfedge_handle(_m.next_halfedge_handle(t_heh)))
339 for (t_heh = _m.next_halfedge_handle(opp_heh);
340 _m.next_halfedge_handle(t_heh) != opp_heh;
341 t_heh = _m.next_halfedge_handle(t_heh) )
345 new_heh = _m.new_edge(vh, vh1);
346 opp_new_heh = _m.opposite_halfedge_handle(new_heh);
347 _m.set_vertex_handle( heh, vh );
349 _m.set_next_halfedge_handle(t_heh, opp_new_heh);
350 _m.set_next_halfedge_handle(new_heh, _m.next_halfedge_handle(heh));
351 _m.set_next_halfedge_handle(heh, new_heh);
352 _m.set_next_halfedge_handle(opp_new_heh, opp_heh);
354 if (_m.face_handle(opp_heh).is_valid())
356 _m.set_face_handle(opp_new_heh, _m.face_handle(opp_heh));
357 _m.set_halfedge_handle(_m.face_handle(opp_new_heh), opp_new_heh);
360 _m.set_face_handle( new_heh, _m.face_handle(heh) );
361 _m.set_halfedge_handle( vh, new_heh);
364 if ( !_m.is_boundary(heh) )
365 _m.set_halfedge_handle( _m.face_handle(heh), heh );
367 _m.set_halfedge_handle( vh1, opp_new_heh );
370 _m.adjust_outgoing_halfedge( vh );
371 _m.adjust_outgoing_halfedge( vh1 );
380 heh = _m.halfedge_handle( _eh, 0);
381 opp_heh = _m.halfedge_handle( _eh, 1);
389 if (_m.is_boundary(_eh) )
392 pos += _m.point(a_1);
393 pos *=
static_cast<RealType
>(9.0/16.0);
395 if(_m.is_boundary(heh))
397 tpos = _m.point(_m.to_vertex_handle(_m.next_halfedge_handle(heh)));
398 tpos += _m.point(_m.to_vertex_handle(_m.opposite_halfedge_handle(_m.prev_halfedge_handle(heh))));
402 assert(_m.is_boundary(opp_heh));
403 tpos = _m.point(_m.to_vertex_handle(_m.next_halfedge_handle(opp_heh)));
404 tpos += _m.point(_m.to_vertex_handle(_m.opposite_halfedge_handle(_m.prev_halfedge_handle(opp_heh))));
406 tpos *=
static_cast<RealType
>(-1.0/16.0);
411 int valence_a_0 = _m.valence(a_0);
412 int valence_a_1 = _m.valence(a_1);
413 assert(valence_a_0>2);
414 assert(valence_a_1>2);
416 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)) )
418 real_t alpha = real_t(1.0/2);
419 real_t beta = real_t(1.0/8);
420 real_t gamma = real_t(-1.0/16);
426 t_he = _m.next_halfedge_handle(_m.opposite_halfedge_handle(heh));
427 b_0 = _m.to_vertex_handle(t_he);
428 if(!_m.is_boundary(_m.opposite_halfedge_handle(t_he)))
430 t_he = _m.next_halfedge_handle(_m.opposite_halfedge_handle(t_he));
431 c_0 = _m.to_vertex_handle(t_he);
434 t_he = _m.opposite_halfedge_handle(_m.prev_halfedge_handle(heh));
435 b_1 = _m.to_vertex_handle(t_he);
436 if(!_m.is_boundary(t_he))
438 t_he = _m.opposite_halfedge_handle(_m.prev_halfedge_handle(t_he));
439 c_1 = _m.to_vertex_handle(t_he);
442 t_he = _m.next_halfedge_handle(_m.opposite_halfedge_handle(opp_heh));
443 assert(b_1.idx()==_m.to_vertex_handle(t_he).idx());
444 if(!_m.is_boundary(_m.opposite_halfedge_handle(t_he)))
446 t_he = _m.next_halfedge_handle(_m.opposite_halfedge_handle(t_he));
447 c_2 = _m.to_vertex_handle(t_he);
450 t_he = _m.opposite_halfedge_handle(_m.prev_halfedge_handle(opp_heh));
451 assert(b_0==_m.to_vertex_handle(t_he));
452 if(!_m.is_boundary(t_he))
454 t_he = _m.opposite_halfedge_handle(_m.prev_halfedge_handle(t_he));
455 c_3 = _m.to_vertex_handle(t_he);
460 assert(a_0.is_valid());
461 assert(a_1.is_valid());
462 assert(b_0.is_valid());
463 assert(b_1.is_valid());
467 pos += _m.point(a_1);
471 tpos += _m.point(b_1);
477 pc_0 = _m.point(c_0);
480 pc_0 = _m.point(a_1) + _m.point(b_0) - _m.point(a_0);
483 pc_1 = _m.point(c_1);
486 pc_1 = _m.point(a_1) + _m.point(b_1) - _m.point(a_0);
489 pc_2 = _m.point(c_2);
492 pc_2 = _m.point(a_0) + _m.point(b_1) - _m.point(a_1);
495 pc_3 = _m.point(c_3);
498 pc_3 = _m.point(a_0) + _m.point(b_0) - _m.point(a_1);
509 RealType normFactor =
static_cast<RealType
>(0.0);
511 if(valence_a_0!=6 && !_m.is_boundary(a_0))
513 assert((
int)weights[valence_a_0].size()==valence_a_0+1);
515 for(
int i = 0; i < valence_a_0 ; t_he=_m.next_halfedge_handle(_m.opposite_halfedge_handle(t_he)), ++i)
517 pos += weights[valence_a_0][i] * _m.point(_m.to_vertex_handle(t_he));
519 assert(t_he==opp_heh);
522 pos += weights[valence_a_0][valence_a_0] * _m.point(a_0);
526 if(valence_a_1!=6 && !_m.is_boundary(a_1))
528 assert((
int)weights[valence_a_1].size()==valence_a_1+1);
530 for(
int i = 0; i < valence_a_1 ; t_he=_m.next_halfedge_handle(_m.opposite_halfedge_handle(t_he)), ++i)
532 pos += weights[valence_a_1][i] * _m.point(_m.to_vertex_handle(t_he));
536 pos += weights[valence_a_1][valence_a_1] * _m.point(a_1);
540 assert(normFactor>0.1);
546 _m.property( ep_pos_, _eh ) = pos;
Contains all the mesh ingredients like the polygonal mesh, the triangle mesh, different mesh kernels ...
Definition: MeshItems.hh:59
Triangle mesh based on the ArrayKernel.
Definition: TriMesh_ArrayKernelT.hh:96
Kernel::VertexHandle VertexHandle
Handle for referencing the corresponding item.
Definition: PolyMeshT.hh:136
Kernel::EdgeHandle EdgeHandle
Scalar type.
Definition: PolyMeshT.hh:138
SmartVertexHandle new_vertex()
Uses default copy and assignment operator.
Definition: PolyMeshT.hh:201
Kernel::FaceHandle FaceHandle
Scalar type.
Definition: PolyMeshT.hh:139
Kernel::HalfedgeHandle HalfedgeHandle
Scalar type.
Definition: PolyMeshT.hh:137
Kernel::Point Point
Coordinate type.
Definition: PolyMeshT.hh:112
Modified Butterfly subdivision algorithm.
Definition: ModifiedButterFlyT.hh:93
bool subdivide(MeshType &_m, size_t _n, const bool _update_points=true) override
Subdivide mesh _m _n times.
Definition: ModifiedButterFlyT.hh:177
void init_weights(size_t _max_valence=30)
Pre-compute weights.
Definition: ModifiedButterFlyT.hh:124
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
bool prepare(mesh_t &_m) override
Prepare mesh, e.g. add properties.
Definition: ModifiedButterFlyT.hh:161
Abstract base class for uniform subdivision algorithms.
Definition: SubdividerT.hh:89
Check integrity of mesh.
Definition: MeshCheckerT.hh:74