Blender V2.61 - r43446

BOP_Mesh.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): none yet.
00026  *
00027  * ***** END GPL LICENSE BLOCK *****
00028  */
00029 
00035 #include "BOP_Mesh.h"
00036 #include "BOP_MathUtils.h"
00037 #include <iostream>
00038 #include <fstream>
00039 
00040 #include "MEM_guardedalloc.h"
00041 #include "BLI_blenlib.h"
00042 
00043 BOP_Mesh::BOP_Mesh()
00044 {
00045 #ifdef HASH
00046 #ifdef HASH_PRINTF_DEBUG
00047     printf ("has hashing\n");
00048 #endif
00049     hash = NULL;
00050     hashsize = 0;
00051 #endif
00052 }
00053 
00057 BOP_Mesh::~BOP_Mesh()
00058 {
00059     const BOP_IT_Vertexs vertexsEnd = m_vertexs.end();
00060     for(BOP_IT_Vertexs itv=m_vertexs.begin();itv!=vertexsEnd;itv++){
00061         delete *itv;
00062     }
00063     m_vertexs.clear();
00064   
00065     const BOP_IT_Edges edgesEnd = m_edges.end();
00066     for(BOP_IT_Edges ite=m_edges.begin();ite!=edgesEnd;ite++){
00067         delete *ite;
00068     }
00069     m_edges.clear();
00070   
00071     const BOP_IT_Faces facesEnd = m_faces.end();
00072     for(BOP_IT_Faces itf=m_faces.begin();itf!=facesEnd;itf++){
00073         delete *itf;
00074     }
00075     m_faces.clear();
00076 
00077 #ifdef HASH
00078     while( hashsize ) {
00079         --hashsize;
00080         BLI_freelistN( &hash[hashsize] );
00081     }
00082     MEM_freeN( hash );
00083     hash = NULL;
00084 #endif
00085 }
00086 
00092 BOP_Index BOP_Mesh::addVertex(MT_Point3 p)
00093 {
00094     m_vertexs.push_back(new BOP_Vertex(p));
00095     return m_vertexs.size()-1;
00096 }
00097 
00104 BOP_Index BOP_Mesh::addEdge(BOP_Index v1, BOP_Index v2)
00105 {
00106 #ifdef HASH
00107     /* prepare a new hash entry for the edge */
00108     int minv;
00109     EdgeEntry *h = (EdgeEntry *)MEM_callocN( sizeof( EdgeEntry ), "edgehash" );
00110 
00111     /* store sorted, smallest vert first */
00112     if( v1 < v2 ) {
00113         minv = HASH(v1);
00114         h->v1 = v1;
00115         h->v2 = v2;
00116     } else {
00117         minv = HASH(v2);
00118         h->v1 = v2;
00119         h->v2 = v1;
00120     }
00121     h->index = m_edges.size();
00122 
00123     /* if hash index larger than hash list, extend the list */
00124     if( minv >= hashsize ) {
00125         int newsize = (minv + 8) & ~7;
00126         ListBase *nhash = (ListBase *)MEM_mallocN( 
00127                 newsize * sizeof( ListBase ),
00128                 "edgehashtable" );
00129         /* copy old entries */
00130         memcpy( nhash, hash, sizeof( ListBase ) * hashsize );
00131         /* clear new ones */
00132         while( hashsize < newsize ) {
00133             nhash[hashsize].first = nhash[hashsize].last = NULL;
00134             ++hashsize;
00135         }
00136         if( hash )
00137             MEM_freeN( hash );
00138         hash = nhash;
00139     }
00140 
00141     /* add the entry to tail of the right hash list */
00142     BLI_addtail( &hash[minv], h );
00143 #endif
00144     m_edges.push_back(new BOP_Edge(v1,v2));
00145     return m_edges.size()-1;
00146 }
00147 
00148 #ifdef HASH
00149 
00155 void BOP_Mesh::rehashVertex(BOP_Index o, BOP_Index n, BOP_Index x)
00156 {
00157     EdgeEntry *edge;
00158     int minv = HASH(o);
00159     BOP_Index v1, v2;
00160 
00161     /* figure out where and what to look for */
00162     if( o < x ) {
00163         minv = HASH(o);
00164         v1 = o; v2 = x;
00165     } else {
00166         minv = HASH(x);
00167         v1 = x; v2 = o;
00168     }
00169 
00170     /* if hash is valid, search for the match */
00171     if( minv < hashsize ) {
00172         for(edge = (EdgeEntry *)hash[minv].first;
00173                 edge; edge = edge->next ) {
00174             if(edge->v1 == v1 && edge->v2 == v2)
00175                 break;
00176         }
00177 
00178         /* NULL edge == no match */
00179         if(!edge) {
00180 #ifdef HASH_PRINTF_DEBUG
00181             printf ("OOPS! didn't find edge (%d %d)\n",v1,v2);
00182 #endif
00183             return;
00184         }
00185 #ifdef HASH_PRINTF_DEBUG
00186         printf ("found edge (%d %d)\n",v1,v2);
00187 #endif
00188         /* remove the edge from the old hash list */
00189         BLI_remlink( &hash[minv], edge );
00190 
00191         /* decide where the new edge should go */
00192         if( n < x ) {
00193             minv = HASH(n);
00194             v1 = n; v2 = x;
00195         } else {
00196             minv = HASH(x);
00197             edge->v1 = x; edge->v2 = n;
00198         }
00199 
00200         /* if necessary, extend the hash list */
00201         if( minv >= hashsize ) {
00202 #ifdef HASH_PRINTF_DEBUG
00203             printf ("OOPS! new vertex too large! (%d->%d)\n",o,n);
00204 #endif
00205             int newsize = (minv + 8) & ~7;
00206             ListBase *nhash = (ListBase *)MEM_mallocN( 
00207                     newsize * sizeof( ListBase ),
00208                     "edgehashtable" );
00209             memcpy( nhash, hash, sizeof( ListBase ) * hashsize );
00210             while( hashsize < newsize ) {
00211                 nhash[hashsize].first = nhash[hashsize].last = NULL;
00212                 ++hashsize;
00213             }
00214             if( hash )
00215                 MEM_freeN( hash );
00216             hash = nhash;
00217         }
00218 
00219         /* add the entry to tail of the right hash list */
00220         BLI_addtail( &hash[minv], edge );
00221     } else {
00222 #ifdef HASH_PRINTF_DEBUG
00223         printf ("OOPS! hash not large enough for (%d %d)\n",minv,hashsize);
00224 #endif
00225     }
00226 }
00227 #endif
00228 
00234 BOP_Index BOP_Mesh::addFace(BOP_Face *face)
00235 {
00236     if (face->size()==3)
00237         return addFace((BOP_Face3 *)face);
00238     else
00239         return addFace((BOP_Face4 *)face);
00240 }
00241 
00247 BOP_Index BOP_Mesh::addFace(BOP_Face3 *face)
00248 {
00249     BOP_Index indexface = m_faces.size();
00250     
00251     BOP_Index index1 = face->getVertex(0);
00252     BOP_Index index2 = face->getVertex(1);
00253     BOP_Index index3 = face->getVertex(2);
00254 
00255     m_faces.push_back((BOP_Face *)face);  
00256         
00257     BOP_Index edge;
00258 
00259     if (!getIndexEdge(index1,index2,edge)) {
00260         edge = addEdge(index1,index2);
00261         getVertex(index1)->addEdge(edge);
00262         getVertex(index2)->addEdge(edge);
00263     }
00264             
00265     getEdge(edge)->addFace(indexface);
00266     
00267     if (!getIndexEdge(index2,index3,edge)) {
00268         edge = addEdge(index2,index3);
00269         getVertex(index2)->addEdge(edge);
00270         getVertex(index3)->addEdge(edge);
00271     }
00272     
00273     getEdge(edge)->addFace(indexface);
00274 
00275     if (!getIndexEdge(index3,index1,edge)) {
00276         edge = addEdge(index3,index1);
00277         getVertex(index3)->addEdge(edge);
00278         getVertex(index1)->addEdge(edge);
00279     }
00280     
00281     getEdge(edge)->addFace(indexface);
00282     
00283     if ((index1 == index2) || (index1 == index3) || (index2 == index3))
00284         face->setTAG(BROKEN);
00285 
00286     return indexface;  
00287 }
00288 
00294 BOP_Index BOP_Mesh::addFace(BOP_Face4 *face)
00295 {
00296     m_faces.push_back((BOP_Face *)face);
00297     BOP_Index indexface = m_faces.size()-1;
00298   
00299     BOP_Index index1 = face->getVertex(0);
00300     BOP_Index index2 = face->getVertex(1);
00301     BOP_Index index3 = face->getVertex(2);
00302     BOP_Index index4 = face->getVertex(3);
00303   
00304     BOP_Index edge;
00305   
00306     if (!getIndexEdge(index1,index2,edge)) {
00307         edge = addEdge(index1,index2);
00308         getVertex(index1)->addEdge(edge);
00309         getVertex(index2)->addEdge(edge);
00310     }
00311   
00312     getEdge(edge)->addFace(indexface);
00313   
00314     if (!getIndexEdge(index2,index3,edge)) {
00315         edge = addEdge(index2,index3);
00316         getVertex(index2)->addEdge(edge);
00317         getVertex(index3)->addEdge(edge);
00318     }
00319   
00320     getEdge(edge)->addFace(indexface);      
00321   
00322     if (!getIndexEdge(index3,index4,edge)) {
00323         edge = addEdge(index3,index4);
00324         getVertex(index3)->addEdge(edge);
00325         getVertex(index4)->addEdge(edge);
00326     }
00327   
00328     getEdge(edge)->addFace(indexface);  
00329   
00330     if (!getIndexEdge(index4,index1,edge)) {
00331         edge = addEdge(index4,index1);
00332         getVertex(index4)->addEdge(edge);
00333         getVertex(index1)->addEdge(edge);
00334     }
00335   
00336     getEdge(edge)->addFace(indexface);
00337   
00338     if ((index1 == index2) || (index1 == index3) || (index1 == index4) || 
00339         (index2 == index3) || (index2 == index4) || (index3 == index4))
00340         face->setTAG(BROKEN);
00341 
00342     return m_faces.size()-1;
00343 }
00344 
00351 bool BOP_Mesh::containsFace(BOP_Faces *faces, BOP_Face *face) 
00352 {
00353   const BOP_IT_Faces facesEnd = faces->end();
00354     for(BOP_IT_Faces it = faces->begin();it!=facesEnd;it++) {
00355         if (face == *it)
00356             return true;
00357     }
00358     
00359     return false;
00360 }
00367 BOP_Edge* BOP_Mesh::getEdge(BOP_Indexs edges, BOP_Index v)
00368 {
00369   const BOP_IT_Indexs edgesEnd = edges.end();
00370     for(BOP_IT_Indexs it=edges.begin();it!=edgesEnd;it++){
00371         BOP_Edge *edge = m_edges[*it];
00372         if ((edge->getVertex1() == v) || (edge->getVertex2() == v))
00373             return edge;
00374     }
00375     return NULL;
00376 }
00377 
00384 BOP_Edge* BOP_Mesh::getEdge(BOP_Index v1, BOP_Index v2)
00385 {
00386 #ifdef HASH
00387     int minv;
00388     EdgeEntry *edge;
00389 
00390     /* figure out where and what to search for */
00391     if( v1 < v2 ) {
00392         minv = HASH(v1);
00393     } else {
00394         minv = HASH(v2);
00395         BOP_Index tmp = v1;
00396         v1 = v2;
00397         v2 = tmp;
00398     }
00399 
00400     /* if hash index valid, search the list and return match if found */
00401     if( minv < hashsize ) {
00402         for(edge = (EdgeEntry *)hash[minv].first;
00403                 edge; edge = edge->next ) {
00404             if(edge->v1 == v1 && edge->v2 == v2)
00405                 return m_edges[edge->index];
00406         }
00407     }
00408 #else
00409     const BOP_IT_Edges edgesEnd = m_edges.end();
00410     for(BOP_IT_Edges edge=m_edges.begin();edge!=edgesEnd;edge++) {
00411         if (((*edge)->getVertex1() == v1 && (*edge)->getVertex2() == v2) ||
00412             ((*edge)->getVertex1() == v2 && (*edge)->getVertex2() == v1)) 
00413             return *edge;
00414     } 
00415 #endif
00416     return NULL;
00417 }
00418 
00426 bool BOP_Mesh::getIndexEdge(BOP_Index v1, BOP_Index v2, BOP_Index &e)
00427 {
00428 #ifdef HASH
00429     int minv;
00430     EdgeEntry *edge;
00431 
00432     /* figure out what and where to look */
00433     if( v1 < v2 ) {
00434         minv = HASH(v1);
00435     } else {
00436         minv = HASH(v2);
00437         BOP_Index tmp = v1;
00438         v1 = v2;
00439         v2 = tmp;
00440     }
00441 
00442     /* if hash index is valid, look for a match */
00443     if( minv < hashsize ) {
00444         for(edge = (EdgeEntry *)hash[minv].first;
00445                 edge; edge = edge->next ) {
00446             if(edge->v1 == v1 && edge->v2 == v2)
00447                 break;
00448         }
00449 
00450         /* edge != NULL means match */
00451         if(edge) {
00452 #ifdef HASH_PRINTF_DEBUG
00453             printf ("found edge (%d %d)\n",v1,v2);
00454 #endif
00455             e = edge->index;
00456 #ifdef BOP_NEW_MERGE
00457             if( m_edges[e]->getUsed() == false ) {
00458                 m_edges[e]->setUsed(true);
00459                 m_vertexs[v1]->addEdge(e);
00460                 m_vertexs[v2]->addEdge(e);
00461             }
00462 #endif
00463             return true;
00464         }
00465 #ifdef HASH_PRINTF_DEBUG
00466         else
00467             printf ("didn't find edge (%d %d)\n",v1,v2);
00468 #endif
00469     }
00470 #else
00471     BOP_Index pos=0;
00472     const BOP_IT_Edges edgesEnd = m_edges.end();
00473     for(BOP_IT_Edges edge=m_edges.begin();edge!=edgesEnd;edge++,pos++) {
00474         if (((*edge)->getVertex1() == v1 && (*edge)->getVertex2() == v2) ||
00475             ((*edge)->getVertex1() == v2 && (*edge)->getVertex2() == v1)){
00476           e = pos;
00477           return true;
00478         }
00479     } 
00480 #endif
00481     return false;
00482 }
00483 
00490 BOP_Edge* BOP_Mesh::getEdge(BOP_Face *face, unsigned int edge)
00491 {
00492     if (face->size()==3)
00493         return getEdge((BOP_Face3 *)face,edge);
00494     else
00495         return getEdge((BOP_Face4 *)face,edge);
00496 }
00497 
00504 BOP_Edge* BOP_Mesh::getEdge(BOP_Face3 *face, unsigned int edge)
00505 {
00506     switch(edge){
00507     case 1:
00508         return getEdge(m_vertexs[face->getVertex(0)]->getEdges(),face->getVertex(1));
00509     case 2:
00510         return getEdge(m_vertexs[face->getVertex(1)]->getEdges(),face->getVertex(2));
00511     case 3:
00512         return getEdge(m_vertexs[face->getVertex(2)]->getEdges(),face->getVertex(0));
00513     };
00514   
00515     return NULL;
00516 }
00517 
00524 BOP_Edge * BOP_Mesh::getEdge(BOP_Face4 *face, unsigned int edge)
00525 {
00526     switch(edge){
00527     case 1:
00528         return getEdge(m_vertexs[face->getVertex(0)]->getEdges(),face->getVertex(1));
00529     case 2:
00530         return getEdge(m_vertexs[face->getVertex(1)]->getEdges(),face->getVertex(2));
00531     case 3:
00532         return getEdge(m_vertexs[face->getVertex(2)]->getEdges(),face->getVertex(3));
00533     case 4:
00534         return getEdge(m_vertexs[face->getVertex(3)]->getEdges(),face->getVertex(0));
00535     };
00536     
00537     return NULL;
00538 }
00539 
00547 BOP_Face* BOP_Mesh::getFace(BOP_Index v1, BOP_Index v2, BOP_Index v3) 
00548 {
00549     const BOP_IT_Faces facesEnd = m_faces.end();
00550     for(BOP_IT_Faces face=m_faces.begin();face!=facesEnd;face++) {
00551         if ((*face)->containsVertex(v1) && (*face)->containsVertex(v2) && 
00552             (*face)->containsVertex(v3))
00553             return (*face);
00554     } 
00555     return NULL;
00556 }
00557 
00566 bool BOP_Mesh::getIndexFace(BOP_Index v1, BOP_Index v2, BOP_Index v3, BOP_Index &f) 
00567 {
00568     BOP_Index pos=0;
00569     const BOP_IT_Faces facesEnd = m_faces.end();
00570     for(BOP_IT_Faces face=m_faces.begin();face!=facesEnd;face++,pos++) {
00571         if ((*face)->containsVertex(v1) && (*face)->containsVertex(v2) && 
00572             (*face)->containsVertex(v3)){
00573           f = pos;
00574           return true;
00575         }
00576     } 
00577     return false;
00578 }
00579 
00584 BOP_Vertexs &BOP_Mesh::getVertexs() 
00585 {
00586     return m_vertexs;
00587 } 
00588 
00593 BOP_Edges &BOP_Mesh::getEdges() 
00594 {
00595     return m_edges;
00596 } 
00597 
00602 BOP_Faces &BOP_Mesh::getFaces() 
00603 {
00604     return m_faces;
00605 } 
00606 
00612 BOP_Vertex* BOP_Mesh::getVertex(BOP_Index i)
00613 {
00614     return m_vertexs[i];
00615 }
00616 
00622 BOP_Edge* BOP_Mesh::getEdge(BOP_Index i) 
00623 {
00624     return m_edges[i];
00625 }
00626 
00632 BOP_Face* BOP_Mesh::getFace(BOP_Index i)
00633 {
00634     return m_faces[i];
00635 }
00636 
00641 unsigned int BOP_Mesh::getNumVertexs() 
00642 {
00643     return m_vertexs.size();
00644 }
00645 
00650 unsigned int BOP_Mesh::getNumEdges() 
00651 {
00652     return m_edges.size();
00653 }
00654 
00659 unsigned int BOP_Mesh::getNumFaces() 
00660 {
00661     return m_faces.size();
00662 }
00663 
00668 unsigned int BOP_Mesh::getNumVertexs(BOP_TAG tag) 
00669 {
00670     unsigned int count = 0;
00671     const BOP_IT_Vertexs vertexsEnd = m_vertexs.end();
00672     for(BOP_IT_Vertexs vertex=m_vertexs.begin();vertex!=vertexsEnd;vertex++) {
00673         if ((*vertex)->getTAG() == tag) count++;
00674     }
00675     return count;
00676 }
00681 unsigned int BOP_Mesh::getNumFaces(BOP_TAG tag) 
00682 {
00683     unsigned int count = 0;
00684     const BOP_IT_Faces facesEnd = m_faces.end();
00685     for(BOP_IT_Faces face=m_faces.begin();face!=facesEnd;face++) {
00686         if ((*face)->getTAG() == tag) count++;
00687     }
00688     return count;
00689 }
00690 
00697 static void removeBrokenFaces( BOP_Edge *edge, BOP_Mesh *mesh )
00698 {
00699     BOP_Faces m_faces = mesh->getFaces();
00700 
00701     BOP_Indexs edgeFaces = edge->getFaces();
00702     const BOP_IT_Indexs edgeFacesEnd = edgeFaces.end();
00703     for(BOP_IT_Indexs idxFace=edgeFaces.begin();idxFace!=edgeFacesEnd;
00704                idxFace++)
00705         m_faces[*idxFace]->setTAG(BROKEN);
00706 }
00707 
00713 BOP_Index BOP_Mesh::replaceVertexIndex(BOP_Index oldIndex, BOP_Index newIndex) 
00714 {
00715     BOP_IT_Indexs oldEdgeIndex;
00716     if (oldIndex==newIndex) return newIndex;
00717   
00718     // Update faces, edges and vertices  
00719     BOP_Vertex *oldVertex = m_vertexs[oldIndex];
00720     BOP_Vertex *newVertex = m_vertexs[newIndex];
00721     BOP_Indexs oldEdges = oldVertex->getEdges();
00722 
00723     // Update faces to the newIndex
00724     BOP_IT_Indexs oldEdgesEnd = oldEdges.end();
00725     for(oldEdgeIndex=oldEdges.begin();oldEdgeIndex!=oldEdgesEnd;
00726            oldEdgeIndex++) {
00727         BOP_Edge *edge = m_edges[*oldEdgeIndex];
00728         if ((edge->getVertex1()==oldIndex && edge->getVertex2()==newIndex) ||
00729             (edge->getVertex2()==oldIndex && edge->getVertex1()==newIndex)) {
00730             // Remove old edge  ==> set edge faces to BROKEN      
00731             removeBrokenFaces( edge, this );
00732             oldVertex->removeEdge(*oldEdgeIndex);
00733             newVertex->removeEdge(*oldEdgeIndex);
00734         }
00735         else {
00736             BOP_Indexs faces = edge->getFaces();
00737             const BOP_IT_Indexs facesEnd = faces.end();
00738             for(BOP_IT_Indexs face=faces.begin();face!=facesEnd;face++) {
00739                 if (m_faces[*face]->getTAG()!=BROKEN)
00740                     m_faces[*face]->replaceVertexIndex(oldIndex,newIndex);
00741             }
00742         }
00743     } 
00744 
00745     oldEdgesEnd = oldEdges.end();
00746     for(oldEdgeIndex=oldEdges.begin();oldEdgeIndex!=oldEdgesEnd;
00747            oldEdgeIndex++) {
00748         BOP_Edge * edge = m_edges[*oldEdgeIndex];
00749         BOP_Edge * edge2;
00750         BOP_Index v1 = edge->getVertex1();
00751     
00752         v1 = (v1==oldIndex?edge->getVertex2():v1);      
00753         if ((edge2 = getEdge(newIndex,v1)) == NULL) {
00754             edge->replaceVertexIndex(oldIndex,newIndex);
00755             if ( edge->getVertex1() == edge->getVertex2() ) {
00756                 removeBrokenFaces( edge, this );
00757                 oldVertex->removeEdge(*oldEdgeIndex);
00758             }
00759 #ifdef HASH
00760             rehashVertex(oldIndex,newIndex,v1);
00761 #endif
00762             newVertex->addEdge(*oldEdgeIndex);
00763         }
00764         else {
00765             BOP_Indexs faces = edge->getFaces();
00766             const BOP_IT_Indexs facesEnd = faces.end();
00767             for(BOP_IT_Indexs f=faces.begin();f!=facesEnd;f++) {
00768                 if (m_faces[*f]->getTAG()!=BROKEN)
00769                 edge2->addFace(*f);
00770             }
00771             BOP_Vertex *oppositeVertex = m_vertexs[v1];
00772             oppositeVertex->removeEdge(*oldEdgeIndex);
00773             edge->replaceVertexIndex(oldIndex,newIndex);
00774             if ( edge->getVertex1() == edge->getVertex2() ) {
00775                 removeBrokenFaces( edge, this );
00776                 oldVertex->removeEdge(*oldEdgeIndex);
00777                 newVertex->removeEdge(*oldEdgeIndex);
00778             }
00779 #ifdef HASH
00780             rehashVertex(oldIndex,newIndex,v1);
00781 #endif
00782         }
00783     }
00784     oldVertex->setTAG(BROKEN);
00785 
00786     return newIndex;
00787 }
00788 
00789 bool BOP_Mesh::isClosedMesh()
00790 {
00791     for(unsigned int i=0; i<m_edges.size(); i++) {
00792         BOP_Edge *edge = m_edges[i];
00793         BOP_Indexs faces = edge->getFaces();
00794         unsigned int count = 0;
00795         const BOP_IT_Indexs facesEnd = faces.end();
00796         for(BOP_IT_Indexs it = faces.begin();it!=facesEnd;it++) {
00797             if (m_faces[*it]->getTAG()!=BROKEN)
00798                 count++;
00799         }
00800 
00801         if ((count%2)!=0) return false;
00802     }
00803 
00804     return true;
00805 }
00806 
00807 
00808 #ifdef BOP_DEBUG
00809 /******************************************************************************
00810  * DEBUG METHODS                                                              * 
00811  * This functions are used to test the mesh state and debug program errors.   *
00812  ******************************************************************************/
00813 
00817 void BOP_Mesh::print() 
00818 {
00819     unsigned int i;
00820     cout << "--Faces--" << endl;
00821     for(i=0;i<m_faces.size();i++){
00822         cout << "Face " << i << ": " << m_faces[i] << endl;
00823     }
00824 
00825     cout << "--Vertices--" << endl;
00826     for(i=0;i<m_vertexs.size();i++){
00827         cout << "Point " << i << ": " << m_vertexs[i]->getPoint() << endl;
00828     }
00829 }
00830 
00834 void BOP_Mesh::printFormat(BOP_Faces *faces)
00835 {
00836     if (faces->size()) {
00837         for(unsigned int it=1;it<faces->size();it++) {
00838             if ((*faces)[it]->getTAG()!=BROKEN) {
00839                 cout << m_vertexs[(*faces)[it]->getVertex(0)]->getPoint() << " ";
00840                 cout << m_vertexs[(*faces)[it]->getVertex(1)]->getPoint() << " ";
00841                 cout << m_vertexs[(*faces)[it]->getVertex(2)]->getPoint() << endl;
00842             }
00843         }
00844     }
00845 }
00846 
00850 void BOP_Mesh::saveFormat(BOP_Faces *faces,char *filename)
00851 {
00852     ofstream fout(filename);
00853   
00854     if (!fout.is_open()) {
00855         cerr << "BOP_Mesh::saveFormat Error: Could not create file." << endl;
00856         return;
00857     }
00858 
00859     unsigned int count = 0;
00860     if (faces->size()) {
00861         for(unsigned int it=0;it<faces->size();it++) {
00862             if ((*faces)[it]->getTAG()!=BROKEN) {
00863                 count++;
00864             }
00865         }
00866     }
00867 
00868     fout << count << endl;
00869     if (faces->size()) {
00870         for(unsigned int it=0;it<faces->size();it++) {
00871             if ((*faces)[it]->getTAG()!=BROKEN){
00872                 fout << m_vertexs[(*faces)[it]->getVertex(0)]->getPoint() << " ";
00873                 fout << m_vertexs[(*faces)[it]->getVertex(1)]->getPoint() << " ";
00874                 fout << m_vertexs[(*faces)[it]->getVertex(2)]->getPoint() << endl;
00875             }
00876         }
00877     }
00878 
00879     fout.close();
00880 }
00881 
00885 void BOP_Mesh::printFormat()
00886 {
00887     cout << "--Vertices--" << endl;
00888     if (m_vertexs.size()>0) {
00889         cout << "{" << m_vertexs[0]->getPoint().x() << ",";
00890         cout << m_vertexs[0]->getPoint().y() << ",";
00891         cout << m_vertexs[0]->getPoint().z() << "}";
00892         for(unsigned int i=1;i<m_vertexs.size();i++) {
00893             cout << ",{" << m_vertexs[i]->getPoint().x() << ",";
00894             cout << m_vertexs[i]->getPoint().y() << ",";
00895             cout << m_vertexs[i]->getPoint().z() << "}";
00896         }
00897         cout << endl;
00898     }
00899 
00900     cout << "--Faces--" << endl;
00901     if (m_faces.size()>0) {
00902         cout << "{" << m_faces[0]->getVertex(0) << ",";
00903         cout << m_faces[0]->getVertex(1) << "," << m_faces[0]->getVertex(2) << "}";
00904         for(unsigned int i=1;i<m_faces.size();i++) {
00905             cout << ",{" << m_faces[i]->getVertex(0) << ",";
00906             cout << m_faces[i]->getVertex(1) << "," << m_faces[i]->getVertex(2) << "}";
00907         }
00908         cout << endl;
00909     }
00910 }
00911 
00915 void BOP_Mesh::printFace(BOP_Face *face, int col)
00916 {
00917   cout << "--Face" << endl;
00918     cout << m_vertexs[face->getVertex(0)]->getPoint();
00919     cout << " " << m_vertexs[face->getVertex(1)]->getPoint();
00920     cout << " " << m_vertexs[face->getVertex(2)]->getPoint();
00921     if (face->size()==4)
00922       cout << " " << m_vertexs[face->getVertex(3)]->getPoint();
00923     cout << " " << col << endl;
00924 }
00925 
00929 void BOP_Mesh::testMesh()
00930 {
00931 
00932     BOP_Face* cares[10];
00933     unsigned int nedges=0,i;
00934     for(i=0;i<m_edges.size();i++) {
00935         BOP_Edge *edge = m_edges[i];
00936         BOP_Indexs faces = edge->getFaces();
00937         unsigned int count = 0;
00938         const BOP_IT_Indexs facesEnd = faces.end();
00939         for(BOP_IT_Indexs it = faces.begin();it!=facesEnd;it++) {
00940             if (m_faces[*it]->getTAG()!=BROKEN) {
00941                 cares[count] = m_faces[*it];
00942                 count++;
00943                 
00944             }
00945         }
00946 
00947         if ((count%2)!=0) nedges++;
00948     }
00949     if (nedges)
00950       cout << nedges << " wrong edges." << endl;
00951     else
00952       cout << "well edges." << endl;
00953 
00954     unsigned int duplFaces = 0;
00955     unsigned int wrongFaces = 0;
00956     for(i=0;i<m_faces.size();i++){
00957       BOP_Face *faceI = m_faces[i];
00958       if (faceI->getTAG()==BROKEN)
00959         continue;
00960 
00961       if (testFace(faceI)){
00962         wrongFaces++;
00963         cout << "Wrong Face: " << faceI << endl;
00964       }
00965 
00966       for(unsigned int j=i+1;j<m_faces.size();j++){
00967         BOP_Face *faceJ = m_faces[j];
00968 
00969         if (faceJ->getTAG()==BROKEN)
00970           continue;
00971 
00972         if (testFaces(faceI,faceJ)){
00973           duplFaces++;
00974           cout << "Duplicate FaceI: " << faceI << endl;
00975           cout << "Duplicate FaceJ: " << faceJ << endl;
00976         }
00977       }
00978     }
00979 
00980     cout << duplFaces << " duplicate faces." << endl;
00981     cout << wrongFaces << " wrong faces." << endl;
00982 }
00983 
00987 bool BOP_Mesh::testFace(BOP_Face *face){
00988   
00989   for(unsigned int i=0;i<face->size();i++){
00990     for(unsigned int j=i+1;j<face->size();j++){
00991       if (face->getVertex(i)==face->getVertex(j))
00992     return true;
00993     }
00994   }
00995 
00996   return false;
00997 }
00998 
01002 bool BOP_Mesh::testFaces(BOP_Face *faceI, BOP_Face *faceJ){
01003 
01004   if (faceI->size()<faceJ->size()){
01005     for(unsigned int i=0;i<faceI->size();i++){
01006       if (!faceJ->containsVertex(faceI->getVertex(i)))
01007     return false;
01008     }
01009     //faceI->setTAG(BROKEN);
01010   }
01011   else{
01012     for(unsigned int i=0;i<faceJ->size();i++){
01013       if (!faceI->containsVertex(faceJ->getVertex(i)))
01014     return false;
01015     }
01016     //faceJ->setTAG(BROKEN);
01017   }
01018 
01019   return true;
01020 }
01021 
01025 void BOP_Mesh::testPlane(BOP_Face *face)
01026 {
01027     MT_Plane3 plane1(m_vertexs[face->getVertex(0)]->getPoint(), 
01028                      m_vertexs[face->getVertex(1)]->getPoint(),
01029                      m_vertexs[face->getVertex(2)]->getPoint());
01030 
01031     if (BOP_orientation(plane1,face->getPlane()) < 0) {   
01032         cout << "Test Plane " << face << " v1: ";
01033         cout << m_vertexs[face->getVertex(0)]->getPoint() << " v2: ";
01034         cout << m_vertexs[face->getVertex(1)]->getPoint() << " v3: ";
01035         cout << m_vertexs[face->getVertex(2)]->getPoint() << " plane: ";
01036         cout << face->getPlane() << endl;
01037         cout << "Incorrect vertices order!!! plane1: " << plane1 << " (";
01038         cout << BOP_orientation(plane1,face->getPlane()) << ") " <<  " invert ";
01039         cout <<  MT_Plane3(m_vertexs[face->getVertex(2)]->getPoint(),
01040                            m_vertexs[face->getVertex(1)]->getPoint(),
01041                            m_vertexs[face->getVertex(0)]->getPoint()) << endl;
01042         if (BOP_collinear(m_vertexs[face->getVertex(0)]->getPoint(),
01043                           m_vertexs[face->getVertex(1)]->getPoint(),
01044                           m_vertexs[face->getVertex(2)]->getPoint())) {
01045             cout << " COLLINEAR!!!" << endl;
01046         }
01047         else {
01048             cout << endl;
01049         }
01050     }
01051 }
01052 
01056 bool BOP_Mesh::testEdges(BOP_Faces *facesObj)
01057 {
01058     for(unsigned int i=0;i<m_edges.size();i++) {
01059         BOP_Edge *edge = m_edges[i];
01060         BOP_Indexs faces = edge->getFaces();
01061         unsigned int count = 0;
01062         const BOP_IT_Indexs facesEnd = faces.end();
01063         for(BOP_IT_Indexs it = faces.begin();it!=facesEnd;it++) {
01064             if ((m_faces[*it]->getTAG()!=BROKEN) && containsFace(facesObj,m_faces[*it]))
01065                 count++;
01066         }
01067         if ((count%2)!=0) {
01068             return false;
01069         }
01070     }
01071     
01072     return true;
01073 }
01074 
01078 void BOP_Mesh::updatePlanes() 
01079 {
01080   const BOP_IT_Faces facesEnd = m_faces.end();
01081     for(BOP_IT_Faces it = m_faces.begin();it!=facesEnd;it++) {
01082       BOP_Face *face = *it;
01083       MT_Plane3 plane(m_vertexs[face->getVertex(0)]->getPoint(), 
01084               m_vertexs[face->getVertex(1)]->getPoint(),
01085               m_vertexs[face->getVertex(2)]->getPoint());
01086       face->setPlane(plane);
01087     }
01088 }
01089 
01090 #endif