54 #ifndef OPENMESH_SUBDIVIDER_UNIFORM_SQRT3T_HH 
   55 #define OPENMESH_SUBDIVIDER_UNIFORM_SQRT3T_HH 
   60 #include <OpenMesh/Core/Mesh/Handles.hh> 
   61 #include <OpenMesh/Core/System/config.hh> 
   63 #if defined(_DEBUG) || defined(DEBUG) 
   66 #  include <OpenMesh/Tools/Utils/MeshCheckerT.hh> 
   67 #  define ASSERT_CONSISTENCY( T, m ) \ 
   68      assert(OpenMesh::Utils::MeshCheckerT<T>(m).check()) 
   70 #  define ASSERT_CONSISTENCY( T, m ) 
   74 #if defined(OM_CC_MIPS) 
   84 namespace Subdivider { 
 
   97 template <
typename MeshType, 
typename RealType = 
double>
 
  102   typedef RealType                                real_t;
 
  103   typedef MeshType                                mesh_t;
 
  106   typedef std::pair< real_t, real_t >             weight_t;
 
  107   typedef std::vector< std::pair<real_t,real_t> > weights_t;
 
  112   Sqrt3T(
void) : 
parent_t(), _1over3( real_t(1.0/3.0) ), _1over27( real_t(1.0/27.0) )
 
  115   explicit Sqrt3T(MeshType &_m) : 
parent_t(_m), _1over3( real_t(1.0/3.0) ), _1over27( real_t(1.0/27.0) )
 
  124   const char *
name()
 const override { 
return "Uniform Sqrt3"; }
 
  130     weights_.resize(_max_valence);
 
  131     std::generate(weights_.begin(), weights_.end(), compute_weight());
 
  140     _m.request_edge_status();
 
  141     _m.add_property( vp_pos_ );
 
  142     _m.add_property( ep_nv_ );
 
  143     _m.add_property( mp_gen_ );
 
  144     _m.property( mp_gen_ ) = 0;
 
  146     return _m.has_edge_status() && vp_pos_.
is_valid() 
 
  153     _m.release_edge_status();
 
  154     _m.remove_property( vp_pos_ );
 
  155     _m.remove_property( ep_nv_ );
 
  156     _m.remove_property( mp_gen_ );
 
  160   bool subdivide( MeshType& _m, 
size_t _n , 
const bool _update_points = 
true)
 override 
  165     typename MeshType::Point            pos(0,0,0), zero(0,0,0);
 
  166     size_t                            &gen = _m.property( mp_gen_ );
 
  168     for (
size_t l=0; l<_n; ++l)
 
  171       for (
auto eh : _m.edges())
 
  173         _m.status( eh ).set_tagged( 
true );
 
  174         if ( (gen%2) && _m.is_boundary(eh) )
 
  175           compute_new_boundary_points( _m, eh ); 
 
  180       for (
auto vh : _m.vertices())
 
  182         if ( _m.is_boundary(vh) )
 
  186             auto heh  = _m.halfedge_handle(vh);
 
  189               auto prev_heh = _m.prev_halfedge_handle(heh);
 
  191               assert( _m.is_boundary(heh     ) );
 
  192               assert( _m.is_boundary(prev_heh) );
 
  194               pos  = _m.point(_m.to_vertex_handle(heh));
 
  195               pos += _m.point(_m.from_vertex_handle(prev_heh));
 
  198               pos += real_t(19.0) * _m.point( vh );
 
  201               _m.property( vp_pos_, vh ) = pos;
 
  205             _m.property( vp_pos_, vh ) = _m.point( vh );
 
  212           for ( 
auto vvh : _m.vv_range(vh))
 
  214             pos += _m.point( vvh );
 
  217           pos *= weights_[ valence ].second;
 
  218           pos += weights_[ valence ].first * _m.point(vh);
 
  219           _m.property( vp_pos_, vh ) =  pos;
 
  224       for (
auto fh : _m.faces())
 
  226         if ( (gen%2) && _m.is_boundary(fh))
 
  228           boundary_split( _m, fh );
 
  232           auto fvit = _m.fv_iter( fh );
 
  233           pos  = _m.point(  *fvit);
 
  234           pos += _m.point(*(++fvit));
 
  235           pos += _m.point(*(++fvit));
 
  237           auto vh = _m.add_vertex( zero );
 
  238           _m.property( vp_pos_, vh ) = pos;
 
  244       for (
auto vh : _m.vertices())
 
  245         _m.set_point(vh, _m.property( vp_pos_, vh ) );
 
  248       for (
auto eh : _m.edges())
 
  249         if ( _m.status( eh ).tagged() && !_m.is_boundary( eh ) )
 
  253       ASSERT_CONSISTENCY( MeshType, _m );
 
  265   struct compute_weight 
 
  267     compute_weight() : valence(-1) { }    
 
  270 #if !defined(OM_CC_MIPS) 
  275         real_t alpha = real_t( (4.0-2.0*cos(2.0*M_PI / real_t(valence)) )/9.0 );
 
  276         return weight_t( real_t(1)-alpha, alpha/real_t(valence) );
 
  278       return weight_t(real_t(0.0), real_t(0.0) );
 
  287   void compute_new_boundary_points( MeshType& _m, 
 
  288                                     const typename MeshType::EdgeHandle& _eh)
 
  290     assert( _m.is_boundary(_eh) );
 
  292     typename MeshType::HalfedgeHandle heh;
 
  293     typename MeshType::VertexHandle   vh1, vh2, vh3, vh4, vhl, vhr;
 
  294     typename MeshType::Point          zero(0,0,0), P1, P2, P3, P4;
 
  309     heh = _m.halfedge_handle(_eh, 
 
  310                              _m.is_boundary(_m.halfedge_handle(_eh,1)));
 
  312     assert( _m.is_boundary( _m.next_halfedge_handle( heh ) ) );
 
  313     assert( _m.is_boundary( _m.prev_halfedge_handle( heh ) ) );
 
  315     vh1 = _m.to_vertex_handle( _m.next_halfedge_handle( heh ) );
 
  316     vh2 = _m.to_vertex_handle( heh );
 
  317     vh3 = _m.from_vertex_handle( heh );
 
  318     vh4 = _m.from_vertex_handle( _m.prev_halfedge_handle( heh ));
 
  325     vhl = _m.add_vertex(zero);
 
  326     vhr = _m.add_vertex(zero);
 
  328     _m.property(vp_pos_, vhl ) = (P1 + real_t(16.0f) * P2 + real_t(10.0f) * P3) * _1over27;
 
  329     _m.property(vp_pos_, vhr ) = ( real_t(10.0f) * P2 + real_t(16.0f) * P3 + P4) * _1over27;
 
  330     _m.property(ep_nv_, _eh).first  = vhl;
 
  331     _m.property(ep_nv_, _eh).second = vhr; 
 
  335   void boundary_split( MeshType& _m, 
const typename MeshType::FaceHandle& _fh )
 
  337     assert( _m.is_boundary(_fh) );
 
  339     typename MeshType::VertexHandle     vhl, vhr;
 
  340     typename MeshType::FaceEdgeIter     fe_it;
 
  341     typename MeshType::HalfedgeHandle   heh;
 
  344     for( fe_it=_m.fe_iter( _fh ); fe_it.is_valid() && !_m.is_boundary( *fe_it ); ++fe_it ) {};
 
  347     vhl = _m.property(ep_nv_, *fe_it).first;
 
  348     vhr = _m.property(ep_nv_, *fe_it).second;
 
  363     heh = _m.halfedge_handle(*fe_it,
 
  364                              _m.is_boundary(_m.halfedge_handle(*fe_it,0)));
 
  366     typename MeshType::HalfedgeHandle pl_P3;
 
  369     boundary_split( _m, heh, vhl );         
 
  370     pl_P3 = _m.next_halfedge_handle( heh ); 
 
  371     boundary_split( _m, heh );              
 
  374     boundary_split( _m, pl_P3, vhr );
 
  375     boundary_split( _m, pl_P3 );
 
  377     assert( _m.is_boundary( vhl ) && _m.halfedge_handle(vhl).is_valid() );
 
  378     assert( _m.is_boundary( vhr ) && _m.halfedge_handle(vhr).is_valid() );
 
  381   void boundary_split(MeshType& _m, 
 
  382                       const typename MeshType::HalfedgeHandle& _heh,
 
  383                       const typename MeshType::VertexHandle& _vh)
 
  385     assert( _m.is_boundary( _m.edge_handle(_heh) ) );
 
  387     typename MeshType::HalfedgeHandle 
 
  389       opp_heh( _m.opposite_halfedge_handle(_heh) ),
 
  390       new_heh, opp_new_heh;
 
  391     typename MeshType::VertexHandle   to_vh(_m.to_vertex_handle(heh));
 
  392     typename MeshType::HalfedgeHandle t_heh;
 
  413         _m.next_halfedge_handle(t_heh) != opp_heh; 
 
  414         t_heh = _m.opposite_halfedge_handle(_m.next_halfedge_handle(t_heh)))
 
  417     assert( _m.is_boundary( t_heh ) );
 
  419     new_heh     = _m.new_edge( _vh, to_vh );
 
  420     opp_new_heh = _m.opposite_halfedge_handle(new_heh);
 
  424     _m.set_next_halfedge_handle(t_heh,   opp_new_heh); 
 
  426     _m.set_next_halfedge_handle(new_heh, _m.next_halfedge_handle(heh));    
 
  427     _m.set_next_halfedge_handle(heh,         new_heh); 
 
  428     _m.set_next_halfedge_handle(opp_new_heh, opp_heh); 
 
  431     _m.set_face_handle(opp_new_heh, _m.face_handle(opp_heh));
 
  434     _m.set_vertex_handle(heh, _vh); 
 
  437     _m.set_face_handle(new_heh, _m.face_handle(heh));
 
  441     _m.set_halfedge_handle( to_vh, opp_new_heh );
 
  444     _m.set_halfedge_handle( _vh, opp_heh );
 
  447   void boundary_split( MeshType& _m, 
 
  448                        const typename MeshType::HalfedgeHandle& _heh)
 
  450     assert( _m.is_boundary( _m.opposite_halfedge_handle( _heh ) ) );
 
  452     typename MeshType::HalfedgeHandle 
 
  454       n_heh(_m.next_halfedge_handle(heh));
 
  456     typename MeshType::VertexHandle   
 
  457       to_vh(_m.to_vertex_handle(heh));
 
  459     typename MeshType::HalfedgeHandle 
 
  460       heh2(_m.new_edge(to_vh,
 
  461                        _m.to_vertex_handle(_m.next_halfedge_handle(n_heh)))),
 
  462       heh3(_m.opposite_halfedge_handle(heh2));
 
  464     typename MeshType::FaceHandle
 
  465       new_fh(_m.new_face()),
 
  466       fh(_m.face_handle(heh));
 
  470 #define set_next_heh set_next_halfedge_handle 
  471 #define next_heh next_halfedge_handle 
  473     _m.set_face_handle(heh,  new_fh);
 
  474     _m.set_face_handle(heh2, new_fh);
 
  475     _m.set_next_heh(heh2, _m.next_heh(_m.next_heh(n_heh)));
 
  476     _m.set_next_heh(heh,  heh2);
 
  477     _m.set_face_handle( _m.next_heh(heh2), new_fh);
 
  481     _m.set_next_heh(heh3,                           n_heh);
 
  482     _m.set_next_heh(_m.next_halfedge_handle(n_heh), heh3);
 
  483     _m.set_face_handle(heh3,  fh);
 
  486     _m.set_halfedge_handle(    fh, n_heh);
 
  487     _m.set_halfedge_handle(new_fh, heh);
 
  489 #undef set_next_halfedge_handle 
  490 #undef next_halfedge_handle 
  499                                      typename MeshType::VertexHandle> > ep_nv_;
 
  502   const real_t _1over3;
 
  503   const real_t _1over27;
 
Contains all the mesh ingredients like the polygonal mesh, the triangle mesh, different mesh kernels ...
Definition: MeshItems.hh:59
 
bool is_valid() const
The handle is valid iff the index is not negative.
Definition: Handles.hh:72
 
Handle representing an edge property.
Definition: Property.hh:447
 
Uniform Sqrt3 subdivision algorithm
Definition: Sqrt3T.hh:99
 
bool cleanup(MeshType &_m) override
Cleanup mesh after usage, e.g. remove added properties.
Definition: Sqrt3T.hh:151
 
bool subdivide(MeshType &_m, size_t _n, const bool _update_points=true) override
Subdivide mesh _m _n times.
Definition: Sqrt3T.hh:160
 
bool prepare(MeshType &_m) override
Prepare mesh, e.g. add properties.
Definition: Sqrt3T.hh:138
 
const char * name() const override
Return name of subdivision algorithm.
Definition: Sqrt3T.hh:124
 
void init_weights(size_t _max_valence=50)
Pre-compute weights.
Definition: Sqrt3T.hh:128
 
Abstract base class for uniform subdivision algorithms.
Definition: SubdividerT.hh:89
 
bool operator()(MeshType &_m, size_t _n, const bool _update_points=true)
Subdivide the mesh _m _n times.
Definition: SubdividerT.hh:122