/** * Returns a new quad (convex) from the merge of two triangles that share the * vertex index v. * @param faceI mesh triangle * @param faceJ mesh triangle * @param v vertex index shared by both triangles * @return a new convex quad if the merge is possible */ BOP_Face* BOP_Merge::createQuad(BOP_Face3 *faceI, BOP_Face3 *faceJ, BOP_Index v) { BOP_Face *faceK = NULL; // Get faces data BOP_Index prevI, nextI, prevJ, nextJ; faceI->getNeighbours(v,prevI,nextI); faceJ->getNeighbours(v,prevJ,nextJ); MT_Point3 vertex = m_mesh->getVertex(v)->getPoint(); MT_Point3 vPrevI = m_mesh->getVertex(prevI)->getPoint(); MT_Point3 vNextI = m_mesh->getVertex(nextI)->getPoint(); MT_Point3 vPrevJ = m_mesh->getVertex(prevJ)->getPoint(); MT_Point3 vNextJ = m_mesh->getVertex(nextJ)->getPoint(); // Quad test if (prevI == nextJ) { if (!BOP_collinear(vNextI,vertex,vPrevJ) && !BOP_collinear(vNextI,vPrevI,vPrevJ) && BOP_convex(vertex,vNextI,vPrevI,vPrevJ)) { faceK = new BOP_Face4(v,nextI,prevI,prevJ,faceI->getPlane(),faceI->getOriginalFace()); faceK->setTAG(faceI->getTAG()); } } else if (nextI == prevJ) { if (!BOP_collinear(vPrevI,vertex,vNextJ) && !BOP_collinear(vPrevI,vNextI,vNextJ) && BOP_convex(vertex,vNextJ,vNextI,vPrevI)) { faceK = new BOP_Face4(v,nextJ,nextI,prevI,faceI->getPlane(),faceI->getOriginalFace()); faceK->setTAG(faceI->getTAG()); } } return faceK; }
/** * Returns a new face (quad or triangle) from the merge of one quad and one * triangle that share the vertex v and come from the same original face. * @param faceI mesh quad * @param faceJ mesh triangle * @param pending vector with pending vertices (required to merge one quad * and one triangle into a new triangle; it supposes to remove two vertexs, * v and its neighbour, that will be a new pending vertex if it wasn't) * @param v vertex index shared by both faces * @return If the merge is possible, a new face without v */ BOP_Face* BOP_Merge::mergeFaces(BOP_Face4 *faceI, BOP_Face3 *faceJ, BOP_Indexs &pending, BOP_Index v) { BOP_Face *faceK = NULL; // Get faces data BOP_Index prevI, nextI, opp, prevJ, nextJ; faceI->getNeighbours(v,prevI,nextI,opp); faceJ->getNeighbours(v,prevJ,nextJ); MT_Point3 vertex = m_mesh->getVertex(v)->getPoint(); MT_Point3 vOpp = m_mesh->getVertex(opp)->getPoint(); MT_Point3 vPrevI = m_mesh->getVertex(prevI)->getPoint(); MT_Point3 vNextI = m_mesh->getVertex(nextI)->getPoint(); MT_Point3 vPrevJ = m_mesh->getVertex(prevJ)->getPoint(); MT_Point3 vNextJ = m_mesh->getVertex(nextJ)->getPoint(); // Merge test if (prevI == nextJ) { if (BOP_between(vertex,vNextI,vPrevJ)) { if (!BOP_collinear(vPrevJ,vPrevI,vOpp) && BOP_convex(vOpp,vPrevI,vPrevJ,vNextI)) { // The result is a new quad faceK = new BOP_Face4(opp,prevI,prevJ,nextI,faceI->getPlane(),faceI->getOriginalFace()); faceK->setTAG(faceI->getTAG()); } else if (BOP_between(vPrevI,vPrevJ,vOpp)) { // The result is a triangle (only if prevI can be merged) if (prevI < m_firstVertex) return NULL; // It can't be merged faceK = new BOP_Face3(nextI,opp,prevJ,faceI->getPlane(),faceI->getOriginalFace()); faceK->setTAG(faceI->getTAG()); if (!containsIndex(pending, prevI)) pending.push_back(prevI); } } } else if (nextI == prevJ) { if (BOP_between(vertex,vPrevI,vNextJ)) { if (!BOP_collinear(vNextJ,vNextI,vOpp) && BOP_convex(vOpp,vPrevI,vNextJ,vNextI)) { // The result is a new quad faceK = new BOP_Face4(opp,prevI,nextJ,nextI,faceI->getPlane(),faceI->getOriginalFace()); faceK->setTAG(faceI->getTAG()); } else if (BOP_between(vNextI,vOpp,vNextJ)) { // The result is a triangle (only if nextI can be merged) if (nextI < m_firstVertex) return NULL; faceK = new BOP_Face3(prevI,nextJ,opp,faceI->getPlane(),faceI->getOriginalFace()); faceK->setTAG(faceI->getTAG()); if (!containsIndex(pending, nextI)) pending.push_back(nextI); } } } return faceK; }
/** * Returns a new quad (convex) from the merge of two triangles that share the * vertex index v. * @param faceI mesh triangle * @param faceJ mesh triangle * @param v vertex index shared by both triangles * @return a new convex quad if the merge is possible */ BOP_Face* BOP_Merge2::createQuad(BOP_Face3 *faceI, BOP_Face3 *faceJ) { // Test if both triangles share a vertex index BOP_Index v; unsigned int i; for(i=0;i<3 ;i++) { v = faceI->getVertex(i); if( faceJ->containsVertex(v) ) break; } if (i == 3) return NULL; BOP_Face *faceK = NULL; // Get faces data BOP_Index prevI, nextI, prevJ, nextJ; faceI->getNeighbours(v,prevI,nextI); faceJ->getNeighbours(v,prevJ,nextJ); MT_Point3 vertex = m_mesh->getVertex(v)->getPoint(); MT_Point3 vPrevI = m_mesh->getVertex(prevI)->getPoint(); MT_Point3 vNextI = m_mesh->getVertex(nextI)->getPoint(); MT_Point3 vPrevJ = m_mesh->getVertex(prevJ)->getPoint(); MT_Point3 vNextJ = m_mesh->getVertex(nextJ)->getPoint(); // Quad test if (prevI == nextJ) { if (!BOP_collinear(vNextI,vertex,vPrevJ) && !BOP_collinear(vNextI,vPrevI,vPrevJ) && BOP_convex(vertex,vNextI,vPrevI,vPrevJ)) { faceK = new BOP_Face4(v,nextI,prevI,prevJ,faceI->getPlane(),faceI->getOriginalFace()); faceK->setTAG(faceI->getTAG()); BOP_Index edge; m_mesh->getIndexEdge(v,prevI,edge); m_mesh->getVertex(v)->removeEdge(edge); m_mesh->getVertex(prevI)->removeEdge(edge); } } else if (nextI == prevJ) { if (!BOP_collinear(vPrevI,vertex,vNextJ) && !BOP_collinear(vPrevI,vNextI,vNextJ) && BOP_convex(vertex,vNextJ,vNextI,vPrevI)) { faceK = new BOP_Face4(v,nextJ,nextI,prevI,faceI->getPlane(),faceI->getOriginalFace()); faceK->setTAG(faceI->getTAG()); BOP_Index edge; m_mesh->getIndexEdge(v,nextI,edge); m_mesh->getVertex(v)->removeEdge(edge); m_mesh->getVertex(nextI)->removeEdge(edge); } } return faceK; }
/** * testPlane */ void BOP_Mesh::testPlane(BOP_Face *face) { MT_Plane3 plane1(m_vertexs[face->getVertex(0)]->getPoint(), m_vertexs[face->getVertex(1)]->getPoint(), m_vertexs[face->getVertex(2)]->getPoint()); if (BOP_orientation(plane1,face->getPlane()) < 0) { cout << "Test Plane " << face << " v1: "; cout << m_vertexs[face->getVertex(0)]->getPoint() << " v2: "; cout << m_vertexs[face->getVertex(1)]->getPoint() << " v3: "; cout << m_vertexs[face->getVertex(2)]->getPoint() << " plane: "; cout << face->getPlane() << endl; cout << "Incorrect vertices order!!! plane1: " << plane1 << " ("; cout << BOP_orientation(plane1,face->getPlane()) << ") " << " invert "; cout << MT_Plane3(m_vertexs[face->getVertex(2)]->getPoint(), m_vertexs[face->getVertex(1)]->getPoint(), m_vertexs[face->getVertex(0)]->getPoint()) << endl; if (BOP_collinear(m_vertexs[face->getVertex(0)]->getPoint(), m_vertexs[face->getVertex(1)]->getPoint(), m_vertexs[face->getVertex(2)]->getPoint())) { cout << " COLLINEAR!!!" << endl; } else { cout << endl; } } }
/** * Tests if faces since firstFace have all vertexs non-coincident of colinear, otherwise repairs the mesh. * @param mesh mesh that contains the faces, edges and vertices * @param firstFace first face index to be tested */ void BOP_mergeVertexs(BOP_Mesh *mesh, unsigned int firstFace) { unsigned int numFaces = mesh->getNumFaces(); for(unsigned int idxFace = firstFace; idxFace < numFaces; idxFace++) { BOP_Face *face = mesh->getFace(idxFace); if ((face->getTAG() != BROKEN) && (face->getTAG() != PHANTOM)) { MT_Point3 vertex1 = mesh->getVertex(face->getVertex(0))->getPoint(); MT_Point3 vertex2 = mesh->getVertex(face->getVertex(1))->getPoint(); MT_Point3 vertex3 = mesh->getVertex(face->getVertex(2))->getPoint(); if (BOP_collinear(vertex1,vertex2,vertex3)) // collinear triangle face->setTAG(PHANTOM); } } }
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 } } } }