Blender V2.61 - r43446

BOP_Face2Face.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_Face2Face.h"
00036 #include "BOP_BBox.h"
00037 
00038 // TAGS for segment classification in x-segment creation
00039 // sA -> point of sA
00040 // sB -> point of sB
00041 // sX -> point of sA and SB
00042 #define sA_sB 12
00043 #define sB_sA 21
00044 #define sX_sA 31
00045 #define sA_sX 13
00046 #define sX_sB 32
00047 #define sB_sX 23
00048 #define sX_sX 33
00049     
00050 #define sA_sA_sB 112
00051 #define sB_sB_sA 221
00052 #define sB_sA_sA 211
00053 #define sA_sB_sB 122
00054 #define sA_sB_sA 121
00055 #define sB_sA_sB 212
00056 #define sA_sX_sB 132
00057 #define sB_sX_sA 231
00058 #define sX_sA_sB 312
00059 #define sX_sB_sA 321
00060 #define sA_sB_sX 123
00061 #define sB_sA_sX 213
00062 
00063 #define sA_sA_sB_sB 1122
00064 #define sB_sB_sA_sA 2211
00065 #define sA_sB_sA_sB 1212
00066 #define sB_sA_sB_sA 2121
00067 #define sA_sB_sB_sA 1221
00068 #define sB_sA_sA_sB 2112
00069 
00070 void BOP_intersectCoplanarFaces(BOP_Mesh*  mesh, 
00071                                 BOP_Faces* facesB, 
00072                                 BOP_Face*  faceA, 
00073                                 BOP_Face*  faceB, 
00074                                 bool       invert);
00075 
00076 void BOP_intersectCoplanarFaces(BOP_Mesh*   mesh, 
00077                                 BOP_Faces*  facesB, 
00078                                 BOP_Face*   faceB, 
00079                                 BOP_Segment sA, 
00080                                 MT_Plane3   planeA, 
00081                                 bool        invert);
00082 
00083 void BOP_intersectNonCoplanarFaces(BOP_Mesh*  mesh, 
00084                                    BOP_Faces* facesA,  
00085                                    BOP_Faces* facesB, 
00086                                    BOP_Face*  faceA, 
00087                                    BOP_Face*  faceB);
00088 
00089 void BOP_getPoints(BOP_Mesh*    mesh, 
00090                    BOP_Face*    faceA, 
00091                    BOP_Segment& sA, 
00092                    MT_Plane3    planeB, 
00093                    MT_Point3*   points, 
00094                    unsigned int*         faces, 
00095                    unsigned int&         size, 
00096                    unsigned int         faceValue);
00097 
00098 void BOP_mergeSort(MT_Point3 *points, unsigned int *face, unsigned int &size, bool &invertA, bool &invertB);
00099 
00100 void BOP_createXS(BOP_Mesh*    mesh, 
00101                   BOP_Face*    faceA, 
00102                   BOP_Face*    faceB, 
00103                   BOP_Segment  sA, 
00104                   BOP_Segment  sB, 
00105                   bool         invert, 
00106                   BOP_Segment* segments);    
00107 
00108 void BOP_createXS(BOP_Mesh*    mesh, 
00109                   BOP_Face*    faceA, 
00110                   BOP_Face*    faceB, 
00111                   MT_Plane3    planeA, 
00112                   MT_Plane3    planeB, 
00113                   BOP_Segment  sA, 
00114                   BOP_Segment  sB, 
00115                   bool         invert, 
00116                   BOP_Segment* segments);    
00117 
00118 BOP_Index BOP_getVertexIndex(BOP_Mesh* mesh, 
00119                        MT_Point3 point, 
00120                        unsigned int       cfgA, 
00121                        unsigned int       cfgB, 
00122                        BOP_Index       vA, 
00123                        BOP_Index       vB, 
00124                        bool      invert);
00125 
00126 BOP_Index BOP_getVertexIndex(BOP_Mesh *mesh, MT_Point3 point, unsigned int cfg, BOP_Index v);
00127 
00128 void triangulate(BOP_Mesh *mesh,  BOP_Faces *faces, BOP_Face *face, BOP_Segment s);
00129 
00130 BOP_Face *BOP_getOppositeFace(BOP_Mesh*  mesh, 
00131                               BOP_Faces* faces, 
00132                               BOP_Face*  face, 
00133                               BOP_Edge*  edge);
00134 
00135 bool BOP_overlap(MT_Vector3 normal, 
00136                  MT_Point3  p1, 
00137                  MT_Point3  p2, 
00138                  MT_Point3  p3, 
00139                  MT_Point3  q1, 
00140                  MT_Point3  q2, 
00141                  MT_Point3  q3);
00142 
00143 void BOP_mergeVertexs(BOP_Mesh *mesh, unsigned int firstFace);
00144 
00145 
00161 void BOP_Face2Face(BOP_Mesh *mesh, BOP_Faces *facesA, BOP_Faces *facesB)
00162 {
00163     for(unsigned int idxFaceA=0;idxFaceA<facesA->size();idxFaceA++) {
00164         BOP_Face *faceA = (*facesA)[idxFaceA];
00165         MT_Plane3 planeA = faceA->getPlane();
00166         MT_Point3 p1 = mesh->getVertex(faceA->getVertex(0))->getPoint();
00167         MT_Point3 p2 = mesh->getVertex(faceA->getVertex(1))->getPoint();
00168         MT_Point3 p3 = mesh->getVertex(faceA->getVertex(2))->getPoint();
00169 
00170         /* get (or create) bounding box for face A */
00171         if( faceA->getBBox() == NULL )
00172             faceA->setBBox(p1,p2,p3);
00173         BOP_BBox *boxA = faceA->getBBox();
00174 
00175     /* start checking B faces with the previously stored split index */
00176 
00177         for(unsigned int idxFaceB=faceA->getSplit();
00178             idxFaceB<facesB->size() && (faceA->getTAG() != BROKEN) && (faceA->getTAG() != PHANTOM);) {
00179             BOP_Face *faceB = (*facesB)[idxFaceB];
00180             faceA->setSplit(idxFaceB);
00181             if ((faceB->getTAG() != BROKEN) && (faceB->getTAG() != PHANTOM)) {
00182 
00183                 /* get (or create) bounding box for face B */
00184                 if( faceB->getBBox() == NULL ) {
00185                     faceB->setBBox(mesh->getVertex(faceB->getVertex(0))->getPoint(),
00186                                    mesh->getVertex(faceB->getVertex(1))->getPoint(),
00187                                    mesh->getVertex(faceB->getVertex(2))->getPoint());
00188                 }
00189                 BOP_BBox *boxB = faceB->getBBox();
00190 
00191                 if (boxA->intersect(*boxB)) {
00192                     MT_Plane3 planeB = faceB->getPlane();
00193                     if (BOP_containsPoint(planeB,p1) &&
00194                             BOP_containsPoint(planeB,p2) &&
00195                             BOP_containsPoint(planeB,p3))
00196                     {
00197                         if (BOP_orientation(planeB,planeA)>0) {
00198                             BOP_intersectCoplanarFaces(mesh,facesB,faceA,faceB,false);
00199                         }
00200                     }
00201                     else {
00202                         BOP_intersectNonCoplanarFaces(mesh,facesA,facesB,faceA,faceB);
00203                     }
00204                 }
00205             }
00206             idxFaceB++;
00207         }
00208     }
00209     
00210     
00211     // Clean broken faces from facesA
00212     BOP_IT_Faces it;
00213     it = facesA->begin();
00214     while (it != facesA->end()) {
00215         BOP_Face *face = *it;
00216         if (face->getTAG() == BROKEN) it = facesA->erase(it);
00217         else it++;
00218     }
00219     /*
00220     it = facesB->begin();
00221     while (it != facesB->end()) {
00222         BOP_Face *face = *it;
00223         if (face->getTAG() == BROKEN) it = facesB->erase(it);
00224         else it++;
00225     }
00226     */
00227 }
00228 
00235 void BOP_sew(BOP_Mesh *mesh, BOP_Faces *facesA, BOP_Faces *facesB)
00236 {
00237     for(unsigned int idxFaceB = 0; idxFaceB < facesB->size(); idxFaceB++) {
00238         BOP_Face *faceB = (*facesB)[idxFaceB];
00239         MT_Plane3 planeB = faceB->getPlane();
00240         MT_Point3 p1 = mesh->getVertex(faceB->getVertex(0))->getPoint();
00241         MT_Point3 p2 = mesh->getVertex(faceB->getVertex(1))->getPoint();
00242         MT_Point3 p3 = mesh->getVertex(faceB->getVertex(2))->getPoint();
00243         
00244         for(unsigned int idxFaceA = 0;
00245             idxFaceA < facesA->size() &&
00246             faceB->getTAG() != BROKEN &&
00247             faceB->getTAG() != PHANTOM;
00248             idxFaceA++) {
00249             BOP_Face *faceA = (*facesA)[idxFaceA];
00250             if ((faceA->getTAG() != BROKEN)&&(faceA->getTAG() != PHANTOM)) {
00251                 MT_Plane3 planeA = faceA->getPlane();
00252                 if (BOP_containsPoint(planeA,p1) && 
00253                     BOP_containsPoint(planeA,p2) && 
00254                     BOP_containsPoint(planeA,p3)) {
00255                     if (BOP_orientation(planeA,planeB) > 0) {
00256                         BOP_intersectCoplanarFaces(mesh,facesA,faceB,faceA,true);
00257                     }
00258                 }
00259             }
00260         }
00261     }
00262 }
00263 
00272 void BOP_intersectCoplanarFaces(BOP_Mesh*  mesh,
00273                                 BOP_Faces* facesB, 
00274                                 BOP_Face*  faceA, 
00275                                 BOP_Face*  faceB, 
00276                                 bool       invert)
00277 {
00278     unsigned int oldSize = facesB->size();
00279     unsigned int originalFaceB = faceB->getOriginalFace();    
00280     
00281     MT_Point3 p1 = mesh->getVertex(faceA->getVertex(0))->getPoint();
00282     MT_Point3 p2 = mesh->getVertex(faceA->getVertex(1))->getPoint();
00283     MT_Point3 p3 = mesh->getVertex(faceA->getVertex(2))->getPoint();
00284     
00285     MT_Vector3 normal(faceA->getPlane().x(),faceA->getPlane().y(),faceA->getPlane().z());
00286     
00287     MT_Vector3 p1p2 = p2-p1;
00288     
00289     MT_Plane3 plane1((p1p2.cross(normal).normalized()),p1);
00290     
00291     BOP_Segment sA;
00292     sA.m_cfg1 = BOP_Segment::createVertexCfg(1);
00293     sA.m_v1 = faceA->getVertex(0);
00294     sA.m_cfg2 = BOP_Segment::createVertexCfg(2);
00295     sA.m_v2 = faceA->getVertex(1);
00296     
00297     BOP_intersectCoplanarFaces(mesh,facesB,faceB,sA,plane1,invert);
00298     
00299     MT_Vector3 p2p3 = p3-p2;
00300     MT_Plane3 plane2((p2p3.cross(normal).normalized()),p2);
00301     
00302     sA.m_cfg1 = BOP_Segment::createVertexCfg(2);
00303     sA.m_v1 = faceA->getVertex(1);
00304     sA.m_cfg2 = BOP_Segment::createVertexCfg(3);
00305     sA.m_v2 = faceA->getVertex(2);
00306   
00307     if (faceB->getTAG() == BROKEN) {
00308         for(unsigned int idxFace = oldSize; idxFace < facesB->size(); idxFace++) {
00309             BOP_Face *face = (*facesB)[idxFace];
00310             if (face->getTAG() != BROKEN && originalFaceB == face->getOriginalFace())
00311                 BOP_intersectCoplanarFaces(mesh,facesB,face,sA,plane2,invert);
00312         }
00313     }
00314     else {
00315         BOP_intersectCoplanarFaces(mesh,facesB,faceB,sA,plane2,invert);
00316     }
00317   
00318     MT_Vector3 p3p1 = p1-p3;
00319     MT_Plane3 plane3((p3p1.cross(normal).safe_normalized()),p3);
00320     
00321     sA.m_cfg1 = BOP_Segment::createVertexCfg(3);
00322     sA.m_v1 = faceA->getVertex(2);
00323     sA.m_cfg2 = BOP_Segment::createVertexCfg(1);
00324     sA.m_v2 = faceA->getVertex(0);
00325   
00326     if (faceB->getTAG() == BROKEN) {
00327         for(unsigned int idxFace = oldSize; idxFace < facesB->size(); idxFace++) {
00328             BOP_Face *face = (*facesB)[idxFace];
00329             if (face->getTAG() != BROKEN && originalFaceB == face->getOriginalFace())
00330                 BOP_intersectCoplanarFaces(mesh,facesB,face,sA,plane3,invert);
00331         }
00332     }
00333     else {
00334         BOP_intersectCoplanarFaces(mesh,facesB,faceB,sA,plane3,invert);
00335     } 
00336 }
00337 
00347 void BOP_intersectCoplanarFaces(BOP_Mesh*   mesh, 
00348                                 BOP_Faces*  facesB, 
00349                                 BOP_Face*   faceB, 
00350                                 BOP_Segment sA, 
00351                                 MT_Plane3   planeA, 
00352                                 bool        invert)
00353 {
00354     BOP_Segment sB = BOP_splitFace(planeA,mesh,faceB);
00355 
00356     if (BOP_Segment::isDefined(sB.m_cfg1)) {
00357         BOP_Segment xSegment[2];
00358         BOP_createXS(mesh,NULL,faceB,planeA,MT_Plane3(),sA,sB,invert,xSegment);
00359         if (BOP_Segment::isDefined(xSegment[1].m_cfg1)) {
00360             unsigned int sizefaces = mesh->getNumFaces();
00361             triangulate(mesh,facesB,faceB,xSegment[1]);
00362             BOP_mergeVertexs(mesh,sizefaces);
00363         }
00364     }
00365 }
00366 
00374 void BOP_intersectNonCoplanarFaces(BOP_Mesh *mesh, 
00375                                    BOP_Faces *facesA, 
00376                                    BOP_Faces *facesB, 
00377                                    BOP_Face *faceA, 
00378                                    BOP_Face *faceB)
00379 {
00380     // Obtain segments of faces A and B from the intersection with their planes
00381     BOP_Segment sA = BOP_splitFace(faceB->getPlane(),mesh,faceA);
00382     BOP_Segment sB = BOP_splitFace(faceA->getPlane(),mesh,faceB);
00383     
00384     if (BOP_Segment::isDefined(sA.m_cfg1) && BOP_Segment::isDefined(sB.m_cfg1)) {    
00385         // There is an intesection, build the X-segment
00386         BOP_Segment xSegment[2];
00387         BOP_createXS(mesh,faceA,faceB,sA,sB,false,xSegment);
00388         
00389         unsigned int sizefaces = mesh->getNumFaces();
00390         triangulate(mesh,facesA,faceA,xSegment[0]);
00391         BOP_mergeVertexs(mesh,sizefaces);
00392     
00393         sizefaces = mesh->getNumFaces();
00394         triangulate(mesh,facesB,faceB,xSegment[1]);
00395         BOP_mergeVertexs(mesh,sizefaces);
00396     }
00397 }
00398 
00404 void BOP_mergeVertexs(BOP_Mesh *mesh, unsigned int firstFace)
00405 {
00406     unsigned int numFaces = mesh->getNumFaces();
00407     for(unsigned int idxFace = firstFace; idxFace < numFaces; idxFace++) {
00408         BOP_Face *face = mesh->getFace(idxFace);
00409         if ((face->getTAG() != BROKEN) && (face->getTAG() != PHANTOM)) {
00410             MT_Point3 vertex1 = mesh->getVertex(face->getVertex(0))->getPoint();
00411             MT_Point3 vertex2 = mesh->getVertex(face->getVertex(1))->getPoint();
00412             MT_Point3 vertex3 = mesh->getVertex(face->getVertex(2))->getPoint();
00413             if (BOP_collinear(vertex1,vertex2,vertex3)) // collinear triangle 
00414                 face->setTAG(PHANTOM);
00415         }
00416     }
00417 }
00418 
00430 void BOP_getPoints(BOP_Mesh*    mesh, 
00431                    BOP_Face*    faceA, 
00432                    BOP_Segment& sA, 
00433                    MT_Plane3    planeB, 
00434                    MT_Point3*   points, 
00435                    unsigned int*         faces, 
00436                    unsigned int&         size, 
00437                    unsigned int          faceValue) 
00438 {
00439     MT_Point3 p1,p2;  
00440   
00441     if (BOP_Segment::isDefined(sA.m_cfg1)) {
00442         if (BOP_Segment::isEdge(sA.m_cfg1)) {
00443             // the new point becomes of split faceA edge 
00444             p1 = BOP_splitEdge(planeB,mesh,faceA,BOP_Segment::getEdge(sA.m_cfg1));
00445         }
00446         else if (BOP_Segment::isVertex(sA.m_cfg1)) {
00447             // the new point becomes of vertex faceA
00448             p1 =  mesh->getVertex(BOP_Segment::getVertex(sA.m_v1))->getPoint();
00449         }
00450 
00451         if (BOP_Segment::isDefined(sA.m_cfg2)) {
00452             if (BOP_Segment::isEdge(sA.m_cfg2)) {
00453                 p2 = BOP_splitEdge(planeB,mesh,faceA,BOP_Segment::getEdge(sA.m_cfg2));
00454             }
00455             else if (BOP_Segment::isVertex(sA.m_cfg2)) { 
00456                 p2 =  mesh->getVertex(BOP_Segment::getVertex(sA.m_v2))->getPoint();
00457             }
00458             points[size] = p1;
00459             points[size+1] = p2;
00460             faces[size] = faceValue;
00461             faces[size+1] = faceValue;
00462             size += 2;
00463         }
00464     
00465         else {
00466             points[size] = p1;
00467             faces[size] = faceValue;
00468             size++;
00469         }
00470     }
00471 }
00472 
00480 void BOP_mergeSort(MT_Point3 *points, unsigned int *face, unsigned int &size, bool &invertA, bool &invertB) {
00481     MT_Point3 sortedPoints[4];
00482     unsigned int sortedFaces[4], position[4];
00483     unsigned int i;
00484     if (size == 2) {
00485 
00486         // Trivial case, only test the merge ...
00487         if (BOP_fuzzyZero(points[0].distance(points[1]))) {
00488             face[0] = 3;
00489             size--;
00490         }
00491     }
00492     else {
00493         // size is 3 or 4
00494         // Get segment extreme points
00495         MT_Scalar maxDistance = -1;
00496         for(i=0;i<size-1;i++){
00497             for(unsigned int j=i+1;j<size;j++){
00498                 MT_Scalar distance = points[i].distance(points[j]);
00499                 if (distance > maxDistance){
00500                     maxDistance = distance;
00501                     position[0] = i;
00502                     position[size-1] = j;
00503                 }
00504             }
00505         }
00506 
00507         // Get segment inner points
00508         position[1] = position[2] = size;
00509         for(i=0;i<size;i++){
00510             if ((i != position[0]) && (i != position[size-1])){
00511                 if (position[1] == size) position[1] = i;
00512                 else position[2] = i;
00513             }
00514         }
00515 
00516         // Get inner points
00517         if (position[2] < size) {
00518             MT_Scalar d1 = points[position[1]].distance(points[position[0]]);
00519             MT_Scalar d2 = points[position[2]].distance(points[position[0]]);
00520             if (d1 > d2) {
00521                 unsigned int aux = position[1];
00522                 position[1] = position[2];
00523                 position[2] = aux;
00524             }
00525         }
00526 
00527         // Sort data
00528         for(i=0;i<size;i++) {
00529             sortedPoints[i] = points[position[i]];
00530             sortedFaces[i] = face[position[i]];
00531         }
00532 
00533         invertA = false;
00534         invertB = false;
00535         if (face[1] == 1) {
00536 
00537             // invertAø?
00538             for(i=0;i<size;i++) {
00539                 if (position[i] == 1) {
00540                     invertA = true;
00541                         break;
00542                     }
00543                     else if (position[i] == 0) break;
00544                 }
00545 
00546             // invertBø?
00547             if (size == 4) {
00548                 for(i=0;i<size;i++) {
00549                     if (position[i] == 3) {
00550                         invertB = true;
00551                         break;
00552                     }
00553                     else if (position[i] == 2) break;
00554                 }
00555             }
00556         }
00557         else if (face[1] == 2) {
00558             // invertBø?
00559             for(i=0;i<size;i++) {
00560                 if (position[i] == 2) {
00561                     invertB = true;
00562                     break;
00563                 }
00564                 else if (position[i] == 1) break;
00565             }
00566         }
00567 
00568 
00569         // Merge data
00570         MT_Scalar d1 = sortedPoints[1].distance(sortedPoints[0]);
00571         MT_Scalar d2 = sortedPoints[1].distance(sortedPoints[2]);
00572         if (BOP_fuzzyZero(d1) && sortedFaces[1] != sortedFaces[0]) {
00573             if (BOP_fuzzyZero(d2) && sortedFaces[1] != sortedFaces[2])  {
00574                 if (d1 < d2) {
00575                     // merge 0 and 1
00576                     sortedFaces[0] = 3;
00577                     for(i = 1; i<size-1;i++) {
00578                         sortedPoints[i] = sortedPoints[i+1];
00579                         sortedFaces[i] = sortedFaces[i+1];
00580                     }
00581                     size--;
00582                     if (size == 3) {
00583                         // merge 1 and 2 ???
00584                         d1 = sortedPoints[1].distance(sortedPoints[2]);
00585                         if (BOP_fuzzyZero(d1) && sortedFaces[1] != sortedFaces[2])  {
00586                             // merge!
00587                             sortedFaces[1] = 3;
00588                             size--;
00589                         }
00590                     }
00591                 }
00592                 else {
00593                     // merge 1 and 2
00594                     sortedFaces[1] = 3;
00595                     for(i = 2; i<size-1;i++) {
00596                         sortedPoints[i] = sortedPoints[i+1];
00597                         sortedFaces[i] = sortedFaces[i+1];
00598                     }
00599                     size--;
00600                 }        
00601             }
00602             else {
00603                 // merge 0 and 1
00604                 sortedFaces[0] = 3;
00605                 for(i = 1; i<size-1;i++) {
00606                     sortedPoints[i] = sortedPoints[i+1];
00607                     sortedFaces[i] = sortedFaces[i+1];
00608                 }
00609                 size--;
00610                 if (size == 3) {
00611                     // merge 1 i 2 ???
00612                     d1 = sortedPoints[1].distance(sortedPoints[2]);
00613                     if (BOP_fuzzyZero(d1) && sortedFaces[1] != sortedFaces[2])  {
00614                         // merge!
00615                         sortedFaces[1] = 3;
00616                         size--;
00617                     }
00618                 }
00619             }     
00620         }
00621         else {
00622             if (BOP_fuzzyZero(d2) && sortedFaces[1] != sortedFaces[2])  {
00623                 // merge 1 and 2
00624                 sortedFaces[1] = 3;
00625                 for(i = 2; i<size-1;i++) {
00626                     sortedPoints[i] = sortedPoints[i+1];
00627                     sortedFaces[i] = sortedFaces[i+1];
00628                 }
00629                 size--;
00630             }
00631             else if (size == 4) {
00632                 d1 = sortedPoints[2].distance(sortedPoints[3]);
00633                 if (BOP_fuzzyZero(d1) && sortedFaces[2] != sortedFaces[3])  {
00634                     // merge 2 and 3
00635                     sortedFaces[2] = 3;
00636                     size--;
00637                 }
00638             }
00639         }
00640     
00641         // Merge initial points ...
00642         for(i=0;i<size;i++) {
00643             points[i] = sortedPoints[i];
00644             face[i] = sortedFaces[i];
00645         }
00646 
00647     }
00648 }
00649 
00650 
00661 void BOP_createXS(BOP_Mesh*    mesh,
00662                   BOP_Face*    faceA,
00663                   BOP_Face*    faceB,
00664                   BOP_Segment  sA,
00665                   BOP_Segment  sB,
00666                   bool         invert,
00667                   BOP_Segment* segments) {
00668     BOP_createXS(mesh, faceA, faceB, faceA->getPlane(), faceB->getPlane(),
00669                  sA, sB, invert, segments);
00670 }
00671 
00684 void BOP_createXS(BOP_Mesh*    mesh, 
00685                   BOP_Face*    faceA, 
00686                   BOP_Face*    faceB, 
00687                   MT_Plane3    planeA, 
00688                   MT_Plane3    planeB, 
00689                   BOP_Segment  sA, 
00690                   BOP_Segment  sB, 
00691                   bool         invert, 
00692                   BOP_Segment* segments)
00693 {    
00694     MT_Point3 points[4];  // points of the segments
00695     unsigned int face[4]; // relative face indexs (1 => faceA, 2 => faceB)
00696     unsigned int size = 0;  // size of points and relative face indexs
00697   
00698     BOP_getPoints(mesh, faceA, sA, planeB, points, face, size, 1);
00699     BOP_getPoints(mesh, faceB, sB, planeA, points, face, size, 2);
00700 
00701     bool invertA = false;
00702     bool invertB = false;
00703     BOP_mergeSort(points,face,size,invertA,invertB);
00704 
00705     if (invertA) sA.invert();
00706     if (invertB) sB.invert();
00707     
00708     // Compute the configuration label
00709     unsigned int label = 0;
00710     for(unsigned int i =0; i < size; i++) {
00711         label = face[i]+label*10;    
00712     }
00713 
00714     if (size == 1) {
00715         // Two coincident points
00716         segments[0].m_cfg1 = sA.m_cfg1;
00717         segments[1].m_cfg1 = sB.m_cfg1;
00718         
00719         segments[0].m_v1 = BOP_getVertexIndex(mesh, points[0], sA.m_cfg1, sB.m_cfg1,
00720                                               sA.m_v1, sB.m_v1, invert);
00721         segments[1].m_v1 = segments[0].m_v1;
00722         segments[0].m_cfg2 = segments[1].m_cfg2 = BOP_Segment::createUndefinedCfg();
00723     }
00724     else if (size == 2) {
00725         switch(label) {
00726         // Two non-coincident points
00727         case sA_sB:
00728         case sB_sA:
00729             segments[0].m_cfg1 = 
00730             segments[1].m_cfg1 = 
00731             segments[0].m_cfg2 = 
00732             segments[1].m_cfg2 = BOP_Segment::createUndefinedCfg();
00733             break;
00734       
00735         // Two coincident points and one non-coincident of sA
00736         case sA_sX:
00737             segments[0].m_cfg1 = sA.m_cfg2;
00738             segments[1].m_cfg1 = sB.m_cfg1;
00739             segments[0].m_v1 = BOP_getVertexIndex(mesh, points[1], sA.m_cfg2, sB.m_cfg1,
00740                                                   sA.m_v2, sB.m_v1, invert);
00741             segments[1].m_v1 = segments[0].m_v1;
00742             
00743             segments[0].m_cfg2 = BOP_Segment::createUndefinedCfg();
00744             segments[1].m_cfg2 = BOP_Segment::createUndefinedCfg();
00745             break;
00746         case sX_sA:
00747             segments[0].m_cfg1 = sA.m_cfg1;
00748             segments[1].m_cfg1 = sB.m_cfg1;
00749             segments[0].m_v1 = BOP_getVertexIndex(mesh, points[0], sA.m_cfg1, sB.m_cfg1,
00750                                                   sA.m_v1, sB.m_v1, invert);
00751             segments[1].m_v1 = segments[0].m_v1;
00752             
00753             segments[0].m_cfg2 = BOP_Segment::createUndefinedCfg();
00754             segments[1].m_cfg2 = BOP_Segment::createUndefinedCfg();
00755             break;
00756       
00757         // Two coincident points and one non-coincident of sB
00758         case sB_sX:
00759             segments[0].m_cfg1 = sA.m_cfg1;
00760             segments[1].m_cfg1 = sB.m_cfg2;
00761             segments[0].m_v1 = BOP_getVertexIndex(mesh, points[1], sA.m_cfg1, sB.m_cfg2, 
00762                                                   sA.m_v1, sB.m_v2, invert);
00763             segments[1].m_v1 = segments[0].m_v1;
00764             
00765             segments[0].m_cfg2 = BOP_Segment::createUndefinedCfg();
00766             segments[1].m_cfg2 = BOP_Segment::createUndefinedCfg();
00767             break;
00768         case sX_sB:
00769             segments[0].m_cfg1 = sA.m_cfg1;
00770             segments[1].m_cfg1 = sB.m_cfg1;
00771             segments[0].m_v1 = BOP_getVertexIndex(mesh, points[0], sA.m_cfg1, sB.m_cfg1, 
00772                                                   sA.m_v1, sB.m_v1, invert);
00773             segments[1].m_v1 = segments[0].m_v1;
00774         
00775             segments[0].m_cfg2 = BOP_Segment::createUndefinedCfg();
00776             segments[1].m_cfg2 = BOP_Segment::createUndefinedCfg();
00777             break;
00778       
00779         // coincident points 2-2
00780         case sX_sX:
00781             segments[0].m_cfg1 = sA.m_cfg1;
00782             segments[1].m_cfg1 = sB.m_cfg1;          
00783             segments[0].m_v1 = BOP_getVertexIndex(mesh, points[0], sA.m_cfg1, sB.m_cfg1, 
00784                                                   sA.m_v1, sB.m_v1, invert);
00785             segments[1].m_v1 = segments[0].m_v1;
00786             
00787             segments[0].m_cfg2 = sA.m_cfg2;
00788             segments[1].m_cfg2 = sB.m_cfg2;          
00789             segments[0].m_v2 = BOP_getVertexIndex(mesh, points[1], sA.m_cfg2, sB.m_cfg2, 
00790                                                   sA.m_v2, sB.m_v2, invert);
00791             segments[1].m_v2 = segments[0].m_v2;
00792             break;
00793         
00794         default:
00795             break; 
00796         }
00797     }
00798     else if (size == 3) {
00799         switch(label) {
00800         case sA_sA_sB:
00801         case sB_sA_sA:
00802         case sA_sB_sB:
00803         case sB_sB_sA:
00804             segments[0].m_cfg1 = 
00805             segments[1].m_cfg1 = 
00806             segments[0].m_cfg2 = 
00807             segments[1].m_cfg2 = BOP_Segment::createUndefinedCfg();
00808             break;
00809       
00810         case sA_sB_sA:
00811             segments[1].m_v1 = BOP_getVertexIndex(mesh,points[1],sB.m_cfg1,sB.m_v1);
00812             segments[1].m_cfg1 = sB.m_cfg1;
00813             segments[1].m_cfg2 = BOP_Segment::createUndefinedCfg();
00814             segments[0].m_cfg1 = sA.getConfig();
00815             segments[0].m_cfg2 = BOP_Segment::createUndefinedCfg();
00816             segments[0].m_v1 = segments[1].m_v1;
00817             break;
00818       
00819         case sB_sA_sB:
00820             segments[0].m_v1 = BOP_getVertexIndex(mesh,points[1],sA.m_cfg1,sA.m_v1);
00821             segments[0].m_cfg1 = sA.m_cfg1;
00822             segments[0].m_cfg2 = BOP_Segment::createUndefinedCfg();
00823             segments[1].m_cfg1 = sB.getConfig();
00824             segments[1].m_cfg2 = BOP_Segment::createUndefinedCfg();
00825             segments[1].m_v1 = segments[0].m_v1;
00826             break;
00827       
00828         case sA_sX_sB:
00829             segments[0].m_cfg1 = sA.m_cfg2;
00830             segments[1].m_cfg1 = sB.m_cfg1;          
00831             segments[0].m_v1 = BOP_getVertexIndex(mesh, points[1], sA.m_cfg2, sB.m_cfg1, 
00832                                                   sA.m_v2, sB.m_v1, invert);
00833             segments[1].m_v1 = segments[0].m_v1;
00834             segments[0].m_cfg2 = BOP_Segment::createUndefinedCfg();
00835             segments[1].m_cfg2 = BOP_Segment::createUndefinedCfg();
00836             break;
00837     
00838         case sB_sX_sA:
00839             segments[0].m_cfg1 = sA.m_cfg1;
00840             segments[1].m_cfg1 = sB.m_cfg2;          
00841             segments[0].m_v1 = BOP_getVertexIndex(mesh, points[1], sA.m_cfg1, sB.m_cfg2, 
00842                                                   sA.m_v1, sB.m_v2, invert);
00843             segments[1].m_v1 = segments[0].m_v1;
00844             segments[0].m_cfg2 = BOP_Segment::createUndefinedCfg();
00845             segments[1].m_cfg2 = BOP_Segment::createUndefinedCfg();
00846             break;
00847       
00848         case sX_sA_sB:
00849             segments[0].m_cfg1 = sA.m_cfg1;
00850             segments[1].m_cfg1 = sB.m_cfg1;          
00851             segments[0].m_v1 = BOP_getVertexIndex(mesh, points[0], sA.m_cfg1, sB.m_cfg1,
00852                                                   sA.m_v1, sB.m_v1, invert);
00853             segments[1].m_v1 = segments[0].m_v1;
00854             
00855             segments[0].m_cfg2 = sA.m_cfg2;
00856             segments[1].m_cfg2 = sB.getConfig();
00857             segments[0].m_v2 = BOP_getVertexIndex(mesh, points[1], sA.m_cfg2, sA.m_v2);
00858             segments[1].m_v2 = segments[0].m_v2;
00859             break;
00860       
00861         case sX_sB_sA:
00862             segments[0].m_cfg1 = sA.m_cfg1;
00863             segments[1].m_cfg1 = sB.m_cfg1;          
00864             segments[0].m_v1 = BOP_getVertexIndex(mesh, points[0], sA.m_cfg1, sB.m_cfg1,
00865                                                   sA.m_v1, sB.m_v1, invert);
00866             segments[1].m_v1 = segments[0].m_v1;
00867             
00868             segments[0].m_cfg2 = sA.getConfig();
00869             segments[1].m_cfg2 = sB.m_cfg2;
00870             segments[0].m_v2 = BOP_getVertexIndex(mesh,points[1],sB.m_cfg2,sB.m_v2);
00871             segments[1].m_v2 = segments[0].m_v2;
00872             break;
00873       
00874         case sA_sB_sX:
00875             segments[0].m_cfg1 = sA.getConfig();
00876             segments[1].m_cfg1 = sB.m_cfg1;
00877             segments[0].m_v1 = BOP_getVertexIndex(mesh,points[1],sB.m_cfg1,sB.m_v1);
00878             segments[1].m_v1 = segments[0].m_v1;
00879             
00880             segments[0].m_cfg2 = sA.m_cfg2;
00881             segments[1].m_cfg2 = sB.m_cfg2;          
00882             segments[0].m_v2 = BOP_getVertexIndex(mesh, points[2], sA.m_cfg2, sB.m_cfg2, 
00883                                                   sA.m_v2, sB.m_v2, invert);
00884             segments[1].m_v2 = segments[0].m_v2;
00885             break;
00886 
00887         case sB_sA_sX:
00888             segments[0].m_cfg1 = sA.m_cfg1;
00889             segments[1].m_cfg1 = sB.getConfig();
00890             segments[0].m_v1 = BOP_getVertexIndex(mesh,points[1],sA.m_cfg1,sA.m_v1);
00891             segments[1].m_v1 = segments[0].m_v1;
00892             
00893             segments[0].m_cfg2 = sA.m_cfg2;
00894             segments[1].m_cfg2 = sB.m_cfg2;          
00895             segments[0].m_v2 = BOP_getVertexIndex(mesh, points[2], sA.m_cfg2, sB.m_cfg2,
00896                                                   sA.m_v2, sB.m_v2, invert);
00897             segments[1].m_v2 = segments[0].m_v2;
00898             break;
00899       
00900         default:
00901             break; 
00902         }
00903     }
00904     else {
00905         // 4!
00906         switch(label) {
00907         case sA_sA_sB_sB:
00908         case sB_sB_sA_sA:
00909             segments[0].m_cfg1 = 
00910             segments[1].m_cfg1 = 
00911             segments[0].m_cfg2 = 
00912             segments[1].m_cfg2 = BOP_Segment::createUndefinedCfg();
00913             break;
00914       
00915         case sA_sB_sA_sB:
00916             segments[0].m_cfg1 = sA.getConfig();
00917             segments[1].m_cfg1 = sB.m_cfg1;
00918             segments[0].m_v1 = BOP_getVertexIndex(mesh,points[1],sB.m_cfg1,sB.m_v1);
00919             segments[1].m_v1 = segments[0].m_v1;
00920             
00921             segments[0].m_cfg2 = sA.m_cfg2;
00922             segments[1].m_cfg2 = sB.getConfig();
00923             segments[0].m_v2 = BOP_getVertexIndex(mesh,points[2],sA.m_cfg2,sA.m_v2);
00924             segments[1].m_v2 = segments[0].m_v2;
00925             break;          
00926       
00927         case sB_sA_sB_sA:
00928             segments[0].m_cfg1 = sA.m_cfg1;
00929             segments[1].m_cfg1 = sB.getConfig();
00930             segments[0].m_v1 = BOP_getVertexIndex(mesh,points[1],sA.m_cfg1,sA.m_v1);
00931             segments[1].m_v1 = segments[0].m_v1;
00932             
00933             segments[0].m_cfg2 = sA.getConfig();
00934             segments[1].m_cfg2 = sB.m_cfg2;
00935             segments[0].m_v2 = BOP_getVertexIndex(mesh,points[2],sB.m_cfg2,sB.m_v2);
00936             segments[1].m_v2 = segments[0].m_v2;
00937             break;          
00938       
00939         case sA_sB_sB_sA:
00940             segments[0].m_cfg1 = sA.getConfig();
00941             segments[1].m_cfg1 = sB.m_cfg1;
00942             segments[0].m_v1 = BOP_getVertexIndex(mesh,points[1],sB.m_cfg1,sB.m_v1);
00943             segments[1].m_v1 = segments[0].m_v1;
00944             
00945             segments[0].m_cfg2 = segments[0].m_cfg1;
00946             segments[1].m_cfg2 = sB.m_cfg2;
00947             segments[0].m_v2 = BOP_getVertexIndex(mesh,points[2],sB.m_cfg2,sB.m_v2);
00948             segments[1].m_v2 = segments[0].m_v2;
00949             break;
00950       
00951         case sB_sA_sA_sB:
00952             segments[0].m_cfg1 = sA.m_cfg1;
00953             segments[1].m_cfg1 = sB.getConfig();
00954             segments[0].m_v1 = BOP_getVertexIndex(mesh,points[1],sA.m_cfg1,sA.m_v1);
00955             segments[1].m_v1 = segments[0].m_v1;
00956             
00957             segments[0].m_cfg2 = sA.m_cfg2;
00958             segments[1].m_cfg2 = segments[1].m_cfg1;
00959             segments[0].m_v2 = BOP_getVertexIndex(mesh,points[2],sA.m_cfg2,sA.m_v2);
00960             segments[1].m_v2 = segments[0].m_v2;
00961             break;
00962       
00963         default:
00964             break; 
00965         }
00966     }
00967     
00968     segments[0].sort();
00969     segments[1].sort();
00970 }
00971 
00983 BOP_Index BOP_getVertexIndex(BOP_Mesh* mesh, 
00984                        MT_Point3 point, 
00985                        unsigned int       cfgA, 
00986                        unsigned int       cfgB, 
00987                        BOP_Index       vA, 
00988                        BOP_Index       vB, 
00989                        bool      invert)
00990 {
00991     if (BOP_Segment::isVertex(cfgA)) { // exists vertex index on A
00992         if (BOP_Segment::isVertex(cfgB)) { // exists vertex index on B
00993             // unify vertex indexs
00994             if (invert)
00995                 return mesh->replaceVertexIndex(vA,vB);
00996             else 
00997                 return mesh->replaceVertexIndex(vB,vA);
00998         }
00999         else
01000             return vA;
01001     }
01002     else {// does not exist vertex index on A
01003         if (BOP_Segment::isVertex(cfgB)) // exists vertex index on B
01004             return vB;  
01005         else {// does not exist vertex index on B
01006             return mesh->addVertex(point);
01007         }
01008     } 
01009 }
01010 
01018 BOP_Index BOP_getVertexIndex(BOP_Mesh *mesh, MT_Point3 point, unsigned int cfg, BOP_Index v)
01019 {
01020     if (BOP_Segment::isVertex(cfg)) // vertex existent
01021         return v;   
01022     else {
01023         return mesh->addVertex(point);
01024     }
01025 }
01026 
01027 /******************************************************************************/
01028 /*** TRIANGULATE                                                            ***/
01029 /******************************************************************************/
01030 
01038 void triangulate(BOP_Mesh *mesh, BOP_Faces *faces, BOP_Face *face, BOP_Segment s)
01039 {
01040     if (BOP_Segment::isUndefined(s.m_cfg1)) {
01041         // Nothing to do
01042     }
01043     else if (BOP_Segment::isVertex(s.m_cfg1)) {
01044         // VERTEX(v1) + VERTEX(v2) => nothing to do
01045     }
01046     else if (BOP_Segment::isEdge(s.m_cfg1)) {
01047         if (BOP_Segment::isVertex(s.m_cfg2) || BOP_Segment::isUndefined(s.m_cfg2)) {
01048             // EDGE(v1) + VERTEX(v2)
01049             BOP_Edge *edge = mesh->getEdge(face,BOP_Segment::getEdge(s.m_cfg1));
01050             BOP_triangulateA(mesh,faces,face,s.m_v1,BOP_Segment::getEdge(s.m_cfg1));
01051             BOP_Face *opposite = BOP_getOppositeFace(mesh,faces,face,edge);
01052             if (opposite != NULL) {
01053               unsigned int e;
01054               opposite->getEdgeIndex(edge->getVertex1(), edge->getVertex2(),e);
01055               BOP_triangulateA(mesh, faces, opposite, s.m_v1, e);
01056             }
01057         }
01058         else {
01059             //  EDGE(v1) + EDGE(v2)
01060             if (BOP_Segment::getEdge(s.m_cfg1) == BOP_Segment::getEdge(s.m_cfg2)) {
01061                  // EDGE(v1) == EDGE(v2)
01062                 BOP_Edge *edge = mesh->getEdge(face,BOP_Segment::getEdge(s.m_cfg1));
01063                 BOP_triangulateD(mesh, faces, face, s.m_v1, s.m_v2, 
01064                                  BOP_Segment::getEdge(s.m_cfg1)); 
01065                 BOP_Face *opposite = BOP_getOppositeFace(mesh,faces,face,edge);
01066                 if (opposite != NULL) {
01067                   unsigned int e;
01068                   opposite->getEdgeIndex(edge->getVertex1(), edge->getVertex2(),e);
01069                   BOP_triangulateD(mesh, faces, opposite, s.m_v1, s.m_v2, e);
01070                 }
01071             }
01072             else { // EDGE(v1) != EDGE(v2)
01073                 BOP_Edge *edge1 = mesh->getEdge(face,BOP_Segment::getEdge(s.m_cfg1));
01074                 BOP_Edge *edge2 = mesh->getEdge(face,BOP_Segment::getEdge(s.m_cfg2));
01075                 BOP_triangulateE(mesh, faces, face, s.m_v1, s.m_v2,
01076                                  BOP_Segment::getEdge(s.m_cfg1),
01077                                  BOP_Segment::getEdge(s.m_cfg2));
01078                 BOP_Face *opposite = BOP_getOppositeFace(mesh,faces,face,edge1);
01079                 if (opposite != NULL) {
01080                   unsigned int e;
01081                   opposite->getEdgeIndex(edge1->getVertex1(), edge1->getVertex2(),e);
01082                   BOP_triangulateA(mesh, faces, opposite, s.m_v1, e);
01083                 }
01084                 opposite = BOP_getOppositeFace(mesh,faces,face,edge2);
01085                 if (opposite != NULL) {
01086                   unsigned int e;
01087                   opposite->getEdgeIndex(edge2->getVertex1(), edge2->getVertex2(),e);
01088                   BOP_triangulateA(mesh, faces, opposite, s.m_v2, e);
01089                 }
01090             }
01091         }
01092     }
01093     else if (BOP_Segment::isIn(s.m_cfg1)) {
01094         if (BOP_Segment::isVertex(s.m_cfg2) || BOP_Segment::isUndefined(s.m_cfg2)) {
01095             // IN(v1) + VERTEX(v2)
01096             BOP_triangulateB(mesh,faces,face,s.m_v1);
01097         }
01098         else if (BOP_Segment::isEdge(s.m_cfg2)) {
01099             // IN(v1) + EDGE(v2)
01100             BOP_Edge *edge = mesh->getEdge(face,BOP_Segment::getEdge(s.m_cfg2));
01101             BOP_triangulateF(mesh,faces,face,s.m_v1,s.m_v2,BOP_Segment::getEdge(s.m_cfg2));
01102             BOP_Face *opposite = BOP_getOppositeFace(mesh,faces,face,edge);
01103             if (opposite != NULL) {
01104               unsigned int e;
01105               opposite->getEdgeIndex(edge->getVertex1(), edge->getVertex2(),e);
01106               BOP_triangulateA(mesh, faces, opposite, s.m_v2, e);
01107             }
01108         }
01109         else // IN(v1) + IN(v2)
01110             BOP_triangulateC(mesh,faces,face,s.m_v1,s.m_v2);
01111     }
01112 }
01113 
01120 bool BOP_containsFace(BOP_Faces *faces, BOP_Face *face)
01121 {
01122   const BOP_IT_Faces facesEnd = faces->end();
01123     for(BOP_IT_Faces it=faces->begin();it!=facesEnd;it++)
01124     {
01125         if (*it == face)
01126         return true;
01127     }
01128     
01129     return false;
01130 }
01131 
01140 BOP_Face *BOP_getOppositeFace(BOP_Mesh*  mesh, 
01141                               BOP_Faces* faces, 
01142                               BOP_Face*  face,
01143                               BOP_Edge*  edge)
01144 {
01145     if (edge == NULL)
01146       return NULL;
01147   
01148     BOP_Indexs auxfaces = edge->getFaces();
01149     const BOP_IT_Indexs auxfacesEnd = auxfaces.end();
01150     for(BOP_IT_Indexs it = auxfaces.begin(); it != auxfacesEnd; it++) {
01151         BOP_Face *auxface = mesh->getFace(*it);
01152         if ((auxface != face) && (auxface->getTAG()!=BROKEN) && 
01153             BOP_containsFace(faces,auxface)) {
01154             return auxface;
01155         }
01156     }        
01157   
01158     return NULL;
01159 }
01160 
01161 /******************************************************************************/ 
01162 /***  OVERLAPPING                                                           ***/
01163 /******************************************************************************/ 
01164 
01171 void BOP_removeOverlappedFaces(BOP_Mesh *mesh,  BOP_Faces *facesA,  BOP_Faces *facesB)
01172 {
01173     for(unsigned int i=0;i<facesA->size();i++) {
01174         BOP_Face *faceI = (*facesA)[i];
01175         if (faceI->getTAG()==BROKEN) continue;
01176         bool overlapped = false;
01177         MT_Point3 p1 = mesh->getVertex(faceI->getVertex(0))->getPoint();
01178         MT_Point3 p2 = mesh->getVertex(faceI->getVertex(1))->getPoint();
01179         MT_Point3 p3 = mesh->getVertex(faceI->getVertex(2))->getPoint();
01180         for(unsigned int j=0;j<facesB->size();) {
01181             BOP_Face *faceJ = (*facesB)[j];
01182             if (faceJ->getTAG()!=BROKEN) {
01183                 MT_Plane3 planeJ = faceJ->getPlane();
01184                 if (BOP_containsPoint(planeJ,p1) && BOP_containsPoint(planeJ,p2)
01185                         && BOP_containsPoint(planeJ,p3))
01186                 {
01187                     MT_Point3 q1 = mesh->getVertex(faceJ->getVertex(0))->getPoint();
01188                     MT_Point3 q2 = mesh->getVertex(faceJ->getVertex(1))->getPoint();
01189                     MT_Point3 q3 = mesh->getVertex(faceJ->getVertex(2))->getPoint();
01190                     if (BOP_overlap(MT_Vector3(planeJ.x(),planeJ.y(),planeJ.z()),
01191                                     p1,p2,p3,q1,q2,q3))
01192                     {
01193                         facesB->erase(facesB->begin()+j,facesB->begin()+(j+1));
01194                         faceJ->setTAG(BROKEN);
01195                         overlapped = true;
01196                     }
01197                     else j++;
01198                 }
01199                 else j++;
01200             }else j++;
01201         }
01202         if (overlapped) faceI->setTAG(OVERLAPPED);
01203     }
01204 }
01205 
01217 bool BOP_overlap(MT_Vector3 normal, MT_Point3 p1, MT_Point3 p2, MT_Point3 p3, 
01218                   MT_Point3 q1, MT_Point3 q2, MT_Point3 q3)
01219 {
01220     MT_Vector3 p1p2 = p2-p1;    
01221     MT_Plane3 plane1(p1p2.cross(normal),p1);
01222     
01223     MT_Vector3 p2p3 = p3-p2;
01224     MT_Plane3 plane2(p2p3.cross(normal),p2);
01225     
01226     MT_Vector3 p3p1 = p1-p3;    
01227     MT_Plane3 plane3(p3p1.cross(normal),p3);
01228   
01229     BOP_TAG tag1 = BOP_createTAG(BOP_classify(q1,plane1));
01230     BOP_TAG tag2 = BOP_createTAG(BOP_classify(q1,plane2));
01231     BOP_TAG tag3 = BOP_createTAG(BOP_classify(q1,plane3));
01232     BOP_TAG tagQ1 = BOP_createTAG(tag1,tag2,tag3);   
01233     if (tagQ1 == IN_IN_IN) return true;    
01234   
01235     tag1 = BOP_createTAG(BOP_classify(q2,plane1));
01236     tag2 = BOP_createTAG(BOP_classify(q2,plane2));
01237     tag3 = BOP_createTAG(BOP_classify(q2,plane3));
01238     BOP_TAG tagQ2 = BOP_createTAG(tag1,tag2,tag3);
01239     if (tagQ2 == IN_IN_IN) return true;    
01240     
01241     tag1 = BOP_createTAG(BOP_classify(q3,plane1));
01242     tag2 = BOP_createTAG(BOP_classify(q3,plane2));
01243     tag3 = BOP_createTAG(BOP_classify(q3,plane3));
01244     BOP_TAG tagQ3 = BOP_createTAG(tag1,tag2,tag3);
01245     if (tagQ3 == IN_IN_IN) return true;    
01246   
01247     if ((tagQ1 & OUT_OUT_OUT) == 0 && (tagQ2 & OUT_OUT_OUT) == 0 && 
01248         (tagQ3 & OUT_OUT_OUT) == 0) return true;
01249     else return false;
01250 }