/*#******************* * Adjacency Members * **********************/ /** Return a boolean that indicate if the face is complex. @param j Index of the edge @return true se la faccia e' manifold, false altrimenti */ inline bool IsManifold( const int j ) const { #if (defined(__VCGLIB_FACE_A) || defined(__VCGLIB_FACE_S)) return ( F(j)==this || this == F(j)->F(Z(j)) ); #endif return true; assert(0); } /** Return a boolean that indicate if the j-th edge of the face is a border. @param j Index of the edge @return true if j is an edge of border, false otherwise */ inline bool IsBorder( const int j ) const { #if (defined(__VCGLIB_FACE_A) || defined(__VCGLIB_FACE_S)) return F(j)==this; #endif return true; assert(0); } /// This function counts the boreders of the face inline int BorderCount() const { #if (defined(__VCGLIB_FACE_A) || defined(__VCGLIB_FACE_S)) int t = 0; if( IsBorder(0) ) ++t; if( IsBorder(1) ) ++t; if( IsBorder(2) ) ++t; return t; #endif assert(0); return 3; } /// This function counts the number of incident faces in a complex edge inline int ComplexSize(const int e) const { #if (defined(__VCGLIB_FACE_A) || defined(__VCGLIB_FACE_S)) int cnt=0; FACE_TYPE *fi=(FACE_TYPE *)this; int nzi,zi=e; do { nzi=fi->Z(zi); fi=fi->F(zi); zi=nzi; ++cnt; } while(fi!=this); return cnt; #endif assert(0); return 2; } /*Funzione di detach che scollega una faccia da un ciclo (eventualmente costituito da due soli elementi) incidente su un edge*/ /** This function detach the face from the adjacent face via the edge e. It's possible to use it also in non-two manifold situation. The function cannot be applicated if the adjacencies among faces aren't define. @param e Index of the edge */ void Detach(const int e) { typedef FEdgePosB< FACE_TYPE > ETYPE; assert(!IsBorder(e)); ETYPE EPB(this,e); // la faccia dall'altra parte EPB.NextF(); int cnt=0; while ( EPB.f->F(EPB.z) != this) { assert(!IsManifold(e)); // Si entra in questo loop solo se siamo in una situazione non manifold. assert(!EPB.f->IsBorder(EPB.z)); EPB.NextF(); cnt++; } assert(EPB.f->F(EPB.z)==this); EPB.f->F(EPB.z) = F(e); EPB.f->Z(EPB.z) = Z(e); F(e) = this; Z(e) = e; EPB.f->SetM(); this->SetM(); } void OldDetach(const int e) { typedef EdgePosB< FACE_TYPE > ETYPE; assert(!IsBorder(e)); ETYPE EPB(this,e); ETYPE TEPB(0,-1); EPB.NextF(); while ( EPB.f != this) { TEPB = EPB; assert(!EPB.f->IsBorder(EPB.z)); EPB.NextF(); } assert(TEPB.f->F(TEPB.z)==this); TEPB.f->F(TEPB.z) = F(e); TEPB.f->Z(TEPB.z) = Z(e); F(e) = this; Z(e) = e; TEPB.f->SetM(); this->SetM(); } /** This function attach the face (via the edge z1) to another face (via the edge z2). It's possible to use it also in non-two manifold situation. The function cannot be applicated if the adjacencies among faces aren't define. @param z1 Index of the edge @param f2 Pointer to the face @param z2 The edge of the face f2 */ void Attach(int z1, face_base *&f2, int z2) { typedef FEdgePosB< FACE_TYPE > ETYPE; ETYPE EPB(f2,z2); ETYPE TEPB; TEPB = EPB; EPB.NextF(); while( EPB.f != f2) //Alla fine del ciclo TEPB contiene la faccia che precede f2 { TEPB = EPB; EPB.NextF(); } //Salvo i dati di f1 prima di sovrascrivere face_base *f1prec = this->F(z1); int z1prec = this->Z(z1); //Aggiorno f1 this->F(z1) = TEPB.f->F(TEPB.z); this->Z(z1) = TEPB.f->Z(TEPB.z); //Aggiorno la faccia che precede f2 TEPB.f->F(TEPB.z) = f1prec; TEPB.f->Z(TEPB.z) = z1prec; } void AssertAdj() { assert(F(0)->F(Z(0))==this); assert(F(1)->F(Z(1))==this); assert(F(2)->F(Z(2))==this); assert(F(0)->Z(Z(0))==0); assert(F(1)->Z(Z(1))==1); assert(F(2)->Z(Z(2))==2); } // Funzione di supporto inline void Nexts( face_base *&f,int &z ) { int t; t = z; z = (*f).Z(z); f = (*f).F(t); } /** This function change the orientation of the face. Inverting the index of two vertex @param z Index of the edge */ void Swap ( const int z ) { int i; face_base *tmp, *prec; int t, precz; swap ( V((z )%3),V((z+1)%3)); if( OBJ_TYPE & (OBJ_TYPE_A|OBJ_TYPE_S ) ) { swap ( F((z+1)%3),F((z+2)%3)); swap ( Z((z+1)%3),Z((z+2)%3)); for(i = 1; i < 3; i++) { tmp = this; t = (z+i)%3; do { prec = tmp; precz = t; Nexts(tmp,t); } while (tmp != this); (*prec).Z(precz) = (z+i)%3; } } } // Stacca la faccia corrente dalla catena di facce incidenti sul vertice z, // NOTA funziona SOLO per la topologia VF!!! // usata nelle classi di collapse void VFDetach(int z) { if(V(z)->Fp()==this ) { int fz = V(z)->Zp(); V(z)->Fp() = (face_from_vert_type *) F(fz); V(z)->Zp() = Z(fz); } else { VEdgePosB x,y; x.f = V(z)->Fp(); x.z = V(z)->Zp(); for(;;) { y = x; x.NextF(); assert(x.f!=0); if(x.f==this) { y.f->F(y.z) = F(z); y.f->Z(y.z) = Z(z); break; } } } } } // end namespace #endif