Blender V2.61 - r43446
|
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 }