FreeFOAM The Cross-Platform CFD Toolkit
Hosted by SourceForge:
Get FreeFOAM at SourceForge.net.
            Fast, secure and Free Open Source software downloads

triangleFuncs.C

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002   =========                 |
00003   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
00004    \\    /   O peration     |
00005     \\  /    A nd           | Copyright (C) 1991-2010 OpenCFD Ltd.
00006      \\/     M anipulation  |
00007 -------------------------------------------------------------------------------
00008 License
00009     This file is part of OpenFOAM.
00010 
00011     OpenFOAM is free software: you can redistribute it and/or modify it
00012     under the terms of the GNU General Public License as published by
00013     the Free Software Foundation, either version 3 of the License, or
00014     (at your option) any later version.
00015 
00016     OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
00017     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00019     for more details.
00020 
00021     You should have received a copy of the GNU General Public License
00022     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
00023 
00024 \*---------------------------------------------------------------------------*/
00025 
00026 #include "triangleFuncs.H"
00027 #include <OpenFOAM/pointField.H>
00028 #include <meshTools/treeBoundBox.H>
00029 #include <OpenFOAM/SortableList.H>
00030 #include <OpenFOAM/boolList.H>
00031 
00032 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
00033 
00034 void Foam::triangleFuncs::setIntersection
00035 (
00036     const point& oppositeSidePt,
00037     const scalar oppositeSign,
00038 
00039     const point& thisSidePt,
00040     const scalar thisSign,
00041 
00042     const scalar tol,
00043 
00044     point& pt
00045 )
00046 {
00047     scalar denom = oppositeSign - thisSign;
00048 
00049     if (mag(denom) < tol)
00050     {
00051         // If almost does not cut choose one which certainly cuts.
00052         pt = oppositeSidePt;
00053     }
00054     else
00055     {
00056         pt = oppositeSidePt + oppositeSign/denom*(thisSidePt - oppositeSidePt);
00057     }
00058 }
00059 
00060 
00061 void Foam::triangleFuncs::selectPt
00062 (
00063     const bool select0,
00064     const point& p0,
00065     const point& p1,
00066     point& min
00067 )
00068 {
00069     if (select0)
00070     {
00071         min = p0;
00072     }
00073     else
00074     {
00075         min = p1;
00076     }
00077 }
00078 
00079 
00080 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
00081 
00082 // Intersect triangle with parallel edges aligned with axis i0.
00083 // Returns true (and intersection in pInter) if any of them intersects triangle.
00084 bool Foam::triangleFuncs::intersectAxesBundle
00085 (
00086     const point& V0,
00087     const point& V10,
00088     const point& V20,
00089     const label i0,
00090     const pointField& origin,
00091     const scalar maxLength,
00092     point& pInter
00093 )
00094 {
00095     // Based on Graphics Gems - Fast Ray Triangle intersection.
00096     // Since direction is coordinate axis there is no need to do projection,
00097     // we can directly check u,v components for inclusion in triangle.
00098 
00099     // Get other components
00100     label i1 = (i0 + 1) % 3;
00101     label i2 = (i1 + 1) % 3;
00102 
00103     scalar u1 = V10[i1];
00104     scalar v1 = V10[i2];
00105 
00106     scalar u2 = V20[i1];
00107     scalar v2 = V20[i2];
00108 
00109     scalar localScale = mag(u1)+mag(v1)+mag(u2)+mag(v2);
00110 
00111     scalar det = v2*u1 - u2*v1;
00112 
00113     // Fix for  V0:(-31.71428 0 -15.10714)
00114     //          V10:(-1.285715 8.99165e-16 -1.142858)
00115     //          V20:(0 0 -1.678573)
00116     //          i0:0
00117     if (localScale < VSMALL || Foam::mag(det)/localScale < SMALL)
00118     {
00119         // Triangle parallel to dir
00120         return false;
00121     }
00122 
00123     forAll(origin, originI)
00124     {
00125         const point& P = origin[originI];
00126 
00127         scalar u0 = P[i1] - V0[i1];
00128         scalar v0 = P[i2] - V0[i2];
00129 
00130         scalar alpha = 0;
00131         scalar beta = 0;
00132         bool inter = false;
00133 
00134         if (Foam::mag(u1) < ROOTVSMALL)
00135         {
00136             beta = u0/u2;
00137             if ((beta >= 0) && (beta <= 1))
00138             {
00139                 alpha = (v0 - beta*v2)/v1;
00140                 inter = ((alpha >= 0) && ((alpha + beta) <= 1));
00141             }
00142         }
00143         else
00144         {
00145             beta = (v0*u1 - u0*v1)/det;
00146             if ((beta >= 0) && (beta <= 1))
00147             {
00148                 alpha = (u0 - beta*u2)/u1;
00149                 inter = ((alpha >= 0) && ((alpha + beta) <= 1));
00150             }
00151         }
00152 
00153         if (inter)
00154         {
00155             pInter = V0 + alpha*V10 + beta*V20;
00156             scalar s = (pInter - origin[originI])[i0];
00157 
00158             if ((s >= 0) && (s <= maxLength))
00159             {
00160                 return true;
00161             }
00162         }
00163     }
00164     return false;
00165 }
00166 
00167 
00168 // Intersect triangle with bounding box. Return true if
00169 // any of the faces of bb intersect triangle.
00170 // Note: so returns false if triangle inside bb.
00171 bool Foam::triangleFuncs::intersectBb
00172 (
00173     const point& p0,
00174     const point& p1,
00175     const point& p2,
00176     const treeBoundBox& cubeBb
00177 )
00178 {
00179     const vector p10 = p1 - p0;
00180     const vector p20 = p2 - p0;
00181 
00182     // cubeBb points; counted as if cell with vertex0 at cubeBb.min().
00183     const point& min = cubeBb.min();
00184     const point& max = cubeBb.max();
00185 
00186     const point& cube0 = min;
00187     const point  cube1(min.x(), min.y(), max.z());
00188     const point  cube2(max.x(), min.y(), max.z());
00189     const point  cube3(max.x(), min.y(), min.z());
00190 
00191     const point  cube4(min.x(), max.y(), min.z());
00192     const point  cube5(min.x(), max.y(), max.z());
00193     const point  cube7(max.x(), max.y(), min.z());
00194 
00195     //
00196     // Intersect all 12 edges of cube with triangle
00197     //
00198 
00199     point pInter;
00200     pointField origin(4);
00201     // edges in x direction
00202     origin[0] = cube0;
00203     origin[1] = cube1;
00204     origin[2] = cube5;
00205     origin[3] = cube4;
00206 
00207     scalar maxSx = max.x() - min.x();
00208 
00209     if (intersectAxesBundle(p0, p10, p20, 0, origin, maxSx, pInter))
00210     {
00211         return true;
00212     }
00213 
00214     // edges in y direction
00215     origin[0] = cube0;
00216     origin[1] = cube1;
00217     origin[2] = cube2;
00218     origin[3] = cube3;
00219 
00220     scalar maxSy = max.y() - min.y();
00221 
00222     if (intersectAxesBundle(p0, p10, p20, 1, origin, maxSy, pInter))
00223     {
00224         return true;
00225     }
00226 
00227     // edges in z direction
00228     origin[0] = cube0;
00229     origin[1] = cube3;
00230     origin[2] = cube7;
00231     origin[3] = cube4;
00232 
00233     scalar maxSz = max.z() - min.z();
00234 
00235     if (intersectAxesBundle(p0, p10, p20, 2, origin, maxSz, pInter))
00236     {
00237         return true;
00238     }
00239 
00240 
00241     // Intersect triangle edges with bounding box
00242     if (cubeBb.intersects(p0, p1, pInter))
00243     {
00244         return true;
00245     }
00246     if (cubeBb.intersects(p1, p2, pInter))
00247     {
00248         return true;
00249     }
00250     if (cubeBb.intersects(p2, p0, pInter))
00251     {
00252         return true;
00253     }
00254 
00255     return false;
00256 }
00257 
00258 
00262 //bool Foam::triangleFuncs::intersectBbExact
00263 //(
00264 //    const point& p0,
00265 //    const point& p1,
00266 //    const point& p2,
00267 //    const treeBoundBox& cubeBb
00268 //)
00269 //{
00270 //    const point& min = cubeBb.min();
00271 //    const point& max = cubeBb.max();
00272 //
00273 //    const point& cube0 = min;
00274 //    const point  cube1(min.x(), min.y(), max.z());
00275 //    const point  cube2(max.x(), min.y(), max.z());
00276 //    const point  cube3(max.x(), min.y(), min.z());
00277 //
00278 //    const point  cube4(min.x(), max.y(), min.z());
00279 //    const point  cube5(min.x(), max.y(), max.z());
00280 //    const point& cube6 = max;
00281 //    const point  cube7(max.x(), max.y(), min.z());
00282 //
00283 //    // Test intersection of triangle with twelve edges of box.
00284 //    {
00285 //        triPointRef tri(p0, p1, p2);
00286 //        if (tri.intersectionExact(cube0, cube1).hit())
00287 //        {
00288 //            return true;
00289 //        }
00290 //        if (tri.intersectionExact(cube1, cube2).hit())
00291 //        {
00292 //            return true;
00293 //        }
00294 //        if (tri.intersectionExact(cube2, cube3).hit())
00295 //        {
00296 //            return true;
00297 //        }
00298 //        if (tri.intersectionExact(cube3, cube0).hit())
00299 //        {   
00300 //            return true;
00301 //        }
00302 //
00303 //        if (tri.intersectionExact(cube4, cube5).hit())
00304 //        {
00305 //            return true;
00306 //        }
00307 //        if (tri.intersectionExact(cube5, cube6).hit())
00308 //        {
00309 //            return true;
00310 //        }
00311 //        if (tri.intersectionExact(cube6, cube7).hit())
00312 //        {
00313 //            return true;
00314 //        }
00315 //        if (tri.intersectionExact(cube7, cube4).hit())
00316 //        {
00317 //            return true;
00318 //        }
00319 //
00320 //        if (tri.intersectionExact(cube0, cube4).hit())
00321 //        {
00322 //            return true;
00323 //        }
00324 //        if (tri.intersectionExact(cube1, cube5).hit())
00325 //        {
00326 //            return true;
00327 //        }
00328 //        if (tri.intersectionExact(cube2, cube6).hit())
00329 //        {
00330 //            return true;
00331 //        }
00332 //        if (tri.intersectionExact(cube3, cube7).hit())
00333 //        {
00334 //            return true;
00335 //        }
00336 //    }
00337 //    // Test intersection of triangle edges with bounding box
00338 //    {
00339 //        triPointRef tri(cube0, cube1, cube2);
00340 //        if (tri.intersectionExact(p0, p1).hit())
00341 //        {
00342 //            return true;
00343 //        }
00344 //        if (tri.intersectionExact(p1, p2).hit())
00345 //        {
00346 //            return true;
00347 //        }
00348 //        if (tri.intersectionExact(p2, p0).hit())
00349 //        {
00350 //            return true;
00351 //        }
00352 //    }
00353 //    {
00354 //        triPointRef tri(cube2, cube3, cube0);
00355 //        if (tri.intersectionExact(p0, p1).hit())
00356 //        {
00357 //            return true;
00358 //        }
00359 //        if (tri.intersectionExact(p1, p2).hit())
00360 //        {
00361 //            return true;
00362 //        }
00363 //        if (tri.intersectionExact(p2, p0).hit())
00364 //        {
00365 //            return true;
00366 //        }
00367 //    }
00368 //    {
00369 //        triPointRef tri(cube4, cube5, cube6);
00370 //        if (tri.intersectionExact(p0, p1).hit())
00371 //        {
00372 //            return true;
00373 //        }
00374 //        if (tri.intersectionExact(p1, p2).hit())
00375 //        {
00376 //            return true;
00377 //        }
00378 //        if (tri.intersectionExact(p2, p0).hit())
00379 //        {
00380 //            return true;
00381 //        }
00382 //    }
00383 //    {
00384 //        triPointRef tri(cube6, cube7, cube4);
00385 //        if (tri.intersectionExact(p0, p1).hit())
00386 //        {
00387 //            return true;
00388 //        }
00389 //        if (tri.intersectionExact(p1, p2).hit())
00390 //        {
00391 //            return true;
00392 //        }
00393 //        if (tri.intersectionExact(p2, p0).hit())
00394 //        {
00395 //            return true;
00396 //        }
00397 //    }
00398 //
00399 //
00400 //    {
00401 //        triPointRef tri(cube4, cube5, cube1);
00402 //        if (tri.intersectionExact(p0, p1).hit())
00403 //        {
00404 //            return true;
00405 //        }
00406 //        if (tri.intersectionExact(p1, p2).hit())
00407 //        {
00408 //            return true;
00409 //        }
00410 //        if (tri.intersectionExact(p2, p0).hit())
00411 //        {
00412 //            return true;
00413 //        }
00414 //    }
00415 //    {
00416 //        triPointRef tri(cube1, cube0, cube4);
00417 //        if (tri.intersectionExact(p0, p1).hit())
00418 //        {
00419 //            return true;
00420 //        }
00421 //        if (tri.intersectionExact(p1, p2).hit())
00422 //        {
00423 //            return true;
00424 //        }
00425 //        if (tri.intersectionExact(p2, p0).hit())
00426 //        {
00427 //            return true;
00428 //        }
00429 //    }
00430 //    {
00431 //        triPointRef tri(cube7, cube6, cube2);
00432 //        if (tri.intersectionExact(p0, p1).hit())
00433 //        {
00434 //            return true;
00435 //        }
00436 //        if (tri.intersectionExact(p1, p2).hit())
00437 //        {
00438 //            return true;
00439 //        }
00440 //        if (tri.intersectionExact(p2, p0).hit())
00441 //        {
00442 //            return true;
00443 //        }
00444 //    }
00445 //    {
00446 //        triPointRef tri(cube2, cube3, cube7);
00447 //        if (tri.intersectionExact(p0, p1).hit())
00448 //        {
00449 //            return true;
00450 //        }
00451 //        if (tri.intersectionExact(p1, p2).hit())
00452 //        {
00453 //            return true;
00454 //        }
00455 //        if (tri.intersectionExact(p2, p0).hit())
00456 //        {
00457 //            return true;
00458 //        }
00459 //    }
00460 //
00461 //    {
00462 //        triPointRef tri(cube0, cube4, cube7);
00463 //        if (tri.intersectionExact(p0, p1).hit())
00464 //        {
00465 //            return true;
00466 //        }
00467 //        if (tri.intersectionExact(p1, p2).hit())
00468 //        {
00469 //            return true;
00470 //        }
00471 //        if (tri.intersectionExact(p2, p0).hit())
00472 //        {
00473 //            return true;
00474 //        }
00475 //    }
00476 //    {
00477 //        triPointRef tri(cube7, cube3, cube0);
00478 //        if (tri.intersectionExact(p0, p1).hit())
00479 //        {
00480 //            return true;
00481 //        }
00482 //        if (tri.intersectionExact(p1, p2).hit())
00483 //        {
00484 //            return true;
00485 //        }
00486 //        if (tri.intersectionExact(p2, p0).hit())
00487 //        {
00488 //            return true;
00489 //        }
00490 //    }
00491 //    {
00492 //        triPointRef tri(cube1, cube5, cube6);
00493 //        if (tri.intersectionExact(p0, p1).hit())
00494 //        {
00495 //            return true;
00496 //        }
00497 //        if (tri.intersectionExact(p1, p2).hit())
00498 //        {
00499 //            return true;
00500 //        }
00501 //        if (tri.intersectionExact(p2, p0).hit())
00502 //        {
00503 //            return true;
00504 //        }
00505 //    }
00506 //    {
00507 //        triPointRef tri(cube6, cube2, cube1);
00508 //        if (tri.intersectionExact(p0, p1).hit())
00509 //        {
00510 //            return true;
00511 //        }
00512 //        if (tri.intersectionExact(p1, p2).hit())
00513 //        {
00514 //            return true;
00515 //        }
00516 //        if (tri.intersectionExact(p2, p0).hit())
00517 //        {
00518 //            return true;
00519 //        }
00520 //    }
00521 //    return false;
00522 //}
00523 
00524 
00525 bool Foam::triangleFuncs::intersect
00526 (
00527     const point& va0,
00528     const point& va10,
00529     const point& va20,
00530 
00531     const point& base,
00532     const point& normal,
00533 
00534     point& pInter0,
00535     point& pInter1
00536 )
00537 {
00538     // Get triangle normal
00539     vector na = va10 ^ va20;
00540     scalar magArea = mag(na);
00541     na/magArea;
00542 
00543     if (mag(na & normal) > (1 - SMALL))
00544     {
00545         // Parallel
00546         return false;
00547     }
00548 
00549     const point va1 = va0 + va10;
00550     const point va2 = va0 + va20;
00551 
00552     // Find the triangle point on the other side.
00553     scalar sign0 = (va0 - base) & normal;
00554     scalar sign1 = (va1 - base) & normal;
00555     scalar sign2 = (va2 - base) & normal;
00556 
00557     label oppositeVertex = -1;
00558 
00559     if (sign0 < 0)
00560     {
00561         if (sign1 < 0)
00562         {
00563             if (sign2 < 0)
00564             {
00565                 // All on same side of plane
00566                 return false;
00567             }
00568             else    // sign2 >= 0
00569             {
00570                 // 2 on opposite side.
00571                 oppositeVertex = 2;
00572             }
00573         }
00574         else    // sign1 >= 0
00575         {
00576             if (sign2 < 0)
00577             {
00578                 // 1 on opposite side.
00579                 oppositeVertex = 1;
00580             }
00581             else
00582             {
00583                 // 0 on opposite side.
00584                 oppositeVertex = 0;
00585             }
00586         }
00587     }
00588     else    // sign0 >= 0
00589     {
00590         if (sign1 < 0)
00591         {
00592             if (sign2 < 0)
00593             {
00594                 // 0 on opposite side.
00595                 oppositeVertex = 0;
00596             }
00597             else    // sign2 >= 0
00598             {
00599                 // 1 on opposite side.
00600                 oppositeVertex = 1;
00601             }
00602         }
00603         else    // sign1 >= 0
00604         {
00605             if (sign2 < 0)
00606             {
00607                 // 2 on opposite side.
00608                 oppositeVertex = 2;
00609             }
00610             else    // sign2 >= 0
00611             {
00612                 // All on same side of plane
00613                 return false;
00614             }
00615         }
00616     }
00617 
00618     scalar tol = SMALL*Foam::sqrt(magArea);
00619 
00620     if (oppositeVertex == 0)
00621     {
00622         // 0 on opposite side. Cut edges 01 and 02
00623         setIntersection(va0, sign0, va1, sign1, tol, pInter0);
00624         setIntersection(va0, sign0, va2, sign2, tol, pInter1);
00625     }
00626     else if (oppositeVertex == 1)
00627     {
00628         // 1 on opposite side. Cut edges 10 and 12
00629         setIntersection(va1, sign1, va0, sign0, tol, pInter0);
00630         setIntersection(va1, sign1, va2, sign2, tol, pInter1);
00631     }
00632     else // oppositeVertex == 2
00633     {
00634         // 2 on opposite side. Cut edges 20 and 21
00635         setIntersection(va2, sign2, va0, sign0, tol, pInter0);
00636         setIntersection(va2, sign2, va1, sign1, tol, pInter1);
00637     }
00638 
00639     return true;
00640 }
00641 
00642 
00643 bool Foam::triangleFuncs::intersect
00644 (
00645     const point& va0,
00646     const point& va10,
00647     const point& va20,
00648 
00649     const point& vb0,
00650     const point& vb10,
00651     const point& vb20,
00652 
00653     point& pInter0,
00654     point& pInter1
00655 )
00656 {
00657     // Get triangle normals
00658     vector na = va10 ^ va20;
00659     na/mag(na);
00660 
00661     vector nb = vb10 ^ vb20;
00662     nb/mag(nb);
00663 
00664     // Calculate intersection of triangle a with plane of b
00665     point planeB0;
00666     point planeB1;
00667     if (!intersect(va0, va10, va20, vb0, nb, planeB0, planeB1))
00668     {
00669         return false;
00670     }
00671 
00672     //       ,,  triangle b with plane of a
00673     point planeA0;
00674     point planeA1;
00675     if (!intersect(vb0, vb10, vb20, va0, na, planeA0, planeA1))
00676     {
00677         return false;
00678     }
00679 
00680     // Now check if intersections overlap (w.r.t. intersection of the two
00681     // planes)
00682 
00683     vector intersection(na ^ nb);
00684 
00685     scalar coordB0 = planeB0 & intersection;
00686     scalar coordB1 = planeB1 & intersection;
00687 
00688     scalar coordA0 = planeA0 & intersection;
00689     scalar coordA1 = planeA1 & intersection;
00690 
00691     // Put information in indexable form for sorting.
00692     List<point*> pts(4);
00693     boolList isFromB(4);
00694     SortableList<scalar> sortCoords(4);
00695 
00696     pts[0] = &planeB0;
00697     isFromB[0] = true;
00698     sortCoords[0] = coordB0;
00699 
00700     pts[1] = &planeB1;
00701     isFromB[1] = true;
00702     sortCoords[1] = coordB1;
00703 
00704     pts[2] = &planeA0;
00705     isFromB[2] = false;
00706     sortCoords[2] = coordA0;
00707 
00708     pts[3] = &planeA1;
00709     isFromB[3] = false;
00710     sortCoords[3] = coordA1;
00711 
00712     sortCoords.sort();
00713 
00714     const labelList& indices = sortCoords.indices();
00715 
00716     if (isFromB[indices[0]] == isFromB[indices[1]])
00717     {
00718         // Entry 0 and 1 are of same region (both a or both b). Hence that
00719         // region does not overlap.
00720         return false;
00721     }
00722     else
00723     {
00724         // Different type. Start of overlap at indices[1], end at indices[2]
00725         pInter0 = *pts[indices[1]];
00726         pInter1 = *pts[indices[2]];
00727 
00728         return true;
00729     }
00730 }
00731 
00732 
00733 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines