1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
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
13 the Free Software Foundation, either version 3 of the License, or
14 (at your 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, see <http://www.gnu.org/licenses/>.
24 \*---------------------------------------------------------------------------*/
26 #include "triangleFuncs.H"
27 #include "pointField.H"
28 #include "treeBoundBox.H"
29 #include "SortableList.H"
32 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
34 void Foam::triangleFuncs::setIntersection
36 const point& oppositeSidePt,
37 const scalar oppositeSign,
39 const point& thisSidePt,
40 const scalar thisSign,
47 scalar denom = oppositeSign - thisSign;
51 // If almost does not cut choose one which certainly cuts.
56 pt = oppositeSidePt + oppositeSign/denom*(thisSidePt - oppositeSidePt);
61 void Foam::triangleFuncs::selectPt
80 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
82 // Intersect triangle with parallel edges aligned with axis i0.
83 // Returns true (and intersection in pInter) if any of them intersects triangle.
84 bool Foam::triangleFuncs::intersectAxesBundle
90 const pointField& origin,
91 const scalar maxLength,
95 // Based on Graphics Gems - Fast Ray Triangle intersection.
96 // Since direction is coordinate axis there is no need to do projection,
97 // we can directly check u,v components for inclusion in triangle.
99 // Get other components
100 label i1 = (i0 + 1) % 3;
101 label i2 = (i1 + 1) % 3;
109 scalar localScale = mag(u1)+mag(v1)+mag(u2)+mag(v2);
111 scalar det = v2*u1 - u2*v1;
113 // Fix for V0:(-31.71428 0 -15.10714)
114 // V10:(-1.285715 8.99165e-16 -1.142858)
115 // V20:(0 0 -1.678573)
117 if (localScale < VSMALL || Foam::mag(det)/localScale < SMALL)
119 // Triangle parallel to dir
123 forAll(origin, originI)
125 const point& P = origin[originI];
127 scalar u0 = P[i1] - V0[i1];
128 scalar v0 = P[i2] - V0[i2];
134 if (Foam::mag(u1) < ROOTVSMALL)
137 if ((beta >= 0) && (beta <= 1))
139 alpha = (v0 - beta*v2)/v1;
140 inter = ((alpha >= 0) && ((alpha + beta) <= 1));
145 beta = (v0*u1 - u0*v1)/det;
146 if ((beta >= 0) && (beta <= 1))
148 alpha = (u0 - beta*u2)/u1;
149 inter = ((alpha >= 0) && ((alpha + beta) <= 1));
155 pInter = V0 + alpha*V10 + beta*V20;
156 scalar s = (pInter - origin[originI])[i0];
158 if ((s >= 0) && (s <= maxLength))
168 // Intersect triangle with bounding box. Return true if
169 // any of the faces of bb intersect triangle.
170 // Note: so returns false if triangle inside bb.
171 bool Foam::triangleFuncs::intersectBb
176 const treeBoundBox& cubeBb
179 const vector p10 = p1 - p0;
180 const vector p20 = p2 - p0;
182 // cubeBb points; counted as if cell with vertex0 at cubeBb.min().
183 const point& min = cubeBb.min();
184 const point& max = cubeBb.max();
186 const point& cube0 = min;
187 const point cube1(min.x(), min.y(), max.z());
188 const point cube2(max.x(), min.y(), max.z());
189 const point cube3(max.x(), min.y(), min.z());
191 const point cube4(min.x(), max.y(), min.z());
192 const point cube5(min.x(), max.y(), max.z());
193 const point cube7(max.x(), max.y(), min.z());
196 // Intersect all 12 edges of cube with triangle
200 pointField origin(4);
201 // edges in x direction
207 scalar maxSx = max.x() - min.x();
209 if (intersectAxesBundle(p0, p10, p20, 0, origin, maxSx, pInter))
214 // edges in y direction
220 scalar maxSy = max.y() - min.y();
222 if (intersectAxesBundle(p0, p10, p20, 1, origin, maxSy, pInter))
227 // edges in z direction
233 scalar maxSz = max.z() - min.z();
235 if (intersectAxesBundle(p0, p10, p20, 2, origin, maxSz, pInter))
241 // Intersect triangle edges with bounding box
242 if (cubeBb.intersects(p0, p1, pInter))
246 if (cubeBb.intersects(p1, p2, pInter))
250 if (cubeBb.intersects(p2, p0, pInter))
259 //// Intersect triangle with bounding box. Return true if
260 //// any of the faces of bb intersect triangle.
261 //// Note: so returns false if triangle inside bb.
262 //bool Foam::triangleFuncs::intersectBbExact
267 // const treeBoundBox& cubeBb
270 // const point& min = cubeBb.min();
271 // const point& max = cubeBb.max();
273 // const point& cube0 = min;
274 // const point cube1(min.x(), min.y(), max.z());
275 // const point cube2(max.x(), min.y(), max.z());
276 // const point cube3(max.x(), min.y(), min.z());
278 // const point cube4(min.x(), max.y(), min.z());
279 // const point cube5(min.x(), max.y(), max.z());
280 // const point& cube6 = max;
281 // const point cube7(max.x(), max.y(), min.z());
283 // // Test intersection of triangle with twelve edges of box.
285 // triPointRef tri(p0, p1, p2);
286 // if (tri.intersectionExact(cube0, cube1).hit())
290 // if (tri.intersectionExact(cube1, cube2).hit())
294 // if (tri.intersectionExact(cube2, cube3).hit())
298 // if (tri.intersectionExact(cube3, cube0).hit())
303 // if (tri.intersectionExact(cube4, cube5).hit())
307 // if (tri.intersectionExact(cube5, cube6).hit())
311 // if (tri.intersectionExact(cube6, cube7).hit())
315 // if (tri.intersectionExact(cube7, cube4).hit())
320 // if (tri.intersectionExact(cube0, cube4).hit())
324 // if (tri.intersectionExact(cube1, cube5).hit())
328 // if (tri.intersectionExact(cube2, cube6).hit())
332 // if (tri.intersectionExact(cube3, cube7).hit())
337 // // Test intersection of triangle edges with bounding box
339 // triPointRef tri(cube0, cube1, cube2);
340 // if (tri.intersectionExact(p0, p1).hit())
344 // if (tri.intersectionExact(p1, p2).hit())
348 // if (tri.intersectionExact(p2, p0).hit())
354 // triPointRef tri(cube2, cube3, cube0);
355 // if (tri.intersectionExact(p0, p1).hit())
359 // if (tri.intersectionExact(p1, p2).hit())
363 // if (tri.intersectionExact(p2, p0).hit())
369 // triPointRef tri(cube4, cube5, cube6);
370 // if (tri.intersectionExact(p0, p1).hit())
374 // if (tri.intersectionExact(p1, p2).hit())
378 // if (tri.intersectionExact(p2, p0).hit())
384 // triPointRef tri(cube6, cube7, cube4);
385 // if (tri.intersectionExact(p0, p1).hit())
389 // if (tri.intersectionExact(p1, p2).hit())
393 // if (tri.intersectionExact(p2, p0).hit())
401 // triPointRef tri(cube4, cube5, cube1);
402 // if (tri.intersectionExact(p0, p1).hit())
406 // if (tri.intersectionExact(p1, p2).hit())
410 // if (tri.intersectionExact(p2, p0).hit())
416 // triPointRef tri(cube1, cube0, cube4);
417 // if (tri.intersectionExact(p0, p1).hit())
421 // if (tri.intersectionExact(p1, p2).hit())
425 // if (tri.intersectionExact(p2, p0).hit())
431 // triPointRef tri(cube7, cube6, cube2);
432 // if (tri.intersectionExact(p0, p1).hit())
436 // if (tri.intersectionExact(p1, p2).hit())
440 // if (tri.intersectionExact(p2, p0).hit())
446 // triPointRef tri(cube2, cube3, cube7);
447 // if (tri.intersectionExact(p0, p1).hit())
451 // if (tri.intersectionExact(p1, p2).hit())
455 // if (tri.intersectionExact(p2, p0).hit())
462 // triPointRef tri(cube0, cube4, cube7);
463 // if (tri.intersectionExact(p0, p1).hit())
467 // if (tri.intersectionExact(p1, p2).hit())
471 // if (tri.intersectionExact(p2, p0).hit())
477 // triPointRef tri(cube7, cube3, cube0);
478 // if (tri.intersectionExact(p0, p1).hit())
482 // if (tri.intersectionExact(p1, p2).hit())
486 // if (tri.intersectionExact(p2, p0).hit())
492 // triPointRef tri(cube1, cube5, cube6);
493 // if (tri.intersectionExact(p0, p1).hit())
497 // if (tri.intersectionExact(p1, p2).hit())
501 // if (tri.intersectionExact(p2, p0).hit())
507 // triPointRef tri(cube6, cube2, cube1);
508 // if (tri.intersectionExact(p0, p1).hit())
512 // if (tri.intersectionExact(p1, p2).hit())
516 // if (tri.intersectionExact(p2, p0).hit())
525 bool Foam::triangleFuncs::intersect
538 // Get triangle normal
539 vector na = va10 ^ va20;
540 scalar magArea = mag(na);
543 if (mag(na & normal) > (1 - SMALL))
549 const point va1 = va0 + va10;
550 const point va2 = va0 + va20;
552 // Find the triangle point on the other side.
553 scalar sign0 = (va0 - base) & normal;
554 scalar sign1 = (va1 - base) & normal;
555 scalar sign2 = (va2 - base) & normal;
557 label oppositeVertex = -1;
565 // All on same side of plane
570 // 2 on opposite side.
578 // 1 on opposite side.
583 // 0 on opposite side.
594 // 0 on opposite side.
599 // 1 on opposite side.
607 // 2 on opposite side.
612 // All on same side of plane
618 scalar tol = SMALL*Foam::sqrt(magArea);
620 if (oppositeVertex == 0)
622 // 0 on opposite side. Cut edges 01 and 02
623 setIntersection(va0, sign0, va1, sign1, tol, pInter0);
624 setIntersection(va0, sign0, va2, sign2, tol, pInter1);
626 else if (oppositeVertex == 1)
628 // 1 on opposite side. Cut edges 10 and 12
629 setIntersection(va1, sign1, va0, sign0, tol, pInter0);
630 setIntersection(va1, sign1, va2, sign2, tol, pInter1);
632 else // oppositeVertex == 2
634 // 2 on opposite side. Cut edges 20 and 21
635 setIntersection(va2, sign2, va0, sign0, tol, pInter0);
636 setIntersection(va2, sign2, va1, sign1, tol, pInter1);
643 bool Foam::triangleFuncs::intersect
657 // Get triangle normals
658 vector na = va10 ^ va20;
661 vector nb = vb10 ^ vb20;
664 // Calculate intersection of triangle a with plane of b
667 if (!intersect(va0, va10, va20, vb0, nb, planeB0, planeB1))
672 // ,, triangle b with plane of a
675 if (!intersect(vb0, vb10, vb20, va0, na, planeA0, planeA1))
680 // Now check if intersections overlap (w.r.t. intersection of the two
683 vector intersection(na ^ nb);
685 scalar coordB0 = planeB0 & intersection;
686 scalar coordB1 = planeB1 & intersection;
688 scalar coordA0 = planeA0 & intersection;
689 scalar coordA1 = planeA1 & intersection;
691 // Put information in indexable form for sorting.
694 SortableList<scalar> sortCoords(4);
698 sortCoords[0] = coordB0;
702 sortCoords[1] = coordB1;
706 sortCoords[2] = coordA0;
710 sortCoords[3] = coordA1;
714 const labelList& indices = sortCoords.indices();
716 if (isFromB[indices[0]] == isFromB[indices[1]])
718 // Entry 0 and 1 are of same region (both a or both b). Hence that
719 // region does not overlap.
724 // Different type. Start of overlap at indices[1], end at indices[2]
725 pInter0 = *pts[indices[1]];
726 pInter1 = *pts[indices[2]];
733 // ************************************************************************* //