Blender V2.61 - r43446

BOP_Merge2.cpp

Go to the documentation of this file.
00001 /*
00002  *
00003  *
00004  * ***** BEGIN GPL LICENSE BLOCK *****
00005  *
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * as published by the Free Software Foundation; either version 2
00009  * of the License, or (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software Foundation,
00018  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00019  *
00020  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00021  * All rights reserved.
00022  *
00023  * The Original Code is: all of this file.
00024  *
00025  * Contributor(s): Marc Freixas, Ken Hughes
00026  *
00027  * ***** END GPL LICENSE BLOCK *****
00028  */
00029 
00035 #include "BOP_Merge2.h"
00036 
00037 #ifdef BOP_NEW_MERGE
00038 
00039 static void deleteFace(BOP_Mesh *m, BOP_Face *face);
00040 
00044 BOP_Merge2 BOP_Merge2::SINGLETON;
00045 
00046 #ifdef BOP_DEBUG
00047 void dumpmesh ( BOP_Mesh *m, bool force )
00048 {
00049     unsigned int nonmanifold = 0;
00050     {
00051     BOP_Edges edges = m->getEdges();
00052     int count = 0;
00053     for (BOP_IT_Edges edge = edges.begin(); edge != edges.end();
00054         ++count, ++edge) {
00055         if (!(*edge)->getUsed() && (*edge)->getFaces().size() == 0 ) continue;
00056         BOP_Vertex * v1 = m->getVertex((*edge)->getVertex1());
00057         BOP_Vertex * v2 = m->getVertex((*edge)->getVertex2());
00058 
00059         if(v1->getTAG()!= BROKEN || v2->getTAG()!= BROKEN ) {
00060             int fcount = 0;
00061             BOP_Indexs faces = (*edge)->getFaces();
00062             for (BOP_IT_Indexs face = faces.begin(); face != faces.end(); face++) {
00063                 BOP_Face *f = m->getFace(*face);
00064                 if(f->getTAG()== UNCLASSIFIED) ++fcount;
00065             }
00066 
00067 
00068             if(fcount !=0 && fcount !=2 ) {
00069                 ++nonmanifold;
00070             }
00071         }
00072     }
00073     if (!force && nonmanifold == 0) return;
00074     }
00075     if( nonmanifold )
00076         cout << nonmanifold << " edges detected" << endl;
00077 #ifdef BOP_DEBUG
00078     cout << "---------------------------" << endl;
00079 
00080     BOP_Edges edges = m->getEdges();
00081     int count = 0;
00082     for (BOP_IT_Edges edge = edges.begin(); edge != edges.end();
00083         ++count, ++edge) {
00084         BOP_Vertex * v1 = m->getVertex((*edge)->getVertex1());
00085         BOP_Vertex * v2 = m->getVertex((*edge)->getVertex2());
00086 
00087         if(v1->getTAG()!= BROKEN || v2->getTAG()!= BROKEN ) {
00088             int fcount = 0;
00089             BOP_Indexs faces = (*edge)->getFaces();
00090             cout << count << ", " << (*edge) << ", " << faces.size() << endl;
00091             for (BOP_IT_Indexs face = faces.begin(); face != faces.end(); face++) {
00092                 BOP_Face *f = m->getFace(*face);
00093                 if(f->getTAG()== UNCLASSIFIED) ++fcount;
00094                 cout << "  face " << f << endl;
00095             }
00096 
00097 
00098             if(fcount !=0 && fcount !=2 )
00099                 cout << "    NON-MANIFOLD" << endl;
00100         }
00101     }
00102 
00103     BOP_Faces faces = m->getFaces();
00104     count = 0;
00105     for (BOP_IT_Faces face = faces.begin(); face != faces.end(); face++) {
00106         if( count < 12*2 || (*face)->getTAG() != BROKEN ) {
00107             cout << count << ", " << *face << endl;
00108         }
00109         ++count;
00110     }
00111 
00112     BOP_Vertexs verts = m->getVertexs();
00113     count = 0;
00114     for (BOP_IT_Vertexs vert = verts.begin(); vert != verts.end(); vert++) {
00115         cout << count++ << ", " << *vert << " " << (*vert)->getNumEdges() << endl;
00116         BOP_Indexs edges = (*vert)->getEdges();
00117         for( BOP_IT_Indexs it = edges.begin(); it != edges.end(); ++it) {
00118             BOP_Edge *edge = m->getEdge(*it);
00119             cout << "   " << edge << endl;
00120         }
00121     }
00122     cout << "===========================" << endl;
00123 #endif
00124 }
00125 #endif
00126 
00133 void BOP_Merge2::mergeFaces(BOP_Mesh *m, BOP_Index v)
00134 {
00135     m_mesh = m;
00136 
00137 #ifdef BOP_DEBUG
00138     cout << "##############################" << endl;
00139 #endif
00140     cleanup( );
00141 
00142     m_firstVertex = v;
00143     bool cont = false;
00144 
00145     // Merge faces
00146     mergeFaces();   
00147 
00148     do {
00149         // Add quads ...
00150         cont = createQuads();
00151         // ... and merge new faces
00152         if( cont ) cont = mergeFaces();
00153 
00154 #ifdef BOP_DEBUG
00155         cout << "called mergeFaces " << cont << endl;
00156 #endif
00157         // ... until the merge is not succesful
00158     } while(cont);
00159 }
00160 
00161 void clean_nonmanifold( BOP_Mesh *m )
00162 {
00163     return;
00164 
00165     BOP_Edges nme;
00166     BOP_Edges e = m->getEdges();
00167     for( BOP_IT_Edges it = e.begin(); it != e.end(); ++it ) {
00168         BOP_Indexs faces = (*it)->getFaces();
00169         if( faces.size() & ~2 )
00170             nme.push_back(*it);
00171     }
00172     if (nme.size() == 0) return;
00173     for( BOP_IT_Edges it = nme.begin(); it != nme.end(); ++it ) {
00174         if( (*it)->getFaces().size() > 1 ) {
00175             BOP_Indexs faces = (*it)->getFaces();
00176             for( BOP_IT_Indexs face = faces.begin(); face != faces.end(); ++face ) {
00177                 MT_Point3 vertex1 = m->getVertex(m->getFace(*face)->getVertex(0))->getPoint();
00178                 MT_Point3 vertex2 = m->getVertex(m->getFace(*face)->getVertex(1))->getPoint();
00179                 MT_Point3 vertex3 = m->getVertex(m->getFace(*face)->getVertex(2))->getPoint();
00180                 if (BOP_collinear(vertex1,vertex2,vertex3)) // collinear triangle
00181                     deleteFace(m,m->getFace(*face));
00182             }
00183             continue;
00184         }
00185         BOP_Face *oface1 = m->getFace((*it)->getFaces().front());
00186         BOP_Face *oface2, *tmpface;
00187         BOP_Index first =(*it)->getVertex1();
00188         BOP_Index next =(*it)->getVertex2();
00189         BOP_Index last = first;
00190         unsigned short facecount = 0;
00191         bool found = false;
00192         BOP_Indexs vertList;
00193 #ifdef BOP_DEBUG
00194         cout << "  first edge is " << (*it) << endl;
00195 #endif
00196         vertList.push_back(first);
00197         BOP_Edge *edge;
00198         while(true) {
00199             BOP_Vertex *vert = m->getVertex(next);
00200             BOP_Indexs edges = vert->getEdges();
00201             edge = NULL;
00202             for( BOP_IT_Indexs eit = edges.begin(); eit != edges.end(); ++eit) {
00203                 edge = m->getEdge(*eit);
00204                 if( edge->getFaces().size() > 1) {
00205                     edge = NULL;
00206                     continue;
00207                 }
00208                 if( edge->getVertex1() == next && edge->getVertex2() != last ) {
00209                     last = next;
00210                     next = edge->getVertex2();
00211                     break;
00212                 }
00213                 if( edge->getVertex2() == next && edge->getVertex1() != last ) {
00214                     last = next;
00215                     next = edge->getVertex1();
00216                     break;
00217                 }
00218                 edge = NULL;
00219             }
00220             if( !edge ) break;
00221 #ifdef BOP_DEBUG
00222             cout << "   next edge is " << edge << endl;
00223 #endif
00224             tmpface = m->getFace(edge->getFaces().front());
00225             if( oface1->getOriginalFace() != tmpface->getOriginalFace() )
00226                 oface2 = tmpface;
00227             else
00228                 ++facecount;
00229             vertList.push_back(last);
00230             if( vertList.size() > 3 ) break;
00231             if( next == first ) {
00232                 found = true;
00233                 break;
00234             }
00235         }
00236         if(found) {
00237             edge = *it;
00238 #ifdef BOP_DEBUG
00239             cout << "   --> found a loop" << endl;
00240 #endif
00241             if( vertList.size() == 3 ) {
00242                 BOP_Face3 *face = (BOP_Face3 *)m->getFace(edge->getFaces().front());
00243                 face->getNeighbours(first,last,next);
00244             } else if( vertList.size() == 4 ) {
00245                 BOP_Face4 *face = (BOP_Face4 *)m->getFace(edge->getFaces().front());
00246                 face->getNeighbours(first,last,next,last);
00247             } else {
00248 #ifdef BOP_DEBUG
00249                 cout << "loop has " << vertList.size() << "verts"; 
00250 #endif
00251                 continue;
00252             }
00253             if(facecount == 1) oface1 = oface2;
00254             next = vertList[1];
00255             last = vertList[2];
00256             if( edge->getVertex2() == next ) { 
00257                 BOP_Face3 *f = new BOP_Face3(next,first,last,
00258                     oface1->getPlane(),oface1->getOriginalFace());
00259                 m->addFace( f );
00260 #ifdef BOP_DEBUG
00261                 cout << "   face is backward: " << f << endl;
00262 #endif
00263                 
00264             } else {
00265                 BOP_Face3 *f = new BOP_Face3(last,first,next,
00266                     oface1->getPlane(),oface1->getOriginalFace());
00267                 m->addFace( f );
00268 #ifdef BOP_DEBUG
00269                 cout << "   face is forward: " << f << endl;
00270 #endif
00271             }
00272         }
00273     }
00274 }
00275 
00285 void BOP_Merge2::cleanup( void )
00286 {
00287     BOP_Edges edges = m_mesh->getEdges();
00288     for (BOP_IT_Edges edge = edges.begin(); edge != edges.end(); ++edge) {
00289         BOP_Indexs faces = (*edge)->getFaces();
00290         for (BOP_IT_Indexs face = faces.begin(); face != faces.end(); ++face) {
00291             BOP_Face *f = m_mesh->getFace(*face);
00292             if(f->getTAG()== UNCLASSIFIED) ;
00293             else (*edge)->removeFace(*face);
00294         }
00295         if( (*edge)->getFaces().size() == 0) (*edge)->setUsed(false);
00296     }
00297 
00298     BOP_Vertexs v = m_mesh->getVertexs();
00299     for( BOP_IT_Vertexs it = v.begin(); it != v.end(); ++it ) {
00300         if( (*it)->getTAG() != BROKEN) {
00301             BOP_Indexs iedges = (*it)->getEdges();
00302             for(BOP_IT_Indexs i = iedges.begin();i!=iedges.end();i++)
00303                 if( m_mesh->getEdge((*i))->getUsed( ) == false) (*it)->removeEdge( *i );
00304             if( (*it)->getEdges().size() == 0 ) (*it)->setTAG(BROKEN);
00305         }
00306     }
00307     // clean_nonmanifold( m_mesh );
00308 }
00309 
00313 bool BOP_Merge2::mergeFaces()
00314 {
00315     BOP_Indexs mergeVertices;
00316     BOP_Vertexs vertices = m_mesh->getVertexs();
00317     BOP_IT_Vertexs v = vertices.begin();
00318     const BOP_IT_Vertexs verticesEnd = vertices.end();
00319 
00320     // Advance to first mergeable vertex
00321     advance(v,m_firstVertex);
00322     BOP_Index pos = m_firstVertex;
00323 
00324     // Add unbroken vertices to the list
00325     while(v!=verticesEnd) {
00326         if ((*v)->getTAG() != BROKEN) {
00327             mergeVertices.push_back(pos);
00328         }
00329 
00330         v++;
00331         pos++;
00332     }
00333 
00334     // Merge faces with that vertices
00335     return mergeFaces(mergeVertices);
00336 }
00337 
00341 void BOP_Merge2::freeVerts(BOP_Index v, BOP_Vertex *vert)
00342 {
00343     BOP_Indexs edges = vert->getEdges();
00344     BOP_Vertex *other;
00345 
00346     for( BOP_IT_Indexs it = edges.begin(); it != edges.end(); ++it) {
00347         BOP_Edge *edge = m_mesh->getEdge(*it);
00348         BOP_Indexs edges2;
00349         if( edge->getVertex1() != v )
00350             other = m_mesh->getVertex( edge->getVertex1() );
00351         else
00352             other = m_mesh->getVertex( edge->getVertex2() );
00353         other->removeEdge(*it);
00354         vert->removeEdge(*it);
00355     }
00356 }
00357 
00363 bool BOP_Merge2::mergeFaces(BOP_Indexs &mergeVertices)
00364 {
00365     // Check size > 0!
00366     if (mergeVertices.size() == 0) return false;
00367     bool didMerge = false;
00368 
00369     for( BOP_Index i = 0; i < mergeVertices.size(); ++i ) {
00370         BOP_LFaces facesByOriginalFace;
00371         BOP_Index v = mergeVertices[i];
00372         BOP_Vertex *vert = m_mesh->getVertex(v);
00373 #ifdef BOP_DEBUG
00374         cout << "i = " << i << ", v = " << v << ", vert = " << vert << endl;
00375         if (v==48)
00376             cout << "found vert 48" << endl;
00377 #endif
00378         if ( vert->getTAG() != BROKEN ) {
00379             getFaces(facesByOriginalFace,v);
00380 
00381             switch (facesByOriginalFace.size()) {
00382             case 0:
00383                 // v has no unbroken faces (so it's a new BROKEN vertex)
00384                 freeVerts( v, vert );
00385                 vert->setTAG(BROKEN);
00386                 break;
00387             case 2: {
00388 #ifdef BOP_DEBUG
00389                 cout << "size of fBOF = " << facesByOriginalFace.size() << endl;
00390 #endif
00391                 BOP_Faces ff = facesByOriginalFace.front();
00392                 BOP_Faces fb = facesByOriginalFace.back();
00393                 BOP_Index eindexs[2];
00394                 int ecount = 0;
00395 
00396                 // look for two edges adjacent to v which contain both ofaces
00397                 BOP_Indexs edges = vert->getEdges();
00398 #ifdef BOP_DEBUG
00399                 cout << "   ff has " << ff.size() << " faces" << endl;
00400                 cout << "   fb has " << fb.size() << " faces" << endl;
00401                 cout << "   v  has " << edges.size() << " edges" << endl;
00402 #endif
00403                 for(BOP_IT_Indexs it = edges.begin(); it != edges.end(); 
00404                         ++it ) {
00405                     BOP_Edge *edge = m_mesh->getEdge(*it);
00406                     BOP_Indexs faces = edge->getFaces();
00407 #ifdef BOP_DEBUG
00408                     cout << "  " << edge << " has " << edge->getFaces().size() << " faces" << endl;
00409 #endif
00410                     if( faces.size() == 2 ) {
00411                         BOP_Face *f0 = m_mesh->getFace(faces[0]);
00412                         BOP_Face *f1 = m_mesh->getFace(faces[1]);
00413                         if( f0->getOriginalFace() != f1->getOriginalFace() ) {
00414 #ifdef BOP_DEBUG
00415                             cout << "   " << f0 << endl;
00416                             cout << "   " << f1 << endl;
00417 #endif
00418                             eindexs[ecount++] = (*it);
00419                         }
00420                     }
00421                 }
00422                 if(ecount == 2) {
00423 #ifdef BOP_DEBUG
00424                     cout << "   edge indexes are " << eindexs[0];
00425                     cout << " and " << eindexs[1] << endl;
00426 #endif
00427                     BOP_Edge *edge = m_mesh->getEdge(eindexs[0]);
00428                     BOP_Index N = edge->getVertex1();
00429                     if(N == v) N = edge->getVertex2();
00430 #ifdef BOP_DEBUG
00431                     cout << "    ## OK, replace "<<v<<" with "<<N << endl;
00432 #endif
00433                     mergeVertex(ff , v, N );
00434                     mergeVertex(fb , v, N );
00435 // now remove v and its edges
00436                     vert->setTAG(BROKEN);
00437                     for(BOP_IT_Indexs it = edges.begin(); it != edges.end(); 
00438                             ++it ) {
00439                         BOP_Edge *tedge = m_mesh->getEdge(*it);
00440                         tedge->setUsed(false);
00441                     }
00442                     didMerge = true;
00443                 }   
00444 #ifdef BOP_DEBUG
00445                 else {
00446                     cout << "   HUH: ecount was " << ecount << endl;
00447                 }
00448 #endif
00449                 }
00450                 break;
00451             default:
00452                 break;
00453             }
00454         }
00455     }
00456 
00457     return didMerge;
00458 }
00459 
00460 void BOP_Merge2::mergeVertex(BOP_Faces &faces, BOP_Index v1, BOP_Index v2)
00461 {
00462     for(BOP_IT_Faces face=faces.begin();face!=faces.end();face++) {
00463         if( (*face)->size() == 3)
00464             mergeVertex((BOP_Face3 *) *face, v1, v2);
00465         else
00466             mergeVertex((BOP_Face4 *) *face, v1, v2);
00467         (*face)->setTAG(BROKEN);
00468 #ifdef BOP_DEBUG
00469         cout << "  breaking " << (*face) << endl;
00470 #endif
00471     }
00472 }
00473 
00474 /*
00475  * Remove a face from the mesh and from each edges's face list
00476  */
00477 
00478 static void deleteFace(BOP_Mesh *m, BOP_Face *face)
00479 {
00480     BOP_Index l2 = face->getVertex(0);
00481     BOP_Faces faces = m->getFaces();
00482     for(int i = face->size(); i-- ; ) {
00483         BOP_Indexs edges = m->getVertex(l2)->getEdges();
00484         BOP_Index l1 = face->getVertex(i);
00485         for(BOP_IT_Indexs it1 = edges.begin(); it1 != edges.end(); ++it1 ) {
00486             BOP_Edge *edge = m->getEdge(*it1);
00487             if( ( edge->getVertex1() == l1 && edge->getVertex2() == l2 ) ||
00488                 ( edge->getVertex1() == l2 && edge->getVertex2() == l1 ) ) {
00489                 BOP_Indexs ef = edge->getFaces();
00490                 for(BOP_IT_Indexs it = ef.begin(); it != ef.end(); ++it ) {
00491                     if( m->getFace(*it) == face) {
00492                         edge->removeFace(*it);
00493                         break;
00494                     }
00495                 }
00496                 break;
00497             }
00498         }
00499         l2 = l1;
00500     }
00501     face->setTAG(BROKEN);
00502 }
00503 
00504 void BOP_Merge2::mergeVertex(BOP_Face3 *face, BOP_Index v1, BOP_Index v2)
00505 {
00506     BOP_Index next, prev;
00507     face->getNeighbours(v1,prev,next);
00508 
00509     // if new vertex is not already in the tri, make a new tri
00510     if( prev != v2 && next != v2 ) {
00511         m_mesh->addFace( new BOP_Face3(prev,v2,next,
00512                     face->getPlane(),face->getOriginalFace()) );
00513 #ifdef BOP_DEBUG
00514         cout << "mv3: add " << prev << "," << v2 << "," << next << endl;
00515     } else {
00516         cout << "mv3: vertex already in tri: doing nothing" << endl;
00517 #endif
00518     }
00519     deleteFace(m_mesh, face);
00520 }
00521 
00522 void BOP_Merge2::mergeVertex(BOP_Face4 *face, BOP_Index v1, BOP_Index v2)
00523 {
00524     BOP_Index next, prev, opp;
00525     face->getNeighbours(v1,prev,next,opp);
00526 
00527     // if new vertex is already in the quad, replace quad with new tri
00528     if( prev == v2 || next == v2 ) {
00529         m_mesh->addFace( new BOP_Face3(prev,next,opp,
00530                     face->getPlane(),face->getOriginalFace()) );
00531 #ifdef BOP_DEBUG
00532         cout << "mv4a: add " << prev << "," << next << "," << opp << endl;
00533 #endif
00534     }
00535     // otherwise make a new quad
00536     else {
00537         m_mesh->addFace( new BOP_Face4(prev,v2,next,opp,
00538                     face->getPlane(),face->getOriginalFace()) );
00539 #ifdef BOP_DEBUG
00540         cout << "mv4b: add "<<prev<<","<<v2<<","<<next<<","<<opp<<endl;
00541 #endif
00542     }
00543     deleteFace(m_mesh, face);
00544 }
00545 
00546 // #define OLD_QUAD
00547 
00553 bool BOP_Merge2::createQuads()
00554 {
00555   
00556     BOP_Faces quads;
00557     
00558     // Get mesh faces
00559     BOP_Faces faces = m_mesh->getFaces();
00560     
00561     // Merge mesh triangles
00562     const BOP_IT_Faces facesIEnd = (faces.end()-1);
00563     const BOP_IT_Faces facesJEnd = faces.end();
00564     for(BOP_IT_Faces faceI=faces.begin();faceI!=facesIEnd;faceI++) {
00565 #ifdef OLD_QUAD
00566         if ((*faceI)->getTAG() == BROKEN || (*faceI)->size() != 3) continue;
00567         for(BOP_IT_Faces faceJ=(faceI+1);faceJ!=facesJEnd;faceJ++) {
00568             if ((*faceJ)->getTAG() == BROKEN || (*faceJ)->size() != 3 ||
00569                 (*faceJ)->getOriginalFace() != (*faceI)->getOriginalFace()) continue;
00570 
00571 
00572             BOP_Face *faceK = createQuad((BOP_Face3*)*faceI,(BOP_Face3*)*faceJ);
00573             if (faceK != NULL) {
00574                 // Set triangles to BROKEN
00575                 deleteFace(m_mesh, *faceI);
00576                 deleteFace(m_mesh, *faceJ);
00577 #ifdef BOP_DEBUG
00578             cout << "createQuad: del " << *faceI << endl;
00579             cout << "createQuad: del " << *faceJ << endl;
00580             cout << "createQuad: add " << faceK << endl;
00581 #endif
00582                 quads.push_back(faceK);
00583                 break;
00584             }
00585         }
00586 #else
00587         if ((*faceI)->getTAG() == BROKEN ) continue;
00588         for(BOP_IT_Faces faceJ=(faceI+1);faceJ!=facesJEnd;faceJ++) {
00589             if ((*faceJ)->getTAG() == BROKEN ||
00590                 (*faceJ)->getOriginalFace() != (*faceI)->getOriginalFace()) continue;
00591 
00592             BOP_Face *faceK = NULL;
00593             if((*faceI)->size() == 3) {
00594                 if((*faceJ)->size() == 3)
00595                     faceK = createQuad((BOP_Face3*)*faceI,(BOP_Face3*)*faceJ);
00596                 else
00597                     faceK = createQuad((BOP_Face3*)*faceI,(BOP_Face4*)*faceJ);
00598             } else {
00599                 if((*faceJ)->size() == 3)
00600                     faceK = createQuad((BOP_Face3*)*faceJ,(BOP_Face4*)*faceI);
00601                 else
00602                     faceK = createQuad((BOP_Face4*)*faceI,(BOP_Face4*)*faceJ);
00603             }
00604 
00605             if (faceK != NULL) {
00606                 // Set triangles to BROKEN
00607                 deleteFace(m_mesh, *faceI);
00608                 deleteFace(m_mesh, *faceJ);
00609 #ifdef BOP_DEBUG
00610             cout << "createQuad: del " << *faceI << endl;
00611             cout << "createQuad: del " << *faceJ << endl;
00612             cout << "createQuad: add " << faceK << endl;
00613 #endif
00614                 quads.push_back(faceK);
00615                 break;
00616             }
00617         }
00618 #endif
00619     }
00620 
00621     // Add quads to mesh
00622     const BOP_IT_Faces quadsEnd = quads.end();
00623     for(BOP_IT_Faces quad=quads.begin();quad!=quadsEnd;quad++) m_mesh->addFace(*quad);
00624     return (quads.size() > 0);
00625 }
00626 
00635 BOP_Face* BOP_Merge2::createQuad(BOP_Face3 *faceI, BOP_Face3 *faceJ)
00636 {
00637     // Test if both triangles share a vertex index
00638     BOP_Index v;
00639     unsigned int i;
00640     for(i=0;i<3 ;i++) {
00641         v = faceI->getVertex(i);
00642         if( faceJ->containsVertex(v) ) break;
00643     }
00644     if (i == 3) return NULL;
00645 
00646     BOP_Face *faceK = NULL;
00647 
00648     // Get faces data
00649     BOP_Index prevI, nextI, prevJ, nextJ;
00650     faceI->getNeighbours(v,prevI,nextI);
00651     faceJ->getNeighbours(v,prevJ,nextJ);
00652     MT_Point3 vertex = m_mesh->getVertex(v)->getPoint();
00653     MT_Point3 vPrevI = m_mesh->getVertex(prevI)->getPoint();
00654     MT_Point3 vNextI = m_mesh->getVertex(nextI)->getPoint();
00655     MT_Point3 vPrevJ = m_mesh->getVertex(prevJ)->getPoint();
00656     MT_Point3 vNextJ = m_mesh->getVertex(nextJ)->getPoint();
00657 
00658     // Quad test
00659     if (prevI == nextJ) {
00660         if (!BOP_collinear(vNextI,vertex,vPrevJ) && !BOP_collinear(vNextI,vPrevI,vPrevJ) &&
00661             BOP_convex(vertex,vNextI,vPrevI,vPrevJ)) {
00662                 faceK = new BOP_Face4(v,nextI,prevI,prevJ,faceI->getPlane(),faceI->getOriginalFace());
00663                 faceK->setTAG(faceI->getTAG());
00664                 BOP_Index edge;
00665                 m_mesh->getIndexEdge(v,prevI,edge);
00666                 m_mesh->getVertex(v)->removeEdge(edge);
00667                 m_mesh->getVertex(prevI)->removeEdge(edge);
00668         }
00669     }
00670     else if (nextI == prevJ) {
00671         if (!BOP_collinear(vPrevI,vertex,vNextJ) && !BOP_collinear(vPrevI,vNextI,vNextJ) &&
00672             BOP_convex(vertex,vNextJ,vNextI,vPrevI)) {
00673                 faceK = new BOP_Face4(v,nextJ,nextI,prevI,faceI->getPlane(),faceI->getOriginalFace());
00674                 faceK->setTAG(faceI->getTAG());
00675                 BOP_Index edge;
00676                 m_mesh->getIndexEdge(v,nextI,edge);
00677                 m_mesh->getVertex(v)->removeEdge(edge);
00678                 m_mesh->getVertex(nextI)->removeEdge(edge);
00679             }
00680     }
00681     return faceK;
00682 }
00683 
00692 BOP_Face* BOP_Merge2::createQuad(BOP_Face3 *faceI, BOP_Face4 *faceJ)
00693 {
00694     // Test if triangle and quad share a vertex index
00695     BOP_Index v;
00696     unsigned int i;
00697     for(i=0;i<3 ;i++) {
00698         v = faceI->getVertex(i);
00699         if( faceJ->containsVertex(v) ) break;
00700     }
00701     if (i == 3) return NULL;
00702 
00703     BOP_Face *faceK = NULL;
00704 
00705     // Get faces data
00706     BOP_Index prevI, nextI, prevJ, nextJ, oppJ;
00707     faceI->getNeighbours(v,prevI,nextI);
00708     faceJ->getNeighbours(v,prevJ,nextJ,oppJ);
00709 
00710     // Quad test
00711     BOP_Index edge;
00712     if (nextI == prevJ) {
00713         if (prevI == nextJ) {   // v is in center
00714             faceK = new BOP_Face3(nextJ,oppJ,prevJ,faceI->getPlane(),faceI->getOriginalFace());
00715             faceK->setTAG(faceI->getTAG());
00716             m_mesh->getIndexEdge(v,prevI,edge);
00717             m_mesh->getVertex(v)->removeEdge(edge);
00718             m_mesh->getVertex(prevI)->removeEdge(edge);
00719             m_mesh->getIndexEdge(v,nextI,edge);
00720             m_mesh->getVertex(v)->removeEdge(edge);
00721             m_mesh->getVertex(nextI)->removeEdge(edge);
00722             freeVerts(v, m_mesh->getVertex(v));
00723         } else if (prevI == oppJ) { // nextI is in center
00724             faceK = new BOP_Face3(v,nextJ,oppJ,faceI->getPlane(),faceI->getOriginalFace());
00725             faceK->setTAG(faceI->getTAG());
00726             m_mesh->getIndexEdge(v,nextI,edge);
00727             m_mesh->getVertex(v)->removeEdge(edge);
00728             m_mesh->getVertex(nextI)->removeEdge(edge);
00729             m_mesh->getIndexEdge(prevI,nextI,edge);
00730             m_mesh->getVertex(prevI)->removeEdge(edge);
00731             m_mesh->getVertex(nextI)->removeEdge(edge);
00732             freeVerts(nextI, m_mesh->getVertex(nextI));
00733         }
00734     } else if (nextI == oppJ && prevI == nextJ ) { // prevI is in center
00735         faceK = new BOP_Face3(prevJ,v,oppJ,faceI->getPlane(),faceI->getOriginalFace());
00736         faceK->setTAG(faceI->getTAG());
00737         m_mesh->getIndexEdge(v,prevI,edge);
00738         m_mesh->getVertex(v)->removeEdge(edge);
00739         m_mesh->getVertex(prevI)->removeEdge(edge);
00740         m_mesh->getIndexEdge(nextI,prevI,edge);
00741         m_mesh->getVertex(nextI)->removeEdge(edge);
00742         m_mesh->getVertex(prevI)->removeEdge(edge);
00743         freeVerts(prevI, m_mesh->getVertex(prevI));
00744     }
00745     return faceK;
00746 }
00747 
00756 BOP_Face* BOP_Merge2::createQuad(BOP_Face4 *faceI, BOP_Face4 *faceJ)
00757 {
00758     BOP_Face *faceK = NULL;
00759     //
00760     // Test if both quads share a vertex index
00761     //
00762     BOP_Index v;
00763     unsigned int i;
00764     for(i=0;i<4 ;i++) {
00765         v = faceI->getVertex(i);
00766         if( faceJ->containsVertex(v) ) break;
00767     }
00768     if (i == 3) return NULL;
00769 
00770 
00771     // Get faces data
00772     BOP_Index prevI, nextI, oppI, prevJ, nextJ, oppJ;
00773     faceI->getNeighbours(v,prevI,nextI,oppI);
00774     faceJ->getNeighbours(v,prevJ,nextJ,oppJ);
00775 
00776     // Quad test
00777     BOP_Index edge;
00778     if (nextI == prevJ) {
00779         if (prevI == nextJ) {   // v is in center
00780             faceK = new BOP_Face4(nextI,oppI,nextJ,oppJ,faceI->getPlane(),faceI->getOriginalFace());
00781             faceK->setTAG(faceI->getTAG());
00782             m_mesh->getIndexEdge(v,prevI,edge);
00783             m_mesh->getVertex(v)->removeEdge(edge);
00784             m_mesh->getVertex(prevI)->removeEdge(edge);
00785             m_mesh->getIndexEdge(v,nextI,edge);
00786             m_mesh->getVertex(v)->removeEdge(edge);
00787             m_mesh->getVertex(nextI)->removeEdge(edge);
00788             freeVerts(v, m_mesh->getVertex(v));
00789         } else if (oppI == oppJ) {  // nextI is in center
00790             faceK = new BOP_Face4(v,nextJ,oppJ,prevI,faceI->getPlane(),faceI->getOriginalFace());
00791             faceK->setTAG(faceI->getTAG());
00792             m_mesh->getIndexEdge(v,nextI,edge);
00793             m_mesh->getVertex(v)->removeEdge(edge);
00794             m_mesh->getVertex(nextI)->removeEdge(edge);
00795             m_mesh->getIndexEdge(prevI,nextI,edge);
00796             m_mesh->getVertex(prevI)->removeEdge(edge);
00797             m_mesh->getVertex(nextI)->removeEdge(edge);
00798             freeVerts(nextI, m_mesh->getVertex(nextI));
00799         }
00800     } else if (prevI == nextJ && oppI == oppJ) { // prevI is in center
00801         faceK = new BOP_Face4(v,nextI,oppJ,prevJ,faceI->getPlane(),faceI->getOriginalFace());
00802         faceK->setTAG(faceI->getTAG());
00803         m_mesh->getIndexEdge(v,prevI,edge);
00804         m_mesh->getVertex(v)->removeEdge(edge);
00805         m_mesh->getVertex(prevI)->removeEdge(edge);
00806         m_mesh->getIndexEdge(nextI,prevI,edge);
00807         m_mesh->getVertex(nextI)->removeEdge(edge);
00808         m_mesh->getVertex(prevI)->removeEdge(edge);
00809         freeVerts(prevI, m_mesh->getVertex(prevI));
00810     }
00811     return faceK;
00812 }
00813 
00820 bool BOP_Merge2::containsIndex(BOP_Indexs indexs, BOP_Index i)
00821 {
00822   const BOP_IT_Indexs indexsEnd = indexs.end();
00823     for(BOP_IT_Indexs it=indexs.begin();it!=indexsEnd;it++) {
00824         if (*it == i) return true;
00825     }
00826     return false;
00827 }
00828 
00835 void BOP_Merge2::getFaces(BOP_LFaces &facesByOriginalFace, BOP_Index v)
00836 {
00837     // Get edges with vertex v
00838 
00839     BOP_Indexs edgeIndexs = m_mesh->getVertex(v)->getEdges();
00840     const BOP_IT_Indexs edgeEnd = edgeIndexs.end();
00841     for(BOP_IT_Indexs edgeIndex = edgeIndexs.begin();edgeIndex != edgeEnd;edgeIndex++) {    
00842         // For each edge, add its no broken faces to the output list
00843         BOP_Edge* edge = m_mesh->getEdge(*edgeIndex);
00844         BOP_Indexs faceIndexs = edge->getFaces();
00845         const BOP_IT_Indexs faceEnd = faceIndexs.end();
00846         for(BOP_IT_Indexs faceIndex=faceIndexs.begin();faceIndex!=faceEnd;faceIndex++) {
00847             BOP_Face* face = m_mesh->getFace(*faceIndex);
00848             if (face->getTAG() != BROKEN) {
00849                 bool found = false;
00850                 // Search if we already have created a list for the 
00851                 // faces that come from the same original face
00852                 const BOP_IT_LFaces lfEnd = facesByOriginalFace.end();
00853                 for(BOP_IT_LFaces facesByOriginalFaceX=facesByOriginalFace.begin();
00854                 facesByOriginalFaceX!=lfEnd; facesByOriginalFaceX++) {
00855                     if (((*facesByOriginalFaceX)[0])->getOriginalFace() == face->getOriginalFace()) {
00856                         // Search that the face has not been added to the list before
00857                         for(unsigned int i = 0;i<(*facesByOriginalFaceX).size();i++) {
00858                             if ((*facesByOriginalFaceX)[i] == face) {
00859                                 found = true;
00860                                 break;
00861                             }
00862                         }
00863                         if (!found) {
00864                             // Add the face to the list
00865                           if (face->getTAG()==OVERLAPPED) facesByOriginalFaceX->insert(facesByOriginalFaceX->begin(),face);
00866                           else facesByOriginalFaceX->push_back(face);
00867                           found = true;
00868                         }
00869                         break;
00870                     }
00871                 }
00872                 if (!found) {
00873                     // Create a new list and add the current face
00874                     BOP_Faces facesByOriginalFaceX;
00875                     facesByOriginalFaceX.push_back(face);
00876                     facesByOriginalFace.push_back(facesByOriginalFaceX);
00877                 }
00878             }
00879         }
00880     }
00881 }
00882 
00891 void BOP_Merge2::getFaces(BOP_LFaces &facesByOriginalFace, BOP_Indexs vertices, BOP_Index v)
00892 {
00893     // Get edges with vertex v
00894     BOP_Indexs edgeIndexs = m_mesh->getVertex(v)->getEdges();
00895     const BOP_IT_Indexs edgeEnd = edgeIndexs.end();
00896     for(BOP_IT_Indexs edgeIndex = edgeIndexs.begin();edgeIndex != edgeEnd;edgeIndex++) {    
00897         // Foreach edge, add its no broken faces to the output list
00898         BOP_Edge* edge = m_mesh->getEdge(*edgeIndex);
00899         BOP_Indexs faceIndexs = edge->getFaces();
00900         const BOP_IT_Indexs faceEnd = faceIndexs.end();
00901         for(BOP_IT_Indexs faceIndex=faceIndexs.begin();faceIndex!=faceEnd;faceIndex++) {
00902             BOP_Face* face = m_mesh->getFace(*faceIndex);
00903             if (face->getTAG() != BROKEN) {
00904                 // Search if the face contains any of the forbidden vertices
00905                 bool found = false;
00906                 for(BOP_IT_Indexs vertex = vertices.begin();*vertex!= v;vertex++) {
00907                     if (face->containsVertex(*vertex)) {
00908                         // face contains a forbidden vertex!
00909                         found = true;
00910                         break;
00911                 }
00912             }
00913             if (!found) {
00914                 // Search if we already have created a list with the 
00915                 // faces that come from the same original face
00916               const BOP_IT_LFaces lfEnd = facesByOriginalFace.end();
00917                 for(BOP_IT_LFaces facesByOriginalFaceX=facesByOriginalFace.begin();
00918                     facesByOriginalFaceX!=lfEnd; facesByOriginalFaceX++) {
00919                     if (((*facesByOriginalFaceX)[0])->getOriginalFace() == face->getOriginalFace()) {
00920                         // Search that the face has not been added to the list before
00921                         for(unsigned int i = 0;i<(*facesByOriginalFaceX).size();i++) {
00922                             if ((*facesByOriginalFaceX)[i] == face) {
00923                                 found = true;
00924                                 break;
00925                             }
00926                         }
00927                         if (!found) {
00928                           // Add face to the list
00929                           if (face->getTAG()==OVERLAPPED) facesByOriginalFaceX->insert(facesByOriginalFaceX->begin(),face);
00930                           else facesByOriginalFaceX->push_back(face);
00931                           found = true;
00932                         }
00933                         break;
00934                     }
00935                 }
00936                 if (!found) {
00937                     // Create a new list and add the current face
00938                     BOP_Faces facesByOriginalFaceX;
00939                     facesByOriginalFaceX.push_back(face);
00940                     facesByOriginalFace.push_back(facesByOriginalFaceX);
00941                 }
00942             }
00943         }
00944     }
00945     }
00946 }
00947 
00948 #endif  /* BOP_NEW_MERGE */