a48  2.0.2
include/stellarmesht.hh
Go to the documentation of this file.
00001 
00008 #ifndef A48_STELLARMESHT_HH
00009 #define A48_STELLARMESHT_HH
00010 
00011 //== INCLUDES =================================================================
00012 
00013 #include <mesht.hh>
00014 
00015 //== NAMESPACES ===============================================================
00016 
00017 namespace a48 {
00018 
00019 //== CLASS DEFINITION =========================================================
00020 
00030 template< class Traits = DefaultTraits >
00031 class BaseStellarPolicy {
00032 
00033     typedef typename Traits::vertex_type vertex_type; 
00034     typedef typename Traits::halfedge_type halfedge_type; 
00035     typedef typename Traits::face_type face_type; 
00036 
00037 public:
00038 
00043     virtual void sample_vertex( const face_type *f, vertex_type *v ) = 0;
00044 
00052     virtual void sample_vertex( const halfedge_type *h, vertex_type *v ) = 0;
00053 
00058     virtual void remove_vertex( const face_type *f, const vertex_type *v ) = 0;
00059 
00067     virtual void remove_vertex( const halfedge_type *h, const vertex_type *v ) = 0;
00068 
00075     virtual void flip_halfedge( const halfedge_type *h ) = 0;
00076 
00077 };
00084 //== CLASS DEFINITION =========================================================
00085 
00102 template< class Traits = DefaultTraits >
00103 class StellarMeshT : public MeshT< Traits > {
00104 
00105 public:
00106 
00107     typedef BaseItemsPolicy< Traits > items_policy; 
00108     typedef BaseStellarPolicy< Traits > stellar_policy; 
00109 
00110     typedef typename Traits::vertex_type vertex_type; 
00111     typedef typename Traits::halfedge_type halfedge_type; 
00112     typedef typename Traits::face_type face_type; 
00113 
00115     StellarMeshT() : MeshT< Traits >(), sp(0) { }
00116 
00121     StellarMeshT( stellar_policy *_sp ) :
00122         MeshT< Traits >(), sp(_sp) { }
00123 
00130     StellarMeshT( items_policy *_ip,
00131                   stellar_policy *_sp = 0 ) :
00132         MeshT< Traits >(_ip), sp(_sp) { }
00133 
00137     StellarMeshT( const StellarMeshT< Traits >& _m ) { *this = _m; }
00138 
00143     StellarMeshT< Traits >& operator = ( const StellarMeshT< Traits >& _m ) {
00144         this->sp = _m.get_stellar_policy();
00145         MeshT< Traits >::operator = ( _m );
00146         return *this;
00147     }
00148 
00149     // @name Query functions
00151 
00155     bool is_tri( void ) const {
00156         for (typename MeshT< Traits >::face_iterator fit = this->faces_begin(); fit != this->faces_end(); ++fit)
00157             if( !(*fit)->is_triangle() ) return false;
00158         return true;
00159     }
00160 
00162 
00163     // @name Set functions
00165 
00170     void set_stellar_policy( stellar_policy *_sp ) { sp = _sp; }
00171 
00173 
00174     // @name Get functions
00176 
00181     stellar_policy* get_stellar_policy( void ) { return sp; }
00182 
00186     const stellar_policy* get_stellar_policy( void ) const { return sp; }
00187 
00189 
00190     // @name Stellar operators for a triangulated mesh
00192 
00208     void edge_weld( halfedge_type *h1, halfedge_type *h2 ) {
00209         if( h1->is_boundary() and h2->is_boundary() ) {
00210             // Remove vertex attributes at the base halfedge
00211             if( sp ) sp->remove_vertex( h1, h1->vertex() ); // @see BaseStellarPolicy
00212             delete_vertex( h1->vertex() ); // After saving base halfedge it can be deleted
00213             half_weld( h1 ); // Half weld using base halfedge (unfolding two faces in one)
00214         } else if( h1->vertex()->degree() == 4 ) { weld( h1->vertex() ); }
00215     }
00216 
00230     void face_weld( halfedge_type *h1, halfedge_type *h2, halfedge_type *h3  ) {
00231         if( h1->vertex()->degree() == 3 and h1->vertex() == h2->vertex() == h3->vertex() )
00232             weld( h1->vertex() );
00233     }
00234 
00249     void edge_split( halfedge_type *h ) { split( h ); }
00250 
00262     void face_split( face_type *f ) { split( f ); }
00263 
00277     void flip( halfedge_type *h ) {
00278         if( h->is_boundary() ) return;
00279         if( !h->is_flip_ok() ) return; // Verify if the halfedge can be flipped
00280         // inform policy of the incoming flip
00281         if( sp ) sp->flip_halfedge( h ); // @see BaseStellarPolicy
00282         halfedge_type *ph = h->previous();
00283         halfedge_type *nh = h->next();
00284         ph->set_next( h->opposite()->next() );
00285         nh->set_next( h->opposite() );
00286         if( h->vertex()->halfedge() == h )
00287             h->vertex()->set_halfedge( h->opposite()->previous() );
00288         if( h->opposite()->vertex()->halfedge() == h->opposite() )
00289             h->opposite()->vertex()->set_halfedge( ph );
00290         h->set_vertex( h->next()->vertex() );
00291         h->set_next( ph );
00292         if( h->face()->halfedge() == nh )
00293             h->face()->set_halfedge( h );
00294         ph = h->opposite()->previous();
00295         ph->set_next( nh );
00296         h->opposite()->next()->set_next( h );
00297         h->opposite()->next()->set_face( h->face() );
00298         if( h->opposite()->face()->halfedge() == h->opposite()->next() )
00299             h->opposite()->face()->set_halfedge( h->opposite() );
00300         nh->set_face( h->opposite()->face() );
00301         h->opposite()->set_vertex( h->previous()->vertex() );
00302         h->opposite()->set_next( ph );
00303     }
00304 
00318     void unflip( halfedge_type *h ) {
00319         if( h->is_boundary() ) return;
00320         if( !h->is_flip_ok() ) return; // Verify if the halfedge can be flipped
00321         // inform policy of the incoming flip
00322         if( sp ) sp->flip_halfedge( h ); // @see BaseStellarPolicy
00323         halfedge_type *ph = h->previous();
00324         halfedge_type *nh = h->next();
00325         ph->set_next( h->opposite()->next() );
00326         ph->set_face( h->opposite()->face() );
00327         if( h->vertex()->halfedge() == h )
00328             h->vertex()->set_halfedge( h->opposite()->previous() );
00329         if( h->opposite()->vertex()->halfedge() == h->opposite() )
00330             h->opposite()->vertex()->set_halfedge( ph );
00331         h->set_vertex( h->opposite()->next()->vertex() );
00332         h->set_next( h->opposite()->previous() );
00333         if( h->face()->halfedge() == ph )
00334             h->face()->set_halfedge( h );
00335         ph = h->opposite()->previous();
00336         ph->set_next( nh );
00337         ph->set_face( h->face() );
00338         h->opposite()->next()->set_next( h->opposite() );
00339         if( h->opposite()->face()->halfedge() == ph )
00340             h->opposite()->face()->set_halfedge( h->opposite() );
00341         h->opposite()->set_vertex( nh->vertex() );
00342         h->opposite()->set_next( nh->next() );
00343         nh->set_next( h );
00344     }
00345 
00355     void weld( vertex_type *v ) {
00356         if( !v->is_weld_ok() ) return; // Verify if the vertex can be welded
00357         unsigned int nf = v->incident_faces(); // Number of incident faces
00358         halfedge_type *bh = v->halfedge(); // Base halfedge
00359         halfedge_type *oh; // Opposed halfedge
00360         if( sp and ( nf == 2 or nf == 4 ) ) sp->remove_vertex( bh, v ); // @see BaseStellarPolicy
00361         if( sp and nf == 3 ) sp->remove_vertex( bh->face(), v ); // @see BaseStellarPolicy
00362         delete_vertex( v ); // After saving base halfedge it can be deleted
00363         half_weld( bh ); // Half weld using base halfedge (unfolding two faces in one)
00364         if( nf == 2 ) return; // It is done if there is only two faces incident
00365         else if( nf == 3 ) { // Delete third face below the unfold face
00366             // The opposed halfedge to bh outside third face
00367             oh = bh->opposite()->next()->opposite();
00368             // Set proper halfedges for vertices in the base halfedge
00369             if( bh->vertex()->halfedge() == bh->opposite()->next() )
00370                 bh->vertex()->set_halfedge( bh );
00371             if( bh->opposite()->vertex()->halfedge() == bh->opposite() )
00372                 bh->opposite()->vertex()->set_halfedge( bh->previous() );
00373             // Delete third face and its halfedges
00374             delete_face( bh->opposite()->face() );
00375             delete_halfedge( bh->opposite()->previous() );
00376             delete_halfedge( bh->opposite()->next() );
00377             delete_halfedge( bh->opposite() );
00378             // Set opposite halfedges of the base edge properly
00379             bh->set_opposite( oh );
00380             if( oh ) oh->set_opposite( bh );
00381         } else if( nf == 4 ) {
00382             // The opposed halfedge to bh pointing to the weld vertex
00383             oh = bh->opposite()->previous()->opposite()->previous();
00384             // Half weld using opposed halfedge (unfolding two faces in one)
00385             half_weld( oh );
00386             // Set opposite halfedge of the base edge properly
00387             bh->set_opposite( oh );
00388             oh->set_opposite( bh );
00389         }
00390     }
00391 
00401     void split( halfedge_type *h ) {
00402         unsigned int nf = h->adjacent_faces(); // Number of adjacent faces
00403         vertex_type *v = this->add_vertex(); // Common middle vertex to create
00404         v->set_halfedge( h );
00405         if( sp ) sp->sample_vertex( h, v ); // @see BaseStellarPolicy
00406         half_split( h, v ); // Half split using input halfedge (folding one face in two)
00407         if( nf == 1 ) return; // It is done if there is only one adjacent face
00408         halfedge_type *oh = h->opposite(); // The other-side halfedge
00409         half_split( oh, v ); // Half split the opposite input halfedge
00410         // Fix pointers of the four splitted halfedges
00411         h->next()->opposite()->next()->set_opposite( oh );
00412         oh->set_opposite( h->next()->opposite()->next() );
00413         oh->next()->opposite()->next()->set_opposite( h );
00414         h->set_opposite( oh->next()->opposite()->next() );
00415     }
00416 
00428     void split( face_type *f0 ) {
00429         halfedge_type *h00 = f0->halfedge();
00430         halfedge_type *h10 = h00->next();
00431         halfedge_type *h20 = h10->next();
00432         // Add new mesh elements
00433         vertex_type *v = this->add_vertex();
00434         if( sp ) sp->sample_vertex( f0, v ); // @see BaseStellarPolicy
00435         halfedge_type *h01 = this->add_halfedge();
00436         halfedge_type *h02 = this->add_halfedge();
00437         halfedge_type *h11 = this->add_halfedge();
00438         halfedge_type *h12 = this->add_halfedge();
00439         halfedge_type *h21 = this->add_halfedge();
00440         halfedge_type *h22 = this->add_halfedge();
00441         face_type *f1 = this->add_face();
00442         face_type *f2 = this->add_face();
00443         // Set proper pointers of new elements
00444         f1->set_halfedge( h10 );
00445         f2->set_halfedge( h20 );
00446         h01->set( v, h02, h12, f0 ); h02->set( h20->vertex(), h00, h21, f0 );
00447         h11->set( v, h12, h22, f1 ); h12->set( h00->vertex(), h10, h01, f1 );
00448         h21->set( v, h22, h02, f2 ); h22->set( h10->vertex(), h20, h11, f2 );
00449         v->set_halfedge( h01 );
00450         // Fix pointers of reused elements
00451         h00->set_next( h01 );
00452         h10->set( h11, f1 );
00453         h20->set( h21, f2 );
00454     }
00455 
00457 
00458 private:
00459 
00472     void half_weld( halfedge_type *h ) {
00473         // Previous and next halfedge and opposed vertex (see figure above)
00474         halfedge_type *ph = h->previous();
00475         halfedge_type *nh = h->next()->opposite()->previous();
00476         vertex_type *ov = h->next()->opposite()->next()->vertex();
00477         // Set proper halfedges for pointed vertices
00478         if( ov->halfedge() == h->next()->opposite()->next() )
00479             ov->set_halfedge( h );
00480         if( h->next()->vertex()->halfedge() == h->next() )
00481             h->next()->vertex()->set_halfedge( nh );
00482         // Set proper halfedge for reused face
00483         h->face()->set_halfedge( h );
00484         // Delete second face and its halfedges (unfolding two faces in one)
00485         delete_face( h->next()->opposite()->face() );
00486         delete_halfedge( h->next()->opposite()->next() );
00487         delete_halfedge( h->next()->opposite() );
00488         delete_halfedge( h->next() );
00489         // Fix pointers of reused halfedges
00490         nh->set_face( h->face() );
00491         nh->set_next( ph );
00492         h->set_next( nh );
00493         h->set_vertex( ov );
00494     }
00495 
00509     void half_split( halfedge_type *h, vertex_type *v ) {
00510         halfedge_type *nh = h->next();
00511         vertex_type *ov = h->vertex();
00512         // Add new mesh elements
00513         face_type *f = this->add_face();
00514         halfedge_type *h1 = this->add_halfedge();
00515         halfedge_type *h2 = this->add_halfedge();
00516         halfedge_type *h3 = this->add_halfedge();
00517         // Set proper pointers of new elements
00518         f->set_halfedge( nh );
00519         h1->set( ov, nh, f );
00520         h2->set( v, h1, h3, f );
00521         h3->set( nh->vertex(), h->previous(), h2, h->face() );
00522         // Fix pointers of reused elements
00523         if( ov->halfedge() == h ) ov->set_halfedge( h1 );
00524         h->face()->set_halfedge( h->previous() );
00525         h->set( v, h3 );
00526         nh->set( h2, f );
00527     }
00528 
00529     stellar_policy *sp; 
00530 
00531 };
00538 //=============================================================================
00539 } // namespace a48
00540 //=============================================================================
00541 #endif // A48_STELLARMESHT_HH
00542 //=============================================================================
 All Classes Namespaces Files Functions Typedefs