Blender  V2.59
BOP_Merge.cpp
Go to the documentation of this file.
00001 /*
00002  *
00003  * $Id: BOP_Merge.cpp 35143 2011-02-25 10:32:33Z jesterking $
00004  *
00005  * ***** BEGIN GPL LICENSE BLOCK *****
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software Foundation,
00019  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00022  * All rights reserved.
00023  *
00024  * The Original Code is: all of this file.
00025  *
00026  * Contributor(s): Marc Freixas, Ken Hughes
00027  *
00028  * ***** END GPL LICENSE BLOCK *****
00029  */
00030 
00036 #include "BOP_Merge.h"
00037 
00038 #ifdef BOP_ORIG_MERGE
00039 
00040 #ifdef _MSC_VER
00041 #if _MSC_VER < 1300
00042 #include <list>
00043 #endif
00044 #endif
00045 
00049 BOP_Merge BOP_Merge::SINGLETON;
00050 
00056 void BOP_Merge::mergeFaces(BOP_Mesh *m, BOP_Index v)
00057 {
00058         m_mesh = m;
00059         m_firstVertex = v;
00060 
00061         bool cont = false;
00062 
00063         // Merge faces
00064         mergeFaces();
00065 
00066         do {
00067                 // Add quads ...
00068                 cont = createQuads();
00069                 if (cont) {
00070                         // ... and merge new faces
00071                         cont = mergeFaces();
00072                 }
00073                 // ... until the merge is not succesful
00074         } while(cont);
00075 }
00076 
00080 bool BOP_Merge::mergeFaces()
00081 {
00082         BOP_Indexs mergeVertices;
00083         BOP_Vertexs vertices = m_mesh->getVertexs();
00084         BOP_IT_Vertexs v = vertices.begin();
00085         const BOP_IT_Vertexs verticesEnd = vertices.end();
00086 
00087         // Advance to first mergeable vertex
00088         advance(v,m_firstVertex);
00089         BOP_Index pos = m_firstVertex;
00090 
00091         // Add unbroken vertices to the list
00092         while(v!=verticesEnd) {
00093                 if ((*v)->getTAG() != BROKEN) mergeVertices.push_back(pos);
00094                 v++;pos++;
00095         }
00096 
00097         // Merge faces with that vertices
00098         return mergeFaces(mergeVertices);
00099 }
00100 
00101 
00107 bool BOP_Merge::mergeFaces(BOP_Indexs &mergeVertices)
00108 {
00109         // Check size > 0!
00110         if (mergeVertices.size() == 0) return false;
00111 
00112         // New faces added by merge
00113         BOP_Faces newFaces;
00114 
00115         // Old faces removed by merge
00116         BOP_Faces oldFaces;
00117 
00118         // Get the first vertex index and add it to 
00119         // the current pending vertices to merge
00120         BOP_Index v = mergeVertices[0];
00121         BOP_Indexs pendingVertices;
00122         pendingVertices.push_back(v);
00123 
00124         // Get faces with index v that come from the same original face
00125         BOP_LFaces facesByOriginalFace;
00126         getFaces(facesByOriginalFace,v);
00127 
00128         bool merged = true;
00129 
00130         // Check it has any unbroken face
00131         if (facesByOriginalFace.size()==0) {
00132                 // v has not any unbroken face (so it's a new BROKEN vertex)
00133                 (m_mesh->getVertex(v))->setTAG(BROKEN);
00134                 merged = false;
00135         }
00136 
00137         // Merge vertex faces   
00138         const BOP_IT_LFaces facesEnd = facesByOriginalFace.end();
00139         
00140         for(BOP_IT_LFaces facesByOriginalFaceX = facesByOriginalFace.begin();
00141                 (facesByOriginalFaceX != facesEnd)&&merged;
00142                 facesByOriginalFaceX++) {               
00143                         merged = mergeFaces((*facesByOriginalFaceX),oldFaces,newFaces,pendingVertices,v);
00144         }
00145 
00146         // Check if the are some pendingVertices to merge
00147         if (pendingVertices.size() > 1 && merged) {
00148                 // There are pending vertices that we need to merge in order to merge v ...
00149                 for(unsigned int i=1;i<pendingVertices.size() && merged;i++) 
00150                         merged = mergeFaces(oldFaces,newFaces,pendingVertices,pendingVertices[i]);
00151         }
00152 
00153         // If merge was succesful ...
00154         if (merged) {
00155                 // Set old faces to BROKEN...
00156           const BOP_IT_Faces oldFacesEnd = oldFaces.end();
00157                 for(BOP_IT_Faces face=oldFaces.begin();face!=oldFacesEnd;face++) 
00158                         (*face)->setTAG(BROKEN);
00159 
00160                 // ... and add merged faces (that are the new merged faces without pending vertices)
00161                 const BOP_IT_Faces newFacesEnd = newFaces.end();
00162                 for(BOP_IT_Faces newFace=newFaces.begin();newFace!=newFacesEnd;newFace++) {
00163                         m_mesh->addFace(*newFace);
00164                         // Also, add new face vertices to the queue of vertices to merge if they weren't
00165                         for(BOP_Index i = 0;i<(*newFace)->size();i++) {
00166                                 BOP_Index vertexIndex = (*newFace)->getVertex(i);
00167                                 if (vertexIndex >= m_firstVertex && !containsIndex(mergeVertices,vertexIndex))
00168                                         mergeVertices.push_back(vertexIndex);
00169                         }
00170                 }
00171                 // Set the merged vertices to BROKEN ...
00172                 const BOP_IT_Indexs pendingEnd = pendingVertices.end();
00173                 for(BOP_IT_Indexs pendingVertex = pendingVertices.begin(); pendingVertex != pendingEnd;pendingVertex++) {
00174                         BOP_Index pV = *pendingVertex;
00175                         m_mesh->getVertex(pV)->setTAG(BROKEN);
00176                         // ... and remove them from mergeVertices queue
00177                         const BOP_IT_Indexs mergeEnd = mergeVertices.end();
00178                         for(BOP_IT_Indexs mergeVertex = mergeVertices.begin(); mergeVertex != mergeEnd;mergeVertex++) {
00179                                 BOP_Index mV = *mergeVertex;
00180                                 if (mV == pV) {
00181                                         mergeVertices.erase(mergeVertex);
00182                                         break;
00183                                 }
00184                         }
00185                 }
00186         }
00187         else {
00188                 // The merge  was not succesful, remove the vertex frome merge vertices queue
00189                 mergeVertices.erase(mergeVertices.begin());
00190                 
00191                 // free the not used newfaces
00192                 const BOP_IT_Faces newFacesEnd = newFaces.end();
00193                 for(BOP_IT_Faces newFace=newFaces.begin();newFace!=newFacesEnd;newFace++) {
00194                         delete (*newFace);
00195                 }
00196         }
00197 
00198         // Invoke mergeFaces and return the merge result
00199         return (mergeFaces(mergeVertices) || merged);
00200 }
00201 
00202 
00215 bool BOP_Merge::mergeFaces(BOP_Faces &oldFaces, BOP_Faces &newFaces, BOP_Indexs &vertices, BOP_Index v) {
00216 
00217         bool merged = true;
00218 
00219         // Get faces with v that come from the same original face, (without the already 'merged' from vertices)
00220         BOP_LFaces facesByOriginalFace;
00221         getFaces(facesByOriginalFace,vertices,v);
00222   
00223         if (facesByOriginalFace.size()==0) {
00224                 // All the faces with this vertex were already merged!!!
00225                 return true;
00226         }
00227         else {
00228                 // Merge faces
00229           const BOP_IT_LFaces facesEnd = facesByOriginalFace.end();
00230                 for(BOP_IT_LFaces facesByOriginalFaceX = facesByOriginalFace.begin();
00231                         (facesByOriginalFaceX != facesEnd)&&merged;
00232                         facesByOriginalFaceX++) {
00233                                 merged = mergeFaces((*facesByOriginalFaceX),oldFaces,newFaces,vertices,v);
00234                 }
00235         }
00236         return merged;
00237 }
00238 
00239 
00253 bool BOP_Merge::mergeFaces(BOP_Faces &faces, BOP_Faces &oldFaces, BOP_Faces &newFaces, BOP_Indexs &vertices, BOP_Index v)
00254 {
00255 
00256         bool merged = false;
00257 
00258         if (faces.size() == 2) {
00259                 // Merge a pair of faces into a new face without v
00260                 BOP_Face *faceI = faces[0];
00261                 BOP_Face *faceJ = faces[1];
00262                 BOP_Face *faceK = mergeFaces(faceI,faceJ,vertices,v);
00263                 if (faceK != NULL) {
00264                         newFaces.push_back(faceK);
00265                         oldFaces.push_back(faceI);
00266                         oldFaces.push_back(faceJ);
00267                         merged = true;
00268                 } 
00269                 else merged = false;
00270         }
00271         else if (faces.size() == 4) {
00272                 // Merge two pair of faces into a new pair without v
00273                 // First we try to perform a simplify merge to avoid more pending vertices
00274                 // (for example, if we have two triangles and two quads it will be better
00275                 // to do 3+4 and 3+4 than 3+3 and 4+4)
00276                 BOP_Face *oldFace1 = faces[0];
00277                 BOP_Face *oldFace2, *newFace1;
00278                 unsigned int indexJ = 1;
00279                 while (indexJ < faces.size() && !merged) {
00280                         oldFace2 = faces[indexJ];
00281                         newFace1 = mergeFaces(oldFace1,oldFace2,v);
00282                         if (newFace1 != NULL) merged = true;
00283                         else indexJ++;
00284                 }
00285                 if (merged) {
00286                         // Merge the other pair of faces 
00287                         unsigned int indexK, indexL;
00288                         if (indexJ == 1) {indexK = 2;indexL = 3;}
00289                         else if (indexJ == 2) {indexK = 1;indexL = 3;}
00290                         else {indexK = 1;indexL = 2;}
00291                         BOP_Face *oldFace3 = faces[indexK];
00292                         BOP_Face *oldFace4 = faces[indexL];
00293                         unsigned int oldSize = vertices.size();
00294                         BOP_Face *newFace2 = mergeFaces(oldFace3,oldFace4,vertices,v);
00295                         if (newFace2 != NULL) {
00296                                 newFaces.push_back(newFace1);
00297                                 newFaces.push_back(newFace2);
00298                                 oldFaces.push_back(oldFace1);
00299                                 oldFaces.push_back(oldFace2);
00300                                 oldFaces.push_back(oldFace3);
00301                                 oldFaces.push_back(oldFace4);
00302                                 merged = true;
00303                         }
00304                         else {
00305                                 // Undo all changes
00306                                 delete newFace1;
00307                                 merged = false;
00308                                 unsigned int count = vertices.size() - oldSize;
00309                                 if (count != 0)
00310                                         vertices.erase(vertices.end() - count, vertices.end());
00311                         }
00312                 }               
00313                 if (!merged) {
00314                         // Try a complete merge
00315                         merged = true;
00316                         while (faces.size()>0 && merged) {
00317                                 indexJ = 1;
00318                                 BOP_Face *faceI = faces[0];
00319                                 merged = false;
00320                                 while (indexJ < faces.size()) {
00321                                         BOP_Face *faceJ = faces[indexJ];
00322                                         BOP_Face *faceK = mergeFaces(faceI,faceJ,vertices,v);
00323                                         if (faceK != NULL) {
00324                                                 // faceK = faceI + faceJ and it does not include v!
00325                                                 faces.erase(faces.begin()+indexJ,faces.begin()+(indexJ+1));
00326                                                 faces.erase(faces.begin(),faces.begin()+1);
00327                                                 newFaces.push_back(faceK);
00328                                                 oldFaces.push_back(faceI);
00329                                                 oldFaces.push_back(faceJ);
00330                                                 merged = true;
00331                                                 break;
00332                                         }
00333                                         else indexJ++;
00334                                 }
00335                         }
00336                 }
00337         }
00338         else merged = false; // there are N=1 or N=3 or N>4 faces!
00339 
00340         // Return merge result
00341         return merged;
00342 }
00343 
00352 BOP_Face* BOP_Merge::mergeFaces(BOP_Face *faceI, BOP_Face *faceJ, BOP_Index v)
00353 {
00354         if (faceI->size() == 3) {
00355                 if (faceJ->size() == 4)
00356                         return mergeFaces((BOP_Face4*)faceJ,(BOP_Face3*)faceI,v);
00357         }
00358         else if (faceI->size() == 4) {
00359                 if (faceJ->size() == 3)
00360                         return mergeFaces((BOP_Face4*)faceI,(BOP_Face3*)faceJ,v);
00361         }
00362         return NULL;
00363 }
00364 
00377 BOP_Face* BOP_Merge::mergeFaces(BOP_Face *faceI, BOP_Face *faceJ, BOP_Indexs &pending, BOP_Index v)
00378 {
00379         if (faceI->size() == 3) {
00380                 if (faceJ->size() == 3)
00381                         return mergeFaces((BOP_Face3*)faceI,(BOP_Face3*)faceJ,v);
00382                 else if (faceJ->size() == 4)
00383                         return mergeFaces((BOP_Face4*)faceJ,(BOP_Face3*)faceI,pending,v);
00384         }
00385         else if (faceI->size() == 4) {
00386                 if (faceJ->size() == 3)
00387                         return mergeFaces((BOP_Face4*)faceI,(BOP_Face3*)faceJ,pending,v);
00388                 else if (faceJ->size() == 4)
00389                         return mergeFaces((BOP_Face4*)faceI,(BOP_Face4*)faceJ,pending,v);
00390         }
00391         return NULL;
00392 }
00393 
00402 BOP_Face* BOP_Merge::mergeFaces(BOP_Face3 *faceI, BOP_Face3 *faceJ, BOP_Index v)
00403 {
00404         BOP_Face *faceK = NULL;
00405 
00406         // Get faces data
00407         BOP_Index prevI, nextI, prevJ, nextJ;   
00408         faceI->getNeighbours(v,prevI,nextI);
00409         faceJ->getNeighbours(v,prevJ,nextJ);
00410         MT_Point3 vertex = m_mesh->getVertex(v)->getPoint();
00411         MT_Point3 vPrevI = m_mesh->getVertex(prevI)->getPoint();
00412         MT_Point3 vNextI = m_mesh->getVertex(nextI)->getPoint();
00413         MT_Point3 vPrevJ = m_mesh->getVertex(prevJ)->getPoint();
00414         MT_Point3 vNextJ = m_mesh->getVertex(nextJ)->getPoint();
00415 
00416         // Merge test
00417         if (prevI == nextJ) {
00418                 // Both faces share the edge (prevI,v) == (v,nextJ)
00419                 if (BOP_between(vertex,vNextI,vPrevJ)) {
00420                         faceK = new BOP_Face3(prevI,prevJ,nextI,faceI->getPlane(),faceI->getOriginalFace());
00421                         faceK->setTAG(faceI->getTAG());
00422                 }
00423         }
00424         else if (nextI == prevJ) {
00425                 // Both faces share the edge (v,nextI) == (prevJ,v)
00426                 if (BOP_between(vertex,vPrevI,vNextJ)) {
00427                         faceK = new BOP_Face3(prevI,nextJ,nextI,faceI->getPlane(),faceI->getOriginalFace());
00428                         faceK->setTAG(faceI->getTAG());
00429                 }
00430         }
00431         return faceK;
00432 }
00433 
00442 BOP_Face* BOP_Merge::mergeFaces(BOP_Face4 *faceI, BOP_Face3 *faceJ, BOP_Index v)
00443 {
00444         BOP_Face *faceK = NULL;
00445 
00446         // Get faces data
00447         BOP_Index prevI, nextI, opp, prevJ, nextJ;
00448         faceI->getNeighbours(v,prevI,nextI,opp);
00449         faceJ->getNeighbours(v,prevJ,nextJ);
00450         MT_Point3 vertex = m_mesh->getVertex(v)->getPoint();
00451         MT_Point3 vOpp = m_mesh->getVertex(opp)->getPoint();
00452         MT_Point3 vPrevI = m_mesh->getVertex(prevI)->getPoint();
00453         MT_Point3 vNextI = m_mesh->getVertex(nextI)->getPoint();
00454         MT_Point3 vPrevJ = m_mesh->getVertex(prevJ)->getPoint();
00455         MT_Point3 vNextJ = m_mesh->getVertex(nextJ)->getPoint();
00456 
00457         // Merge test
00458         if (prevI == nextJ) {
00459                 if (BOP_between(vertex,vNextI,vPrevJ) && !BOP_collinear(vPrevJ,vPrevI,vOpp)
00460                         && BOP_convex(vOpp,vPrevI,vPrevJ,vNextI)) {
00461                         faceK = new BOP_Face4(opp,prevI,prevJ,nextI,faceI->getPlane(),faceI->getOriginalFace());
00462                         faceK->setTAG(faceI->getTAG());
00463                 }
00464         }
00465         else if (nextI == prevJ) {
00466                 if (BOP_between(vertex,vPrevI,vNextJ) && !BOP_collinear(vNextJ,vNextI,vOpp)
00467                         && BOP_convex(vOpp,vPrevI,vNextJ,vNextI)) {
00468                         faceK = new BOP_Face4(opp,prevI,nextJ,nextI,faceI->getPlane(),faceI->getOriginalFace());
00469                         faceK->setTAG(faceI->getTAG());
00470                 }
00471         }
00472         return faceK;
00473 }
00474 
00486 BOP_Face* BOP_Merge::mergeFaces(BOP_Face4 *faceI, BOP_Face3 *faceJ, BOP_Indexs &pending, BOP_Index v)
00487 {
00488         BOP_Face *faceK = NULL;
00489 
00490         // Get faces data
00491         BOP_Index prevI, nextI, opp, prevJ, nextJ;
00492         faceI->getNeighbours(v,prevI,nextI,opp);
00493         faceJ->getNeighbours(v,prevJ,nextJ);
00494         MT_Point3 vertex = m_mesh->getVertex(v)->getPoint();
00495         MT_Point3 vOpp = m_mesh->getVertex(opp)->getPoint();
00496         MT_Point3 vPrevI = m_mesh->getVertex(prevI)->getPoint();
00497         MT_Point3 vNextI = m_mesh->getVertex(nextI)->getPoint();
00498         MT_Point3 vPrevJ = m_mesh->getVertex(prevJ)->getPoint();
00499         MT_Point3 vNextJ = m_mesh->getVertex(nextJ)->getPoint();
00500 
00501         // Merge test
00502         if (prevI == nextJ) {
00503                 if (BOP_between(vertex,vNextI,vPrevJ)) {
00504                         if (!BOP_collinear(vPrevJ,vPrevI,vOpp) && BOP_convex(vOpp,vPrevI,vPrevJ,vNextI)) {
00505                                 // The result is a new quad
00506                                 faceK = new BOP_Face4(opp,prevI,prevJ,nextI,faceI->getPlane(),faceI->getOriginalFace());
00507                                 faceK->setTAG(faceI->getTAG());
00508                         }
00509                         else if (BOP_between(vPrevI,vPrevJ,vOpp)) {
00510                                 // The result is a triangle (only if prevI can be merged)
00511                                 if (prevI < m_firstVertex) return NULL; // It can't be merged
00512                                 faceK = new BOP_Face3(nextI,opp,prevJ,faceI->getPlane(),faceI->getOriginalFace());
00513                                 faceK->setTAG(faceI->getTAG());
00514                                 if (!containsIndex(pending, prevI)) pending.push_back(prevI);
00515                         }
00516                 }
00517         }
00518         else if (nextI == prevJ) {
00519                 if (BOP_between(vertex,vPrevI,vNextJ)) {
00520                         if (!BOP_collinear(vNextJ,vNextI,vOpp) && BOP_convex(vOpp,vPrevI,vNextJ,vNextI)) {
00521                                 // The result is a new quad
00522                                 faceK = new BOP_Face4(opp,prevI,nextJ,nextI,faceI->getPlane(),faceI->getOriginalFace());
00523                                 faceK->setTAG(faceI->getTAG());
00524                         }
00525                         else if (BOP_between(vNextI,vOpp,vNextJ)) {
00526                                 // The result is a triangle (only if nextI can be merged)
00527                                 if (nextI < m_firstVertex) return NULL;
00528                                 faceK = new BOP_Face3(prevI,nextJ,opp,faceI->getPlane(),faceI->getOriginalFace());
00529                                 faceK->setTAG(faceI->getTAG());
00530                                 if (!containsIndex(pending, nextI)) pending.push_back(nextI);
00531                         }
00532                 }
00533         }
00534         return faceK;
00535 }
00536 
00548 BOP_Face* BOP_Merge::mergeFaces(BOP_Face4 *faceI, BOP_Face4 *faceJ, BOP_Indexs &pending, BOP_Index v)
00549 {
00550         BOP_Face *faceK = NULL;
00551 
00552         // Get faces data
00553         BOP_Index prevI, nextI, oppI, prevJ, nextJ, oppJ;
00554         faceI->getNeighbours(v,prevI,nextI,oppI);
00555         faceJ->getNeighbours(v,prevJ,nextJ,oppJ);
00556         MT_Point3 vertex = m_mesh->getVertex(v)->getPoint();
00557         MT_Point3 vPrevI = m_mesh->getVertex(prevI)->getPoint();
00558         MT_Point3 vNextI = m_mesh->getVertex(nextI)->getPoint();
00559         MT_Point3 vOppI = m_mesh->getVertex(oppI)->getPoint();
00560         MT_Point3 vPrevJ = m_mesh->getVertex(prevJ)->getPoint();
00561         MT_Point3 vNextJ = m_mesh->getVertex(nextJ)->getPoint();
00562         MT_Point3 vOppJ = m_mesh->getVertex(oppJ)->getPoint();
00563 
00564         // Merge test
00565         if (prevI == nextJ) {
00566                 // prevI/nextJ will be a new vertex required to merge
00567                 if (prevI < m_firstVertex) return NULL; // It can't be merged
00568                 if (BOP_between(vertex,vPrevJ,vNextI) && BOP_between(vNextJ,vOppJ,vOppI)) {
00569                         faceK = new BOP_Face4(oppJ,prevJ,nextI,oppI,faceI->getPlane(),faceI->getOriginalFace());
00570                         faceK->setTAG(faceI->getTAG());
00571                         // We add prevI to the pending list if it wasn't yet
00572                         if (!containsIndex(pending, prevI)) pending.push_back(prevI);
00573                 }
00574         }
00575         else if (nextI == prevJ) {
00576                 // nextI/prevJ will be a new vertex required to merge
00577                 if (nextI < m_firstVertex) return NULL; // It can't be merged
00578                 if (BOP_between(vertex,vPrevI,vNextJ) && BOP_between(vNextI,vOppI,vOppJ)) {
00579                         faceK = new BOP_Face4(oppI,prevI,nextJ,oppJ,faceI->getPlane(),faceI->getOriginalFace());
00580                         faceK->setTAG(faceI->getTAG());
00581                         // Add nextI to the pending list if it wasn't yet
00582                         if (!containsIndex(pending, nextI)) pending.push_back(nextI);
00583                 }
00584         }
00585         return faceK;
00586 }
00587 
00588 
00594 bool BOP_Merge::createQuads()
00595 {
00596   
00597         BOP_Faces quads;
00598         
00599         // Get mesh faces
00600         BOP_Faces faces = m_mesh->getFaces();
00601 
00602         
00603     // Merge mesh triangles
00604         const BOP_IT_Faces facesIEnd = (faces.end()-1);
00605         const BOP_IT_Faces facesJEnd = faces.end();
00606         for(BOP_IT_Faces faceI=faces.begin();faceI!=facesIEnd;faceI++) {
00607                 if ((*faceI)->getTAG() == BROKEN || (*faceI)->size() != 3) continue;
00608                 for(BOP_IT_Faces faceJ=(faceI+1);faceJ!=facesJEnd;faceJ++) {
00609                         if ((*faceJ)->getTAG() == BROKEN || (*faceJ)->size() != 3 ||
00610                                 (*faceJ)->getOriginalFace() != (*faceI)->getOriginalFace()) continue;
00611 
00612                         // Test if both triangles share a vertex index
00613                         BOP_Index v;
00614                         bool found = false;
00615                         for(unsigned int i=0;i<3 && !found;i++) {
00616                                 v = (*faceI)->getVertex(i);
00617                                 found = (*faceJ)->containsVertex(v);
00618                                 
00619                         }
00620                         if (!found) continue;
00621 
00622                         BOP_Face *faceK = createQuad((BOP_Face3*)*faceI,(BOP_Face3*)*faceJ,v);
00623                         if (faceK != NULL) {
00624                                 // Set triangles to BROKEN
00625                                 (*faceI)->setTAG(BROKEN);
00626                                 (*faceJ)->setTAG(BROKEN);
00627                                 quads.push_back(faceK);
00628                                 break;
00629                         }
00630                 }
00631         }
00632 
00633     // Add quads to mesh
00634         const BOP_IT_Faces quadsEnd = quads.end();
00635         for(BOP_IT_Faces quad=quads.begin();quad!=quadsEnd;quad++) m_mesh->addFace(*quad);
00636         return (quads.size() > 0);
00637 }
00638 
00647 BOP_Face* BOP_Merge::createQuad(BOP_Face3 *faceI, BOP_Face3 *faceJ, BOP_Index v)
00648 {
00649         BOP_Face *faceK = NULL;
00650 
00651         // Get faces data
00652         BOP_Index prevI, nextI, prevJ, nextJ;
00653         faceI->getNeighbours(v,prevI,nextI);
00654         faceJ->getNeighbours(v,prevJ,nextJ);
00655         MT_Point3 vertex = m_mesh->getVertex(v)->getPoint();
00656         MT_Point3 vPrevI = m_mesh->getVertex(prevI)->getPoint();
00657         MT_Point3 vNextI = m_mesh->getVertex(nextI)->getPoint();
00658         MT_Point3 vPrevJ = m_mesh->getVertex(prevJ)->getPoint();
00659         MT_Point3 vNextJ = m_mesh->getVertex(nextJ)->getPoint();
00660 
00661         // Quad test
00662         if (prevI == nextJ) {
00663                 if (!BOP_collinear(vNextI,vertex,vPrevJ) && !BOP_collinear(vNextI,vPrevI,vPrevJ) &&
00664                         BOP_convex(vertex,vNextI,vPrevI,vPrevJ)) {
00665                                 faceK = new BOP_Face4(v,nextI,prevI,prevJ,faceI->getPlane(),faceI->getOriginalFace());
00666                                 faceK->setTAG(faceI->getTAG());
00667                 }
00668         }
00669         else if (nextI == prevJ) {
00670                 if (!BOP_collinear(vPrevI,vertex,vNextJ) && !BOP_collinear(vPrevI,vNextI,vNextJ) &&
00671                         BOP_convex(vertex,vNextJ,vNextI,vPrevI)) {
00672                                 faceK = new BOP_Face4(v,nextJ,nextI,prevI,faceI->getPlane(),faceI->getOriginalFace());
00673                                 faceK->setTAG(faceI->getTAG());
00674                         }
00675         }
00676         return faceK;
00677 }
00678 
00685 bool BOP_Merge::containsIndex(BOP_Indexs indexs, BOP_Index i)
00686 {
00687   const BOP_IT_Indexs indexsEnd = indexs.end();
00688         for(BOP_IT_Indexs it=indexs.begin();it!=indexsEnd;it++) {
00689                 if (*it == i) return true;
00690         }
00691         return false;
00692 }
00693 
00700 void BOP_Merge::getFaces(BOP_LFaces &facesByOriginalFace, BOP_Index v)
00701 {
00702         // Get edges with vertex v
00703         BOP_Indexs edgeIndexs = m_mesh->getVertex(v)->getEdges();
00704         const BOP_IT_Indexs edgeEnd = edgeIndexs.end();
00705         for(BOP_IT_Indexs edgeIndex = edgeIndexs.begin();edgeIndex != edgeEnd;edgeIndex++) {    
00706                 // Foreach edge, add its no broken faces to the output list
00707                 BOP_Edge* edge = m_mesh->getEdge(*edgeIndex);
00708                 BOP_Indexs faceIndexs = edge->getFaces();
00709                 const BOP_IT_Indexs faceEnd = faceIndexs.end();
00710                 for(BOP_IT_Indexs faceIndex=faceIndexs.begin();faceIndex!=faceEnd;faceIndex++) {
00711                         BOP_Face* face = m_mesh->getFace(*faceIndex);
00712                         if (face->getTAG() != BROKEN) {
00713                                 bool found = false;
00714                                 // Search if we already have created a list for the 
00715                                 // faces that come from the same original face
00716                                 const BOP_IT_LFaces lfEnd = facesByOriginalFace.end();
00717                                 for(BOP_IT_LFaces facesByOriginalFaceX=facesByOriginalFace.begin();
00718                                 facesByOriginalFaceX!=lfEnd; facesByOriginalFaceX++) {
00719                                         if (((*facesByOriginalFaceX)[0])->getOriginalFace() == face->getOriginalFace()) {
00720                                                 // Search that the face has not been added to the list before
00721                                                 for(unsigned int i = 0;i<(*facesByOriginalFaceX).size();i++) {
00722                                                         if ((*facesByOriginalFaceX)[i] == face) {
00723                                                                 found = true;
00724                                                                 break;
00725                                                         }
00726                                                 }
00727                                                 if (!found) {
00728                                                         // Add the face to the list
00729                                                   if (face->getTAG()==OVERLAPPED) facesByOriginalFaceX->insert(facesByOriginalFaceX->begin(),face);
00730                                                   else facesByOriginalFaceX->push_back(face);
00731                                                   found = true;
00732                                                 }
00733                                                 break;
00734                                         }
00735                                 }
00736                                 if (!found) {
00737                                         // Create a new list and add the current face
00738                                         BOP_Faces facesByOriginalFaceX;
00739                                         facesByOriginalFaceX.push_back(face);
00740                                         facesByOriginalFace.push_back(facesByOriginalFaceX);
00741                                 }
00742                         }
00743                 }
00744         }
00745 }
00746 
00755 void BOP_Merge::getFaces(BOP_LFaces &facesByOriginalFace, BOP_Indexs vertices, BOP_Index v)
00756 {
00757         // Get edges with vertex v
00758         BOP_Indexs edgeIndexs = m_mesh->getVertex(v)->getEdges();
00759         const BOP_IT_Indexs edgeEnd = edgeIndexs.end();
00760         for(BOP_IT_Indexs edgeIndex = edgeIndexs.begin();edgeIndex != edgeEnd;edgeIndex++) {    
00761                 // Foreach edge, add its no broken faces to the output list
00762                 BOP_Edge* edge = m_mesh->getEdge(*edgeIndex);
00763                 BOP_Indexs faceIndexs = edge->getFaces();
00764                 const BOP_IT_Indexs faceEnd = faceIndexs.end();
00765                 for(BOP_IT_Indexs faceIndex=faceIndexs.begin();faceIndex!=faceEnd;faceIndex++) {
00766                         BOP_Face* face = m_mesh->getFace(*faceIndex);
00767                         if (face->getTAG() != BROKEN) {
00768                                 // Search if the face contains any of the forbidden vertices
00769                                 bool found = false;
00770                                 for(BOP_IT_Indexs vertex = vertices.begin();*vertex!= v;vertex++) {
00771                                         if (face->containsVertex(*vertex)) {
00772                                                 // face contains a forbidden vertex!
00773                                                 found = true;
00774                                                 break;
00775                                 }
00776                         }
00777                         if (!found) {
00778                                 // Search if we already have created a list with the 
00779                                 // faces that come from the same original face
00780                           const BOP_IT_LFaces lfEnd = facesByOriginalFace.end();
00781                                 for(BOP_IT_LFaces facesByOriginalFaceX=facesByOriginalFace.begin();
00782                                         facesByOriginalFaceX!=lfEnd; facesByOriginalFaceX++) {
00783                                         if (((*facesByOriginalFaceX)[0])->getOriginalFace() == face->getOriginalFace()) {
00784                                                 // Search that the face has not been added to the list before
00785                                                 for(unsigned int i = 0;i<(*facesByOriginalFaceX).size();i++) {
00786                                                         if ((*facesByOriginalFaceX)[i] == face) {
00787                                                                 found = true;
00788                                                                 break;
00789                                                         }
00790                                                 }
00791                                                 if (!found) {
00792                                                   // Add face to the list
00793                                                   if (face->getTAG()==OVERLAPPED) facesByOriginalFaceX->insert(facesByOriginalFaceX->begin(),face);
00794                                                   else facesByOriginalFaceX->push_back(face);
00795                                                   found = true;
00796                                                 }
00797                                                 break;
00798                                         }
00799                                 }
00800                                 if (!found) {
00801                                         // Create a new list and add the current face
00802                                         BOP_Faces facesByOriginalFaceX;
00803                                         facesByOriginalFaceX.push_back(face);
00804                                         facesByOriginalFace.push_back(facesByOriginalFaceX);
00805                                 }
00806                         }
00807                 }
00808         }
00809         }
00810 }
00811 
00812 #endif  /* BOP_ORIG_MERGE */