/** * 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); } } } } } }
/** * Simplifies the mesh, merging the pairs of triangles that come frome the * same original face and define a quad. * @return true if a quad was added, false otherwise */ bool BOP_Merge::createQuads() { BOP_Faces quads; // Get mesh faces BOP_Faces faces = m_mesh->getFaces(); // Merge mesh triangles const BOP_IT_Faces facesIEnd = (faces.end()-1); const BOP_IT_Faces facesJEnd = faces.end(); for(BOP_IT_Faces faceI=faces.begin();faceI!=facesIEnd;faceI++) { if ((*faceI)->getTAG() == BROKEN || (*faceI)->size() != 3) continue; for(BOP_IT_Faces faceJ=(faceI+1);faceJ!=facesJEnd;faceJ++) { if ((*faceJ)->getTAG() == BROKEN || (*faceJ)->size() != 3 || (*faceJ)->getOriginalFace() != (*faceI)->getOriginalFace()) continue; // Test if both triangles share a vertex index BOP_Index v; bool found = false; for(unsigned int i=0;i<3 && !found;i++) { v = (*faceI)->getVertex(i); found = (*faceJ)->containsVertex(v); } if (!found) continue; BOP_Face *faceK = createQuad((BOP_Face3*)*faceI,(BOP_Face3*)*faceJ,v); if (faceK != NULL) { // Set triangles to BROKEN (*faceI)->setTAG(BROKEN); (*faceJ)->setTAG(BROKEN); quads.push_back(faceK); break; } } } // Add quads to mesh const BOP_IT_Faces quadsEnd = quads.end(); for(BOP_IT_Faces quad=quads.begin();quad!=quadsEnd;quad++) m_mesh->addFace(*quad); return (quads.size() > 0); }
/** * Simplifies the mesh, merging the pairs of triangles that come frome the * same original face and define a quad. * @return true if a quad was added, false otherwise */ bool BOP_Merge2::createQuads() { BOP_Faces quads; // Get mesh faces BOP_Faces faces = m_mesh->getFaces(); // Merge mesh triangles const BOP_IT_Faces facesIEnd = (faces.end()-1); const BOP_IT_Faces facesJEnd = faces.end(); for(BOP_IT_Faces faceI=faces.begin();faceI!=facesIEnd;faceI++) { #ifdef OLD_QUAD if ((*faceI)->getTAG() == BROKEN || (*faceI)->size() != 3) continue; for(BOP_IT_Faces faceJ=(faceI+1);faceJ!=facesJEnd;faceJ++) { if ((*faceJ)->getTAG() == BROKEN || (*faceJ)->size() != 3 || (*faceJ)->getOriginalFace() != (*faceI)->getOriginalFace()) continue; BOP_Face *faceK = createQuad((BOP_Face3*)*faceI,(BOP_Face3*)*faceJ); if (faceK != NULL) { // Set triangles to BROKEN deleteFace(m_mesh, *faceI); deleteFace(m_mesh, *faceJ); #ifdef BOP_DEBUG cout << "createQuad: del " << *faceI << endl; cout << "createQuad: del " << *faceJ << endl; cout << "createQuad: add " << faceK << endl; #endif quads.push_back(faceK); break; } } #else if ((*faceI)->getTAG() == BROKEN ) continue; for(BOP_IT_Faces faceJ=(faceI+1);faceJ!=facesJEnd;faceJ++) { if ((*faceJ)->getTAG() == BROKEN || (*faceJ)->getOriginalFace() != (*faceI)->getOriginalFace()) continue; BOP_Face *faceK = NULL; if((*faceI)->size() == 3) { if((*faceJ)->size() == 3) faceK = createQuad((BOP_Face3*)*faceI,(BOP_Face3*)*faceJ); else faceK = createQuad((BOP_Face3*)*faceI,(BOP_Face4*)*faceJ); } else { if((*faceJ)->size() == 3) faceK = createQuad((BOP_Face3*)*faceJ,(BOP_Face4*)*faceI); else faceK = createQuad((BOP_Face4*)*faceI,(BOP_Face4*)*faceJ); } if (faceK != NULL) { // Set triangles to BROKEN deleteFace(m_mesh, *faceI); deleteFace(m_mesh, *faceJ); #ifdef BOP_DEBUG cout << "createQuad: del " << *faceI << endl; cout << "createQuad: del " << *faceJ << endl; cout << "createQuad: add " << faceK << endl; #endif quads.push_back(faceK); break; } } #endif } // Add quads to mesh const BOP_IT_Faces quadsEnd = quads.end(); for(BOP_IT_Faces quad=quads.begin();quad!=quadsEnd;quad++) m_mesh->addFace(*quad); return (quads.size() > 0); }
/** * Merge a set of faces removing the vertex index v. * @param faces set of faces * @param oldFaces set of old faces obtained from the merge * @param newFaces set of new faces obtained from the merge * @param vertices sequence of indexs (v1 ... vi = v ... vn) where : * v is the current vertex to test, * vj (j < i) are tested vertices, * vk (k >= i) are vertices required to test to merge vj * (so if a vertex vk can't be merged, the merge is not possible). * @param v vertex index * @return true if the merge is succesful, false otherwise */ bool BOP_Merge::mergeFaces(BOP_Faces &faces, BOP_Faces &oldFaces, BOP_Faces &newFaces, BOP_Indexs &vertices, BOP_Index v) { bool merged = false; if (faces.size() == 2) { // Merge a pair of faces into a new face without v BOP_Face *faceI = faces[0]; BOP_Face *faceJ = faces[1]; BOP_Face *faceK = mergeFaces(faceI,faceJ,vertices,v); if (faceK != NULL) { newFaces.push_back(faceK); oldFaces.push_back(faceI); oldFaces.push_back(faceJ); merged = true; } else merged = false; } else if (faces.size() == 4) { // Merge two pair of faces into a new pair without v // First we try to perform a simplify merge to avoid more pending vertices // (for example, if we have two triangles and two quads it will be better // to do 3+4 and 3+4 than 3+3 and 4+4) BOP_Face *oldFace1 = faces[0]; BOP_Face *oldFace2, *newFace1; unsigned int indexJ = 1; while (indexJ < faces.size() && !merged) { oldFace2 = faces[indexJ]; newFace1 = mergeFaces(oldFace1,oldFace2,v); if (newFace1 != NULL) merged = true; else indexJ++; } if (merged) { // Merge the other pair of faces unsigned int indexK, indexL; if (indexJ == 1) {indexK = 2;indexL = 3;} else if (indexJ == 2) {indexK = 1;indexL = 3;} else {indexK = 1;indexL = 2;} BOP_Face *oldFace3 = faces[indexK]; BOP_Face *oldFace4 = faces[indexL]; unsigned int oldSize = vertices.size(); BOP_Face *newFace2 = mergeFaces(oldFace3,oldFace4,vertices,v); if (newFace2 != NULL) { newFaces.push_back(newFace1); newFaces.push_back(newFace2); oldFaces.push_back(oldFace1); oldFaces.push_back(oldFace2); oldFaces.push_back(oldFace3); oldFaces.push_back(oldFace4); merged = true; } else { // Undo all changes delete newFace1; merged = false; unsigned int count = vertices.size() - oldSize; if (count != 0) vertices.erase(vertices.end() - count, vertices.end()); } } if (!merged) { // Try a complete merge merged = true; while (faces.size()>0 && merged) { indexJ = 1; BOP_Face *faceI = faces[0]; merged = false; while (indexJ < faces.size()) { BOP_Face *faceJ = faces[indexJ]; BOP_Face *faceK = mergeFaces(faceI,faceJ,vertices,v); if (faceK != NULL) { // faceK = faceI + faceJ and it does not include v! faces.erase(faces.begin()+indexJ,faces.begin()+(indexJ+1)); faces.erase(faces.begin(),faces.begin()+1); newFaces.push_back(faceK); oldFaces.push_back(faceI); oldFaces.push_back(faceJ); merged = true; break; } else indexJ++; } } } } else merged = false; // there are N=1 or N=3 or N>4 faces! // Return merge result return merged; }