diff --git a/vcg/complex/trimesh/update/halfedge_topology.h b/vcg/complex/trimesh/update/halfedge_topology.h index f43f53dc..393bfe43 100644 --- a/vcg/complex/trimesh/update/halfedge_topology.h +++ b/vcg/complex/trimesh/update/halfedge_topology.h @@ -46,11 +46,11 @@ namespace vcg /// Default Constructor Garbage() { - }; + } ~Garbage() { - }; + } void undelete_hedges(MeshType &m) { @@ -133,20 +133,18 @@ namespace vcg * * \return Pointer to the new vertex */ - static VertexPointer edge_collapse_quad(MeshType &m, EdgePointer ep, VertexPointer vp) + static VertexPointer edge_collapse_quad(MeshType &m, HEdgePointer hp, VertexPointer vp) { assert(vp); - assert(ep); - assert(MeshType::EdgeType::HasEHAdjacency()); - assert(MeshType::HEdgeType::HasHEAdjacency()); + assert(hp); assert(MeshType::HEdgeType::HasHVAdjacency()); - assert(ep->EHp()->HVp() == vp || ep->EHp()->HOp()->HVp() == vp); - assert(ep->EHp()->HFp()->VN() == 4); - assert(ep->EHp()->HOp()->HFp()->VN() == 4); + assert(hp->HVp() == vp || hp->HOp()->HVp() == vp); + assert(hp->HFp()->VN() == 4); + assert(hp->HOp()->HFp()->VN() == 4); + VertexPointer vp_opp; FacePointer fp; - HEdgePointer hp = ep->EHp(); if( hp->HVp() == vp ) hp = hp->HOp(); @@ -176,10 +174,8 @@ namespace vcg { assert(MeshType::VertexType::HasVHAdjacency()); - assert(MeshType::EdgeType::HasEHAdjacency()); assert(MeshType::FaceType::HasFHAdjacency()); assert(MeshType::HEdgeType::HasHVAdjacency()); - assert(MeshType::HEdgeType::HasHEAdjacency()); assert(MeshType::HEdgeType::HasHFAdjacency()); assert(MeshType::HEdgeType::HasHOppAdjacency()); assert(MeshType::HEdgeType::HasHPrevAdjacency()); @@ -192,6 +188,8 @@ namespace vcg assert( !has_doublet(fp) ); assert(!is_singlet(fp)); + bool HasHE = MeshType::HEdgeType::HasHEAdjacency(); + bool HasEH = MeshType::EdgeType::HasEHAdjacency(); HEdgePointer hp; @@ -225,22 +223,27 @@ namespace vcg hps[2]->HOp()->HOp()=hps[3]->HOp(); hps[3]->HOp()->HOp()=hps[2]->HOp(); - - hps[1]->HOp()->HEp()=hps[0]->HEp(); - hps[3]->HOp()->HEp()=hps[2]->HEp(); - - for(int i=0; i<3; i+=2) - { - if(hps[i]->HEp()->EHp() == hps[i]) - hps[i]->HEp()->EHp() = hps[i]->HOp(); - } - for(int i=0; i<4; i++) { if(hps[i]->HVp()->VHp() == hps[i]) hps[i]->HVp()->VHp() = hps[(i+4-1)%4]->HOp(); } + if(HasHE) + { + hps[1]->HOp()->HEp()=hps[0]->HEp(); + hps[3]->HOp()->HEp()=hps[2]->HEp(); + } + + if(HasEH && HasHE) + { + for(int i=0; i<3; i+=2) + { + if(hps[i]->HEp()->EHp() == hps[i]) + hps[i]->HEp()->EHp() = hps[i]->HOp(); + } + } + // there are no faces, remove hedges and edge /* /\ @@ -261,7 +264,9 @@ namespace vcg { if(b[j]) { - Allocator::DeleteEdge(m, *(hps[i]->HEp()) ); + if(HasHE) + Allocator::DeleteEdge(m, *(hps[i]->HEp()) ); + Allocator::DeleteHEdge(m, *(hps[i]->HOp()) ); Allocator::DeleteHEdge(m, *(hps[i+1]->HOp()) ); @@ -285,15 +290,16 @@ namespace vcg Allocator::DeleteFace(m, *(fp) ); Allocator::DeleteVertex(m, *(opposite_vertex) ); - Allocator::DeleteEdge(m, *(hps[1]->HEp()) ); - Allocator::DeleteEdge(m, *(hps[3]->HEp()) ); + if(HasHE) + { + Allocator::DeleteEdge(m, *(hps[1]->HEp()) ); + Allocator::DeleteEdge(m, *(hps[3]->HEp()) ); + } Allocator::DeleteHEdge(m, *(hps[0]) ); Allocator::DeleteHEdge(m, *(hps[1]) ); Allocator::DeleteHEdge(m, *(hps[2]) ); Allocator::DeleteHEdge(m, *(hps[3]) ); -// assert( !is_nonManifold_vertex(m, vp) ); - return vp; } @@ -353,8 +359,11 @@ namespace vcg Allocator::DeleteVertex(m, *vp); - Allocator::DeleteEdge(m, *(hp->HEp()) ); - Allocator::DeleteEdge(m, *(hp->HPp()->HEp()) ); + if(MeshType::HEdgeType::HasHEAdjacency()) + { + Allocator::DeleteEdge(m, *(hp->HEp()) ); + Allocator::DeleteEdge(m, *(hp->HPp()->HEp()) ); + } Allocator::DeleteHEdge(m, *hp ); Allocator::DeleteHEdge(m, *(hp->HOp()) ); Allocator::DeleteHEdge(m, *(hp->HPp()) ); @@ -374,9 +383,9 @@ namespace vcg * \param m Mesh * \param vp Vertex shared by the two consecutive edges inside the singlet * - * \return Pointer to the new edge + * \return Pointer to an halfdedge representing the new edge */ - static EdgePointer singlet_remove(MeshType &m, FacePointer fp) + static HEdgePointer singlet_remove(MeshType &m, FacePointer fp) { /* 2 @@ -393,6 +402,8 @@ namespace vcg assert( is_singlet(fp) ); + bool HasHE = MeshType::HEdgeType::HasHEAdjacency(); + bool HasEH = MeshType::EdgeType::HasEHAdjacency(); vector ext_hedges; @@ -409,7 +420,8 @@ namespace vcg else if(vertex_valence((*hi)->HVp()) == 1) { Allocator::DeleteVertex( m, *((*hi)->HVp()) ); - Allocator::DeleteEdge( m, *((*hi)->HEp()) ); + if(HasHE) + Allocator::DeleteEdge( m, *((*hi)->HEp()) ); } } @@ -425,16 +437,20 @@ namespace vcg ext_hedges[0]->HOp() = ext_hedges[1]; ext_hedges[1]->HOp() = ext_hedges[0]; - Allocator::DeleteEdge( m, *(ext_hedges[1]->HEp()) ); + if(HasHE) + { + Allocator::DeleteEdge( m, *(ext_hedges[1]->HEp()) ); - ext_hedges[1]->HEp() = ext_hedges[0]->HEp(); + ext_hedges[1]->HEp() = ext_hedges[0]->HEp(); - ext_hedges[0]->HEp()->EHp() = ext_hedges[0]; + if(HasEH) + ext_hedges[0]->HEp()->EHp() = ext_hedges[0]; + } ext_hedges[0]->HVp()->VHp() = ext_hedges[0]; ext_hedges[1]->HVp()->VHp() = ext_hedges[1]; - return ext_hedges[0]->HEp(); + return ext_hedges[0]; } else @@ -442,8 +458,11 @@ namespace vcg ext_hedges[0]->HVp()->VHp() = NULL; ext_hedges[1]->HVp()->VHp() = NULL; - Allocator::DeleteEdge( m, *( ext_hedges[0]->HEp()) ); - Allocator::DeleteEdge( m, *( ext_hedges[1]->HEp()) ); + if(HasHE) + { + Allocator::DeleteEdge( m, *( ext_hedges[0]->HEp()) ); + Allocator::DeleteEdge( m, *( ext_hedges[1]->HEp()) ); + } Allocator::DeleteHEdge( m, *( ext_hedges[0]) ); Allocator::DeleteHEdge( m, *( ext_hedges[1]) ); @@ -462,16 +481,17 @@ namespace vcg * * \return Pointer to the rotated edge */ - static EdgePointer edge_rotate(MeshType &m, EdgePointer ep, bool cw) + static HEdgePointer edge_rotate(HEdgePointer hp, bool cw) { - assert( MeshType::EdgeType::HasEHAdjacency() ); assert( MeshType::HEdgeType::HasHFAdjacency() ); assert( MeshType::HEdgeType::HasHOppAdjacency() ); assert( MeshType::FaceType::HasFHAdjacency() ); - FacePointer fp1 = ep->EHp()->HFp(); - FacePointer fp2 = ep->EHp()->HOp()->HFp(); + + FacePointer fp1 = hp->HFp(); + FacePointer fp2 = hp->HOp()->HFp(); + assert( fp1 ); assert( fp1->VN() == 4 ); @@ -492,8 +512,9 @@ namespace vcg fps.push_back(fp1); fps.push_back(fp2); - hps.push_back( getHEdges( fp1, ep->EHp() ) ); - hps.push_back( getHEdges( fp2, ep->EHp()->HOp() ) ); + + hps.push_back( getHEdges( fp1, hp ) ); + hps.push_back( getHEdges( fp2, hp->HOp() ) ); for(int i=0; i< 2; i++) @@ -541,7 +562,7 @@ namespace vcg } - return ep; + return hp; } @@ -621,49 +642,47 @@ namespace vcg * * \return Pointer to the other vertex belonging to the collapsed edge */ - static VertexPointer edge_collapse(MeshType &m, EdgePointer ep, VertexPointer vp) + static VertexPointer edge_collapse(MeshType &m, HEdgePointer hp, VertexPointer vp) { - assert(MeshType::EdgeType::HasEHAdjacency()); assert(MeshType::VertexType::HasVHAdjacency()); assert(MeshType::HEdgeType::HasHOppAdjacency()); assert(MeshType::HEdgeType::HasHVAdjacency()); assert(MeshType::HEdgeType::HasHPrevAdjacency()); - if( ep->EHp()->HFp() ) - assert(ep->EHp()->HFp()->VN() > 3); + if( hp->HFp() ) + assert(hp->HFp()->VN() > 3); - if( ep->EHp()->HOp()->HFp()) - assert(ep->EHp()->HOp()->HFp()->VN() > 3); + if( hp->HOp()->HFp()) + assert(hp->HOp()->HFp()->VN() > 3); - assert(ep->EHp()->HFp() || ep->EHp()->HOp()->HFp()); - assert(ep->EHp()->HVp() == vp || ep->EHp()->HOp()->HVp() == vp); + assert(hp->HFp() || hp->HOp()->HFp()); + assert(hp->HVp() == vp || hp->HOp()->HVp() == vp); - HEdgePointer he = ep->EHp(); - HEdgePointer hopp = he->HOp(); + HEdgePointer hopp = hp->HOp(); VertexPointer vp1; - if( he->HVp() == vp ) + if( hp->HVp() == vp ) vp1 = hopp->HVp(); else - vp1 = he->HVp(); + vp1 = hp->HVp(); change_vertex( vp, vp1); //HP - he->HNp()->HPp() = he->HPp(); + hp->HNp()->HPp() = hp->HPp(); hopp->HNp()->HPp() = hopp->HPp(); //HN - he->HPp()->HNp() = he->HNp(); + hp->HPp()->HNp() = hp->HNp(); hopp->HPp()->HNp() = hopp->HNp(); //FH - if( he->HFp() ) - if( he->HFp()->FHp() == he ) - he->HFp()->FHp() = he->HNp(); + if( hp->HFp() ) + if( hp->HFp()->FHp() == hp ) + hp->HFp()->FHp() = hp->HNp(); if( hopp->HFp() ) if( hopp->HFp()->FHp() == hopp ) @@ -673,8 +692,9 @@ namespace vcg if( vp1->VHp() == hopp ) vp1->VHp() = hopp->HNp(); - Allocator::DeleteEdge(m,*ep); - Allocator::DeleteHEdge(m,*he); + if(HasHEAdjacency(m)) + Allocator::DeleteEdge(m,*(hp->HEp())); + Allocator::DeleteHEdge(m,*hp); Allocator::DeleteHEdge(m,*hopp); Allocator::DeleteVertex(m,*vp); @@ -694,9 +714,7 @@ namespace vcg { assert(MeshType::VertexType::HasVHAdjacency()); - assert(MeshType::EdgeType::HasEHAdjacency()); assert(MeshType::HEdgeType::HasHVAdjacency()); - assert(MeshType::HEdgeType::HasHEAdjacency()); assert(MeshType::HEdgeType::HasHFAdjacency()); assert(MeshType::HEdgeType::HasHOppAdjacency()); assert(MeshType::HEdgeType::HasHPrevAdjacency()); @@ -736,10 +754,8 @@ namespace vcg { assert(MeshType::VertexType::HasVHAdjacency()); - assert(MeshType::EdgeType::HasEHAdjacency()); assert(MeshType::FaceType::HasFHAdjacency()); assert(MeshType::HEdgeType::HasHVAdjacency()); - assert(MeshType::HEdgeType::HasHEAdjacency()); assert(MeshType::HEdgeType::HasHFAdjacency()); assert(MeshType::HEdgeType::HasHOppAdjacency()); assert(MeshType::HEdgeType::HasHPrevAdjacency()); @@ -795,9 +811,7 @@ namespace vcg { assert(MeshType::VertexType::HasVHAdjacency()); - assert(MeshType::EdgeType::HasEHAdjacency()); assert(MeshType::HEdgeType::HasHVAdjacency()); - assert(MeshType::HEdgeType::HasHEAdjacency()); assert(MeshType::HEdgeType::HasHFAdjacency()); assert(MeshType::HEdgeType::HasHOppAdjacency()); assert(MeshType::HEdgeType::HasHPrevAdjacency()); @@ -812,6 +826,9 @@ namespace vcg // assert( count(vps.begin(), vps.end(), vps[i]) == 1 ); // } + bool HasHE = MeshType::HEdgeType::HasHEAdjacency(); + bool HasEH = MeshType::EdgeType::HasEHAdjacency(); + HEdgeIterator hi; std::vector gphps; @@ -849,9 +866,12 @@ namespace vcg { fp->SetD(); - ei = Allocator::AddEdges(m,edge_n); - for(EdgeIterator ei1 = ei; ei1 != m.edge.end(); ++ei1) - (*ei1).SetD(); + if(HasEH || HasHE) + { + ei = Allocator::AddEdges(m,edge_n); + for(EdgeIterator ei1 = ei; ei1 != m.edge.end(); ++ei1) + (*ei1).SetD(); + } typename Allocator::template PointerUpdater pu; @@ -889,14 +909,20 @@ namespace vcg ++hi2; - for(EdgeIterator ei1 = ei; ei1 != m.edge.end(); ++ei1, ++hi1, ++hi2) + EdgeIterator ei1 = ei; + + for(; hi2 != m.hedge.end(); ++hi1, ++hi2) { // EH - (*ei1).EHp() = &(*hi1); + if(HasEH) + (*ei1).EHp() = &(*hi1); // HE - (*hi1).HEp() = &(*ei1); - (*hi2).HEp() = &(*ei1); + if(HasHE) + { + (*hi1).HEp() = &(*ei1); + (*hi2).HEp() = &(*ei1); + } //HO (*hi1).HOp() = &(*hi2); @@ -1117,7 +1143,9 @@ namespace vcg Allocator::DeleteHEdge( m, *hps[i] ); Allocator::DeleteHEdge( m, *(hps[i]->HOp()) ); - Allocator::DeleteEdge( m, *(hps[i]->HEp()) ); + + if(MeshType::HEdgeType::HasHEAdjacency()) + Allocator::DeleteEdge( m, *(hps[i]->HEp()) ); if( !hps[(i+size-1)%size]->HOp()->HFp() ) { @@ -1314,7 +1342,7 @@ namespace vcg * \retval true if diagonal can be collapsed * \retval false if diagonal cannot be collapsed */ - static bool can_collapse_diagonal(HEdgePointer hp) + static bool check_diagonal_collapse(HEdgePointer hp) { assert(hp); @@ -1324,38 +1352,21 @@ namespace vcg vector faces; - Pos p(hp); + HEdgePointer hopp = hp->HNp()->HNp(); + vector faces1 = get_incident_faces(hp->HVp(), hp); + vector faces2 = get_incident_faces(hp->HNp()->HNp()->HVp(), hopp); - p.FlipE(); - p.FlipF(); + faces.assign(faces1.begin()+1, faces1.end()); + faces.assign(faces2.begin()+1, faces2.end()); - while( p.HE() != hp ) - { - faces.push_back(p.F()); - - p.FlipE(); - p.FlipF(); - } - - HEdgePointer opp = hp->HNp()->HNp(); - - p.he = opp; - - p.FlipE(); - p.FlipF(); - - while( p.HE() != opp ) - { - faces.push_back(p.F()); - - p.FlipE(); - p.FlipF(); - } + // First check: unsigned int size = faces.size(); - int null_count = 0; + bool null_face = false; + + // if size <=2 check is ok if(size > 2) { for(unsigned int i = 0; i < size; i++) @@ -1364,15 +1375,45 @@ namespace vcg { if(faces[(i+1)%size] != NULL && faces[((i+size)-1)%size] != NULL ) { - if(null_count > 0) + if(null_face) return false; - else - null_count++; + + null_face=true; } } } } + // End of first check + + + // Second check + + sort (faces1.begin(), faces1.end()); + sort (faces2.begin(), faces2.end()); + + if( faces1[0] == NULL ) + faces1.erase(faces1.begin()); + + if( faces2[0] == NULL ) + faces2.erase(faces2.begin()); + + vector intersection(faces1.size()+faces2.size()); + typename vector::iterator it; + + it = set_intersection(faces1.begin(),faces1.end(), faces2.begin(), faces2.end(), intersection.begin()); + + intersection.erase(it,intersection.end()); + + size = intersection.size(); + + assert( size != 0); + + if(size != 1) + return false; + + // End of second check + return true; } @@ -1457,7 +1498,7 @@ namespace vcg /*! * Gets vertices on the 1-ring of a vertex * - * \param vp Vertex + * \param vp Vertex. It must be a non-border vertex. * * \return Vector containing vertices */ @@ -1495,8 +1536,9 @@ namespace vcg return ret; } + /*! - * Gets facees on the 1-ring of a vertex + * Gets faces on the 1-ring of a vertex * * \param vp Vertex * @@ -1521,6 +1563,7 @@ namespace vcg } + /*! * Checks if a face is a singlet *