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 "treeDataTriSurface.H"
27 #include "triSurfaceTools.H"
28 #include "triangleFuncs.H"
29 #include "indexedOctree.H"
31 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
33 defineTypeNameAndDebug(Foam::treeDataTriSurface, 0);
36 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
38 // // Fast distance to triangle calculation. From
39 // // "Distance Between Point and Triangle in 3D"
40 // // David Eberly, Magic Software Inc. Aug. 2003.
41 // // Works on function Q giving distance to point and tries to minimize this.
42 // Foam::scalar Foam::treeDataTriSurface::nearestCoords
56 // const vector D(base - P);
58 // // Precalculate distance factors.
59 // const scalar d = E0 & D;
60 // const scalar e = E1 & D;
62 // // Do classification
63 // const scalar det = a*c - b*b;
77 // //min on edge t = 0
79 // s = (d >= 0 ? 0 : (-d >= a ? 1 : -d/a));
85 // t = (e >= 0 ? 0 : (-e >= c ? 1 : -e/c));
90 // //region 3. Min on edge s = 0
92 // t = (e >= 0 ? 0 : (-e >= c ? 1 : -e/c));
99 // s = (d >= 0 ? 0 : (-d >= a ? 1 : -d/a));
104 // const scalar invDet = 1/det;
114 // const scalar tmp0 = b + d;
115 // const scalar tmp1 = c + e;
118 // //min on edge s+t=1
119 // const scalar numer = tmp1 - tmp0;
120 // const scalar denom = a-2*b+c;
121 // s = (numer >= denom ? 1 : numer/denom);
128 // t = (tmp1 <= 0 ? 1 : (e >= 0 ? 0 : - e/c));
134 // const scalar tmp0 = b + d;
135 // const scalar tmp1 = c + e;
138 // //min on edge s+t=1
139 // const scalar numer = tmp1 - tmp0;
140 // const scalar denom = a-2*b+c;
141 // s = (numer >= denom ? 1 : numer/denom);
148 // s = (tmp1 <= 0 ? 1 : (d >= 0 ? 0 : - d/a));
154 // const scalar numer = c+e-(b+d);
161 // const scalar denom = a-2*b+c;
162 // s = (numer >= denom ? 1 : numer/denom);
169 // // Calculate distance.
170 // // Note: abs should not be needed but truncation error causes problems
171 // // with points very close to one of the triangle vertices.
172 // // (seen up to -9e-15). Alternatively add some small value.
174 // const scalar f = D & D;
175 // return Foam::mag(a*s*s + 2*b*s*t + c*t*t + 2*d*s + 2*e*t + f);
179 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
181 // Construct from components
182 Foam::treeDataTriSurface::treeDataTriSurface
184 const triSurface& surface,
185 const scalar planarTol
189 planarTol_(planarTol)
193 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
195 Foam::pointField Foam::treeDataTriSurface::shapePoints() const
197 const pointField& points = surface_.points();
199 pointField centres(surface_.size());
201 forAll(surface_, triI)
203 centres[triI] = surface_[triI].centre(points);
209 //- Get type of sample (inside/outside/mixed) w.r.t. surface.
210 Foam::label Foam::treeDataTriSurface::getVolumeType
212 const indexedOctree<treeDataTriSurface>& tree,
216 // Find nearest point
217 const treeBoundBox& treeBb = tree.bb();
219 pointIndexHit pHit = tree.findNearest
225 Foam::magSqr(treeBb.span())
231 FatalErrorIn("treeDataTriSurface::getVolumeType(..)")
232 << "treeBb:" << treeBb
233 << " sample:" << sample
235 << abort(FatalError);
238 triSurfaceTools::sideType t = triSurfaceTools::surfaceSide
245 if (t == triSurfaceTools::UNKNOWN)
247 return indexedOctree<treeDataTriSurface>::UNKNOWN;
249 else if (t == triSurfaceTools::INSIDE)
251 return indexedOctree<treeDataTriSurface>::INSIDE;
253 else if (t == triSurfaceTools::OUTSIDE)
255 return indexedOctree<treeDataTriSurface>::OUTSIDE;
259 FatalErrorIn("treeDataTriSurface::getVolumeType(..)")
260 << "problem" << abort(FatalError);
261 return indexedOctree<treeDataTriSurface>::UNKNOWN;
266 // Check if any point on triangle is inside cubeBb.
267 bool Foam::treeDataTriSurface::overlaps
270 const treeBoundBox& cubeBb
273 const pointField& points = surface_.points();
274 const labelledTri& f = surface_[index];
276 treeBoundBox triBb(points, surface_[index]);
278 //- For testing: robust one
279 //return cubeBb.overlaps(triBb);
281 //- Exact test of triangle intersecting bb
283 // Quick rejection. If whole bounding box of tri is outside cubeBb then
284 // there will be no intersection.
285 if (!cubeBb.overlaps(triBb))
290 // Check if one or more triangle point inside
291 if (cubeBb.containsAny(points, f))
297 const point& p0 = points[f[0]];
298 const point& p1 = points[f[1]];
299 const point& p2 = points[f[2]];
302 // Now we have the difficult case: all points are outside but connecting
303 // edges might go through cube. Use fast intersection of bounding box.
305 //return triangleFuncs::intersectBbExact(p0, p1, p2, cubeBb);
306 return triangleFuncs::intersectBb(p0, p1, p2, cubeBb);
310 // Calculate nearest point to sample. Updates (if any) nearestDistSqr, minIndex,
312 void Foam::treeDataTriSurface::findNearest
314 const labelUList& indices,
317 scalar& nearestDistSqr,
322 const pointField& points = surface_.points();
326 label index = indices[i];
327 const triSurface::FaceType& f = surface_[index];
329 ////- Possible optimization: do quick rejection of triangle if bounding
330 //// sphere does not intersect triangle bounding box. From simplistic
331 //// test was not found to speed up things.
333 //// Triangle bounding box.
334 //point triBbMin = min(p0, min(p1, p2));
335 //point triBbMax = max(p0, max(p1, p2));
339 // indexedOctree<treeDataTriSurface>::intersects
348 // // Get spanning vectors of triangle
350 // vector E0(p0 - p1);
351 // vector E1(p2 - p1);
357 // // Get nearest point in s,t coordinates (s is along E0, t
362 // scalar distSqr = nearestCoords
376 pointHit pHit = f.nearestPoint(sample, points);
378 scalar distSqr = sqr(pHit.distance());
380 if (distSqr < nearestDistSqr)
382 nearestDistSqr = distSqr;
384 nearestPoint = pHit.rawPoint();
391 // Calculate nearest point to line. Updates (if any) nearestDistSqr, minIndex,
393 void Foam::treeDataTriSurface::findNearest
395 const labelUList& indices,
396 const linePointRef& ln,
398 treeBoundBox& tightest,
406 "treeDataTriSurface::findNearest(const labelUList&"
407 ", const linePointRef&, treeBoundBox&, label&, point&, point&) const"
412 bool Foam::treeDataTriSurface::intersects
417 point& intersectionPoint
420 const pointField& points = surface_.points();
422 const triSurface::FaceType& f = surface_[index];
424 // Do quick rejection test
425 treeBoundBox triBb(points, f);
427 const direction startBits(triBb.posBits(start));
428 const direction endBits(triBb.posBits(end));
430 if ((startBits & endBits) != 0)
432 // start and end in same block outside of triBb.
436 const vector dir(end - start);
438 // Use relative tolerance (from octree) to determine intersection.
439 pointHit inter = f.intersection
444 intersection::HALF_RAY,
448 if (inter.hit() && inter.distance() <= 1)
450 // Note: no extra test on whether intersection is in front of us
451 // since using half_ray.
452 intersectionPoint = inter.hitPoint();
462 //- Using exact intersections
463 //pointHit info = f.tri(points).intersectionExact(start, end);
467 // intersectionPoint = info.hitPoint();
473 // ************************************************************************* //