/** * Creates a list of lists L1, L2, ... LN where * LX = mesh faces with vertex v that come from the same original face * and without any of the vertices that appear before v in vertices * @param facesByOriginalFace list of faces lists * @param vertices vector with vertices indexs that contains v * @param v vertex index */ void BOP_Merge2::getFaces(BOP_LFaces &facesByOriginalFace, BOP_Indexs vertices, BOP_Index v) { // Get edges with vertex v BOP_Indexs edgeIndexs = m_mesh->getVertex(v)->getEdges(); const BOP_IT_Indexs edgeEnd = edgeIndexs.end(); for(BOP_IT_Indexs edgeIndex = edgeIndexs.begin();edgeIndex != edgeEnd;edgeIndex++) { // Foreach edge, add its no broken faces to the output list BOP_Edge* edge = m_mesh->getEdge(*edgeIndex); BOP_Indexs faceIndexs = edge->getFaces(); const BOP_IT_Indexs faceEnd = faceIndexs.end(); for(BOP_IT_Indexs faceIndex=faceIndexs.begin();faceIndex!=faceEnd;faceIndex++) { BOP_Face* face = m_mesh->getFace(*faceIndex); if (face->getTAG() != BROKEN) { // Search if the face contains any of the forbidden vertices bool found = false; for(BOP_IT_Indexs vertex = vertices.begin();*vertex!= v;vertex++) { if (face->containsVertex(*vertex)) { // face contains a forbidden vertex! found = true; break; } } if (!found) { // Search if we already have created a list with the // faces that come from the same original face const BOP_IT_LFaces lfEnd = facesByOriginalFace.end(); for(BOP_IT_LFaces facesByOriginalFaceX=facesByOriginalFace.begin(); facesByOriginalFaceX!=lfEnd; facesByOriginalFaceX++) { if (((*facesByOriginalFaceX)[0])->getOriginalFace() == face->getOriginalFace()) { // Search that the face has not been added to the list before for(unsigned int i = 0;i<(*facesByOriginalFaceX).size();i++) { if ((*facesByOriginalFaceX)[i] == face) { found = true; break; } } if (!found) { // Add face to the list if (face->getTAG()==OVERLAPPED) facesByOriginalFaceX->insert(facesByOriginalFaceX->begin(),face); else facesByOriginalFaceX->push_back(face); found = true; } break; } } if (!found) { // Create a new list and add the current face BOP_Faces facesByOriginalFaceX; facesByOriginalFaceX.push_back(face); facesByOriginalFace.push_back(facesByOriginalFaceX); } } } } } }
/** * Returns the first edge with the specified vertex index from a list of edge indexs. * @param edges edge indexs * @param v vertex index * @return first edge with the specified vertex index, NULL otherwise */ BOP_Edge* BOP_Mesh::getEdge(BOP_Indexs edges, BOP_Index v) { const BOP_IT_Indexs edgesEnd = edges.end(); for(BOP_IT_Indexs it=edges.begin();it!=edgesEnd;it++){ BOP_Edge *edge = m_edges[*it]; if ((edge->getVertex1() == v) || (edge->getVertex2() == v)) return edge; } return NULL; }
/** * testMesh */ void BOP_Mesh::testMesh() { BOP_Face* cares[10]; unsigned int nedges=0,i; for(i=0;i<m_edges.size();i++) { BOP_Edge *edge = m_edges[i]; BOP_Indexs faces = edge->getFaces(); unsigned int count = 0; const BOP_IT_Indexs facesEnd = faces.end(); for(BOP_IT_Indexs it = faces.begin();it!=facesEnd;it++) { if (m_faces[*it]->getTAG()!=BROKEN) { cares[count] = m_faces[*it]; count++; } } if ((count%2)!=0) nedges++; } if (nedges) cout << nedges << " wrong edges." << endl; else cout << "well edges." << endl; unsigned int duplFaces = 0; unsigned int wrongFaces = 0; for(i=0;i<m_faces.size();i++){ BOP_Face *faceI = m_faces[i]; if (faceI->getTAG()==BROKEN) continue; if (testFace(faceI)){ wrongFaces++; cout << "Wrong Face: " << faceI << endl; } for(unsigned int j=i+1;j<m_faces.size();j++){ BOP_Face *faceJ = m_faces[j]; if (faceJ->getTAG()==BROKEN) continue; if (testFaces(faceI,faceJ)){ duplFaces++; cout << "Duplicate FaceI: " << faceI << endl; cout << "Duplicate FaceJ: " << faceJ << endl; } } } cout << duplFaces << " duplicate faces." << endl; cout << wrongFaces << " wrong faces." << endl; }
/** * remove edges from vertices when the vertex is removed */ void BOP_Merge2::freeVerts(BOP_Index v, BOP_Vertex *vert) { BOP_Indexs edges = vert->getEdges(); BOP_Vertex *other; for( BOP_IT_Indexs it = edges.begin(); it != edges.end(); ++it) { BOP_Edge *edge = m_mesh->getEdge(*it); BOP_Indexs edges2; if( edge->getVertex1() != v ) other = m_mesh->getVertex( edge->getVertex1() ); else other = m_mesh->getVertex( edge->getVertex2() ); other->removeEdge(*it); vert->removeEdge(*it); } }
bool BOP_Mesh::isClosedMesh() { for(unsigned int i=0; i<m_edges.size(); i++) { BOP_Edge *edge = m_edges[i]; BOP_Indexs faces = edge->getFaces(); unsigned int count = 0; const BOP_IT_Indexs facesEnd = faces.end(); for(BOP_IT_Indexs it = faces.begin();it!=facesEnd;it++) { if (m_faces[*it]->getTAG()!=BROKEN) count++; } if ((count%2)!=0) return false; } return true; }
static void deleteFace(BOP_Mesh *m, BOP_Face *face) { BOP_Index l2 = face->getVertex(0); BOP_Faces faces = m->getFaces(); for(int i = face->size(); i-- ; ) { BOP_Indexs edges = m->getVertex(l2)->getEdges(); BOP_Index l1 = face->getVertex(i); for(BOP_IT_Indexs it1 = edges.begin(); it1 != edges.end(); ++it1 ) { BOP_Edge *edge = m->getEdge(*it1); if( ( edge->getVertex1() == l1 && edge->getVertex2() == l2 ) || ( edge->getVertex1() == l2 && edge->getVertex2() == l1 ) ) { BOP_Indexs ef = edge->getFaces(); for(BOP_IT_Indexs it = ef.begin(); it != ef.end(); ++it ) { if( m->getFace(*it) == face) { edge->removeFace(*it); break; } } break; } } l2 = l1; } face->setTAG(BROKEN); }
/** * testEdges */ bool BOP_Mesh::testEdges(BOP_Faces *facesObj) { for(unsigned int i=0;i<m_edges.size();i++) { BOP_Edge *edge = m_edges[i]; BOP_Indexs faces = edge->getFaces(); unsigned int count = 0; const BOP_IT_Indexs facesEnd = faces.end(); for(BOP_IT_Indexs it = faces.begin();it!=facesEnd;it++) { if ((m_faces[*it]->getTAG()!=BROKEN) && containsFace(facesObj,m_faces[*it])) count++; } if ((count%2)!=0) { return false; } } return true; }
/** * Simplifies a mesh, merging the faces with the specified vertices. * @param mergeVertices vertices to test * @return true if a face merge was performed */ bool BOP_Merge2::mergeFaces(BOP_Indexs &mergeVertices) { // Check size > 0! if (mergeVertices.size() == 0) return false; bool didMerge = false; for( BOP_Index i = 0; i < mergeVertices.size(); ++i ) { BOP_LFaces facesByOriginalFace; BOP_Index v = mergeVertices[i]; BOP_Vertex *vert = m_mesh->getVertex(v); #ifdef BOP_DEBUG cout << "i = " << i << ", v = " << v << ", vert = " << vert << endl; if (v==48) cout << "found vert 48" << endl; #endif if ( vert->getTAG() != BROKEN ) { getFaces(facesByOriginalFace,v); switch (facesByOriginalFace.size()) { case 0: // v has no unbroken faces (so it's a new BROKEN vertex) freeVerts( v, vert ); vert->setTAG(BROKEN); break; case 2: { #ifdef BOP_DEBUG cout << "size of fBOF = " << facesByOriginalFace.size() << endl; #endif BOP_Faces ff = facesByOriginalFace.front(); BOP_Faces fb = facesByOriginalFace.back(); BOP_Index eindexs[2]; int ecount = 0; // look for two edges adjacent to v which contain both ofaces BOP_Indexs edges = vert->getEdges(); #ifdef BOP_DEBUG cout << " ff has " << ff.size() << " faces" << endl; cout << " fb has " << fb.size() << " faces" << endl; cout << " v has " << edges.size() << " edges" << endl; #endif for(BOP_IT_Indexs it = edges.begin(); it != edges.end(); ++it ) { BOP_Edge *edge = m_mesh->getEdge(*it); BOP_Indexs faces = edge->getFaces(); #ifdef BOP_DEBUG cout << " " << edge << " has " << edge->getFaces().size() << " faces" << endl; #endif if( faces.size() == 2 ) { BOP_Face *f0 = m_mesh->getFace(faces[0]); BOP_Face *f1 = m_mesh->getFace(faces[1]); if( f0->getOriginalFace() != f1->getOriginalFace() ) { #ifdef BOP_DEBUG cout << " " << f0 << endl; cout << " " << f1 << endl; #endif eindexs[ecount++] = (*it); } } } if(ecount == 2) { #ifdef BOP_DEBUG cout << " edge indexes are " << eindexs[0]; cout << " and " << eindexs[1] << endl; #endif BOP_Edge *edge = m_mesh->getEdge(eindexs[0]); BOP_Index N = edge->getVertex1(); if(N == v) N = edge->getVertex2(); #ifdef BOP_DEBUG cout << " ## OK, replace "<<v<<" with "<<N << endl; #endif mergeVertex(ff , v, N ); mergeVertex(fb , v, N ); // now remove v and its edges vert->setTAG(BROKEN); for(BOP_IT_Indexs it = edges.begin(); it != edges.end(); ++it ) { BOP_Edge *tedge = m_mesh->getEdge(*it); tedge->setUsed(false); } didMerge = true; } #ifdef BOP_DEBUG else { cout << " HUH: ecount was " << ecount << endl; } #endif } break; default: break; } } } return didMerge; }
void clean_nonmanifold( BOP_Mesh *m ) { return; BOP_Edges nme; BOP_Edges e = m->getEdges(); for( BOP_IT_Edges it = e.begin(); it != e.end(); ++it ) { BOP_Indexs faces = (*it)->getFaces(); if( faces.size() & ~2 ) nme.push_back(*it); } if (nme.size() == 0) return; for( BOP_IT_Edges it = nme.begin(); it != nme.end(); ++it ) { if( (*it)->getFaces().size() > 1 ) { BOP_Indexs faces = (*it)->getFaces(); for( BOP_IT_Indexs face = faces.begin(); face != faces.end(); ++face ) { MT_Point3 vertex1 = m->getVertex(m->getFace(*face)->getVertex(0))->getPoint(); MT_Point3 vertex2 = m->getVertex(m->getFace(*face)->getVertex(1))->getPoint(); MT_Point3 vertex3 = m->getVertex(m->getFace(*face)->getVertex(2))->getPoint(); if (BOP_collinear(vertex1,vertex2,vertex3)) // collinear triangle deleteFace(m,m->getFace(*face)); } continue; } BOP_Face *oface1 = m->getFace((*it)->getFaces().front()); BOP_Face *oface2, *tmpface; BOP_Index first =(*it)->getVertex1(); BOP_Index next =(*it)->getVertex2(); BOP_Index last = first; unsigned short facecount = 0; bool found = false; BOP_Indexs vertList; #ifdef BOP_DEBUG cout << " first edge is " << (*it) << endl; #endif vertList.push_back(first); BOP_Edge *edge; while(true) { BOP_Vertex *vert = m->getVertex(next); BOP_Indexs edges = vert->getEdges(); edge = NULL; for( BOP_IT_Indexs eit = edges.begin(); eit != edges.end(); ++eit) { edge = m->getEdge(*eit); if( edge->getFaces().size() > 1) { edge = NULL; continue; } if( edge->getVertex1() == next && edge->getVertex2() != last ) { last = next; next = edge->getVertex2(); break; } if( edge->getVertex2() == next && edge->getVertex1() != last ) { last = next; next = edge->getVertex1(); break; } edge = NULL; } if( !edge ) break; #ifdef BOP_DEBUG cout << " next edge is " << edge << endl; #endif tmpface = m->getFace(edge->getFaces().front()); if( oface1->getOriginalFace() != tmpface->getOriginalFace() ) oface2 = tmpface; else ++facecount; vertList.push_back(last); if( vertList.size() > 3 ) break; if( next == first ) { found = true; break; } } if(found) { edge = *it; #ifdef BOP_DEBUG cout << " --> found a loop" << endl; #endif if( vertList.size() == 3 ) { BOP_Face3 *face = (BOP_Face3 *)m->getFace(edge->getFaces().front()); face->getNeighbours(first,last,next); } else if( vertList.size() == 4 ) { BOP_Face4 *face = (BOP_Face4 *)m->getFace(edge->getFaces().front()); face->getNeighbours(first,last,next,last); } else { #ifdef BOP_DEBUG cout << "loop has " << vertList.size() << "verts"; #endif continue; } if(facecount == 1) oface1 = oface2; next = vertList[1]; last = vertList[2]; if( edge->getVertex2() == next ) { BOP_Face3 *f = new BOP_Face3(next,first,last, oface1->getPlane(),oface1->getOriginalFace()); m->addFace( f ); #ifdef BOP_DEBUG cout << " face is backward: " << f << endl; #endif } else { BOP_Face3 *f = new BOP_Face3(last,first,next, oface1->getPlane(),oface1->getOriginalFace()); m->addFace( f ); #ifdef BOP_DEBUG cout << " face is forward: " << f << endl; #endif } } } }
/** * Triangulates the input face according to the specified segment. * @param mesh mesh that contains the faces, edges and vertices * @param faces set of faces that contains the original face and the new triangulated faces * @param face face to be triangulated * @param s segment used to triangulate face */ void triangulate(BOP_Mesh *mesh, BOP_Faces *faces, BOP_Face *face, BOP_Segment s) { if (BOP_Segment::isUndefined(s.m_cfg1)) { // Nothing to do } else if (BOP_Segment::isVertex(s.m_cfg1)) { // VERTEX(v1) + VERTEX(v2) => nothing to do } else if (BOP_Segment::isEdge(s.m_cfg1)) { if (BOP_Segment::isVertex(s.m_cfg2) || BOP_Segment::isUndefined(s.m_cfg2)) { // EDGE(v1) + VERTEX(v2) BOP_Edge *edge = mesh->getEdge(face,BOP_Segment::getEdge(s.m_cfg1)); BOP_triangulateA(mesh,faces,face,s.m_v1,BOP_Segment::getEdge(s.m_cfg1)); BOP_Face *opposite = BOP_getOppositeFace(mesh,faces,face,edge); if (opposite != NULL) { unsigned int e; opposite->getEdgeIndex(edge->getVertex1(), edge->getVertex2(),e); BOP_triangulateA(mesh, faces, opposite, s.m_v1, e); } } else { // EDGE(v1) + EDGE(v2) if (BOP_Segment::getEdge(s.m_cfg1) == BOP_Segment::getEdge(s.m_cfg2)) { // EDGE(v1) == EDGE(v2) BOP_Edge *edge = mesh->getEdge(face,BOP_Segment::getEdge(s.m_cfg1)); BOP_triangulateD(mesh, faces, face, s.m_v1, s.m_v2, BOP_Segment::getEdge(s.m_cfg1)); BOP_Face *opposite = BOP_getOppositeFace(mesh,faces,face,edge); if (opposite != NULL) { unsigned int e; opposite->getEdgeIndex(edge->getVertex1(), edge->getVertex2(),e); BOP_triangulateD(mesh, faces, opposite, s.m_v1, s.m_v2, e); } } else { // EDGE(v1) != EDGE(v2) BOP_Edge *edge1 = mesh->getEdge(face,BOP_Segment::getEdge(s.m_cfg1)); BOP_Edge *edge2 = mesh->getEdge(face,BOP_Segment::getEdge(s.m_cfg2)); BOP_triangulateE(mesh, faces, face, s.m_v1, s.m_v2, BOP_Segment::getEdge(s.m_cfg1), BOP_Segment::getEdge(s.m_cfg2)); BOP_Face *opposite = BOP_getOppositeFace(mesh,faces,face,edge1); if (opposite != NULL) { unsigned int e; opposite->getEdgeIndex(edge1->getVertex1(), edge1->getVertex2(),e); BOP_triangulateA(mesh, faces, opposite, s.m_v1, e); } opposite = BOP_getOppositeFace(mesh,faces,face,edge2); if (opposite != NULL) { unsigned int e; opposite->getEdgeIndex(edge2->getVertex1(), edge2->getVertex2(),e); BOP_triangulateA(mesh, faces, opposite, s.m_v2, e); } } } } else if (BOP_Segment::isIn(s.m_cfg1)) { if (BOP_Segment::isVertex(s.m_cfg2) || BOP_Segment::isUndefined(s.m_cfg2)) { // IN(v1) + VERTEX(v2) BOP_triangulateB(mesh,faces,face,s.m_v1); } else if (BOP_Segment::isEdge(s.m_cfg2)) { // IN(v1) + EDGE(v2) BOP_Edge *edge = mesh->getEdge(face,BOP_Segment::getEdge(s.m_cfg2)); BOP_triangulateF(mesh,faces,face,s.m_v1,s.m_v2,BOP_Segment::getEdge(s.m_cfg2)); BOP_Face *opposite = BOP_getOppositeFace(mesh,faces,face,edge); if (opposite != NULL) { unsigned int e; opposite->getEdgeIndex(edge->getVertex1(), edge->getVertex2(),e); BOP_triangulateA(mesh, faces, opposite, s.m_v2, e); } } else // IN(v1) + IN(v2) BOP_triangulateC(mesh,faces,face,s.m_v1,s.m_v2); } }
/** * Replaces a vertex index. * @param oldIndex old vertex index * @param newIndex new vertex index */ BOP_Index BOP_Mesh::replaceVertexIndex(BOP_Index oldIndex, BOP_Index newIndex) { BOP_IT_Indexs oldEdgeIndex; if (oldIndex==newIndex) return newIndex; // Update faces, edges and vertices BOP_Vertex *oldVertex = m_vertexs[oldIndex]; BOP_Vertex *newVertex = m_vertexs[newIndex]; BOP_Indexs oldEdges = oldVertex->getEdges(); // Update faces to the newIndex BOP_IT_Indexs oldEdgesEnd = oldEdges.end(); for(oldEdgeIndex=oldEdges.begin();oldEdgeIndex!=oldEdgesEnd; oldEdgeIndex++) { BOP_Edge *edge = m_edges[*oldEdgeIndex]; if ((edge->getVertex1()==oldIndex && edge->getVertex2()==newIndex) || (edge->getVertex2()==oldIndex && edge->getVertex1()==newIndex)) { // Remove old edge ==> set edge faces to BROKEN removeBrokenFaces( edge, this ); oldVertex->removeEdge(*oldEdgeIndex); newVertex->removeEdge(*oldEdgeIndex); } else { BOP_Indexs faces = edge->getFaces(); const BOP_IT_Indexs facesEnd = faces.end(); for(BOP_IT_Indexs face=faces.begin();face!=facesEnd;face++) { if (m_faces[*face]->getTAG()!=BROKEN) m_faces[*face]->replaceVertexIndex(oldIndex,newIndex); } } } oldEdgesEnd = oldEdges.end(); for(oldEdgeIndex=oldEdges.begin();oldEdgeIndex!=oldEdgesEnd; oldEdgeIndex++) { BOP_Edge * edge = m_edges[*oldEdgeIndex]; BOP_Edge * edge2; BOP_Index v1 = edge->getVertex1(); v1 = (v1==oldIndex?edge->getVertex2():v1); if ((edge2 = getEdge(newIndex,v1)) == NULL) { edge->replaceVertexIndex(oldIndex,newIndex); if ( edge->getVertex1() == edge->getVertex2() ) { removeBrokenFaces( edge, this ); oldVertex->removeEdge(*oldEdgeIndex); } #ifdef HASH rehashVertex(oldIndex,newIndex,v1); #endif newVertex->addEdge(*oldEdgeIndex); } else { BOP_Indexs faces = edge->getFaces(); const BOP_IT_Indexs facesEnd = faces.end(); for(BOP_IT_Indexs f=faces.begin();f!=facesEnd;f++) { if (m_faces[*f]->getTAG()!=BROKEN) edge2->addFace(*f); } BOP_Vertex *oppositeVertex = m_vertexs[v1]; oppositeVertex->removeEdge(*oldEdgeIndex); edge->replaceVertexIndex(oldIndex,newIndex); if ( edge->getVertex1() == edge->getVertex2() ) { removeBrokenFaces( edge, this ); oldVertex->removeEdge(*oldEdgeIndex); newVertex->removeEdge(*oldEdgeIndex); } #ifdef HASH rehashVertex(oldIndex,newIndex,v1); #endif } } oldVertex->setTAG(BROKEN); return newIndex; }