1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2009 OpenCFD Ltd.
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM is free software; you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation; either version 2 of the License, or (at your
14 option) any later version.
16 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM; if not, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 \*---------------------------------------------------------------------------*/
27 #include "triangleFuncs.H"
28 #include "pointField.H"
29 #include "treeBoundBox.H"
30 #include "SortableList.H"
33 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
35 void Foam::triangleFuncs::setIntersection
37 const point& oppositeSidePt,
38 const scalar oppositeSign,
40 const point& thisSidePt,
41 const scalar thisSign,
48 scalar denom = oppositeSign - thisSign;
52 // If almost does not cut choose one which certainly cuts.
57 pt = oppositeSidePt + oppositeSign/denom*(thisSidePt - oppositeSidePt);
62 void Foam::triangleFuncs::selectPt
81 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
83 // Intersect triangle with parallel edges aligned with axis i0.
84 // Returns true (and intersection in pInter) if any of them intersects triangle.
85 bool Foam::triangleFuncs::intersectAxesBundle
91 const pointField& origin,
92 const scalar maxLength,
96 // Based on Graphics Gems - Fast Ray Triangle intersection.
97 // Since direction is coordinate axis there is no need to do projection,
98 // we can directly check u,v components for inclusion in triangle.
100 // Get other components
101 label i1 = (i0 + 1) % 3;
102 label i2 = (i1 + 1) % 3;
110 scalar localScale = mag(u1)+mag(v1)+mag(u2)+mag(v2);
112 scalar det = v2*u1 - u2*v1;
114 // Fix for V0:(-31.71428 0 -15.10714)
115 // V10:(-1.285715 8.99165e-16 -1.142858)
116 // V20:(0 0 -1.678573)
118 if (localScale < VSMALL || Foam::mag(det)/localScale < SMALL)
120 // Triangle parallel to dir
124 forAll(origin, originI)
126 const point& P = origin[originI];
128 scalar u0 = P[i1] - V0[i1];
129 scalar v0 = P[i2] - V0[i2];
135 if (Foam::mag(u1) < ROOTVSMALL)
138 if ((beta >= 0) && (beta <= 1))
140 alpha = (v0 - beta*v2)/v1;
141 inter = ((alpha >= 0) && ((alpha + beta) <= 1));
146 beta = (v0*u1 - u0*v1)/det;
147 if ((beta >= 0) && (beta <= 1))
149 alpha = (u0 - beta*u2)/u1;
150 inter = ((alpha >= 0) && ((alpha + beta) <= 1));
156 pInter = V0 + alpha*V10 + beta*V20;
157 scalar s = (pInter - origin[originI])[i0];
159 if ((s >= 0) && (s <= maxLength))
169 // Intersect triangle with bounding box. Return true if
170 // any of the faces of bb intersect triangle.
171 // Note: so returns false if triangle inside bb.
172 bool Foam::triangleFuncs::intersectBb
177 const treeBoundBox& cubeBb
180 const vector p10 = p1 - p0;
181 const vector p20 = p2 - p0;
183 // cubeBb points; counted as if cell with vertex0 at cubeBb.min().
184 const point& min = cubeBb.min();
185 const point& max = cubeBb.max();
187 const point& cube0 = min;
188 const point cube1(min.x(), min.y(), max.z());
189 const point cube2(max.x(), min.y(), max.z());
190 const point cube3(max.x(), min.y(), min.z());
192 const point cube4(min.x(), max.y(), min.z());
193 const point cube5(min.x(), max.y(), max.z());
194 const point cube7(max.x(), max.y(), min.z());
197 // Intersect all 12 edges of cube with triangle
201 pointField origin(4);
202 // edges in x direction
208 scalar maxSx = max.x() - min.x();
210 if (intersectAxesBundle(p0, p10, p20, 0, origin, maxSx, pInter))
215 // edges in y direction
221 scalar maxSy = max.y() - min.y();
223 if (intersectAxesBundle(p0, p10, p20, 1, origin, maxSy, pInter))
228 // edges in z direction
234 scalar maxSz = max.z() - min.z();
236 if (intersectAxesBundle(p0, p10, p20, 2, origin, maxSz, pInter))
242 // Intersect triangle edges with bounding box
243 if (cubeBb.intersects(p0, p1, pInter))
247 if (cubeBb.intersects(p1, p2, pInter))
251 if (cubeBb.intersects(p2, p0, pInter))
260 //// Intersect triangle with bounding box. Return true if
261 //// any of the faces of bb intersect triangle.
262 //// Note: so returns false if triangle inside bb.
263 //bool Foam::triangleFuncs::intersectBbExact
268 // const treeBoundBox& cubeBb
271 // const point& min = cubeBb.min();
272 // const point& max = cubeBb.max();
274 // const point& cube0 = min;
275 // const point cube1(min.x(), min.y(), max.z());
276 // const point cube2(max.x(), min.y(), max.z());
277 // const point cube3(max.x(), min.y(), min.z());
279 // const point cube4(min.x(), max.y(), min.z());
280 // const point cube5(min.x(), max.y(), max.z());
281 // const point& cube6 = max;
282 // const point cube7(max.x(), max.y(), min.z());
284 // // Test intersection of triangle with twelve edges of box.
286 // triPointRef tri(p0, p1, p2);
287 // if (tri.intersectionExact(cube0, cube1).hit())
291 // if (tri.intersectionExact(cube1, cube2).hit())
295 // if (tri.intersectionExact(cube2, cube3).hit())
299 // if (tri.intersectionExact(cube3, cube0).hit())
304 // if (tri.intersectionExact(cube4, cube5).hit())
308 // if (tri.intersectionExact(cube5, cube6).hit())
312 // if (tri.intersectionExact(cube6, cube7).hit())
316 // if (tri.intersectionExact(cube7, cube4).hit())
321 // if (tri.intersectionExact(cube0, cube4).hit())
325 // if (tri.intersectionExact(cube1, cube5).hit())
329 // if (tri.intersectionExact(cube2, cube6).hit())
333 // if (tri.intersectionExact(cube3, cube7).hit())
338 // // Test intersection of triangle edges with bounding box
340 // triPointRef tri(cube0, cube1, cube2);
341 // if (tri.intersectionExact(p0, p1).hit())
345 // if (tri.intersectionExact(p1, p2).hit())
349 // if (tri.intersectionExact(p2, p0).hit())
355 // triPointRef tri(cube2, cube3, cube0);
356 // if (tri.intersectionExact(p0, p1).hit())
360 // if (tri.intersectionExact(p1, p2).hit())
364 // if (tri.intersectionExact(p2, p0).hit())
370 // triPointRef tri(cube4, cube5, cube6);
371 // if (tri.intersectionExact(p0, p1).hit())
375 // if (tri.intersectionExact(p1, p2).hit())
379 // if (tri.intersectionExact(p2, p0).hit())
385 // triPointRef tri(cube6, cube7, cube4);
386 // if (tri.intersectionExact(p0, p1).hit())
390 // if (tri.intersectionExact(p1, p2).hit())
394 // if (tri.intersectionExact(p2, p0).hit())
402 // triPointRef tri(cube4, cube5, cube1);
403 // if (tri.intersectionExact(p0, p1).hit())
407 // if (tri.intersectionExact(p1, p2).hit())
411 // if (tri.intersectionExact(p2, p0).hit())
417 // triPointRef tri(cube1, cube0, cube4);
418 // if (tri.intersectionExact(p0, p1).hit())
422 // if (tri.intersectionExact(p1, p2).hit())
426 // if (tri.intersectionExact(p2, p0).hit())
432 // triPointRef tri(cube7, cube6, cube2);
433 // if (tri.intersectionExact(p0, p1).hit())
437 // if (tri.intersectionExact(p1, p2).hit())
441 // if (tri.intersectionExact(p2, p0).hit())
447 // triPointRef tri(cube2, cube3, cube7);
448 // if (tri.intersectionExact(p0, p1).hit())
452 // if (tri.intersectionExact(p1, p2).hit())
456 // if (tri.intersectionExact(p2, p0).hit())
463 // triPointRef tri(cube0, cube4, cube7);
464 // if (tri.intersectionExact(p0, p1).hit())
468 // if (tri.intersectionExact(p1, p2).hit())
472 // if (tri.intersectionExact(p2, p0).hit())
478 // triPointRef tri(cube7, cube3, cube0);
479 // if (tri.intersectionExact(p0, p1).hit())
483 // if (tri.intersectionExact(p1, p2).hit())
487 // if (tri.intersectionExact(p2, p0).hit())
493 // triPointRef tri(cube1, cube5, cube6);
494 // if (tri.intersectionExact(p0, p1).hit())
498 // if (tri.intersectionExact(p1, p2).hit())
502 // if (tri.intersectionExact(p2, p0).hit())
508 // triPointRef tri(cube6, cube2, cube1);
509 // if (tri.intersectionExact(p0, p1).hit())
513 // if (tri.intersectionExact(p1, p2).hit())
517 // if (tri.intersectionExact(p2, p0).hit())
526 bool Foam::triangleFuncs::intersect
539 // Get triangle normal
540 vector na = va10 ^ va20;
541 scalar magArea = mag(na);
544 if (mag(na & normal) > (1 - SMALL))
550 const point va1 = va0 + va10;
551 const point va2 = va0 + va20;
553 // Find the triangle point on the other side.
554 scalar sign0 = (va0 - base) & normal;
555 scalar sign1 = (va1 - base) & normal;
556 scalar sign2 = (va2 - base) & normal;
558 label oppositeVertex = -1;
566 // All on same side of plane
571 // 2 on opposite side.
579 // 1 on opposite side.
584 // 0 on opposite side.
595 // 0 on opposite side.
600 // 1 on opposite side.
608 // 2 on opposite side.
613 // All on same side of plane
619 scalar tol = SMALL*Foam::sqrt(magArea);
621 if (oppositeVertex == 0)
623 // 0 on opposite side. Cut edges 01 and 02
624 setIntersection(va0, sign0, va1, sign1, tol, pInter0);
625 setIntersection(va0, sign0, va2, sign2, tol, pInter1);
627 else if (oppositeVertex == 1)
629 // 1 on opposite side. Cut edges 10 and 12
630 setIntersection(va1, sign1, va0, sign0, tol, pInter0);
631 setIntersection(va1, sign1, va2, sign2, tol, pInter1);
633 else // oppositeVertex == 2
635 // 2 on opposite side. Cut edges 20 and 21
636 setIntersection(va2, sign2, va0, sign0, tol, pInter0);
637 setIntersection(va2, sign2, va1, sign1, tol, pInter1);
644 bool Foam::triangleFuncs::intersect
658 // Get triangle normals
659 vector na = va10 ^ va20;
662 vector nb = vb10 ^ vb20;
665 // Calculate intersection of triangle a with plane of b
668 if (!intersect(va0, va10, va20, vb0, nb, planeB0, planeB1))
673 // ,, triangle b with plane of a
676 if (!intersect(vb0, vb10, vb20, va0, na, planeA0, planeA1))
681 // Now check if intersections overlap (w.r.t. intersection of the two
684 vector intersection(na ^ nb);
686 scalar coordB0 = planeB0 & intersection;
687 scalar coordB1 = planeB1 & intersection;
689 scalar coordA0 = planeA0 & intersection;
690 scalar coordA1 = planeA1 & intersection;
692 // Put information in indexable form for sorting.
695 SortableList<scalar> sortCoords(4);
699 sortCoords[0] = coordB0;
703 sortCoords[1] = coordB1;
707 sortCoords[2] = coordA0;
711 sortCoords[3] = coordA1;
715 const labelList& indices = sortCoords.indices();
717 if (isFromB[indices[0]] == isFromB[indices[1]])
719 // Entry 0 and 1 are of same region (both a or both b). Hence that
720 // region does not overlap.
725 // Different type. Start of overlap at indices[1], end at indices[2]
726 pInter0 = *pts[indices[1]];
727 pInter1 = *pts[indices[2]];
734 // ************************************************************************* //