tetrahedronI.H
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2026 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
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.
15 
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
19  for more details.
20 
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/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "triangle.H"
27 #include "IOstreams.H"
28 #include "plane.H"
29 
30 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
31 
32 template<class Point, class PointRef>
34 (
35  const Point& a,
36  const Point& b,
37  const Point& c,
38  const Point& d
39 )
40 :
41  a_(a),
42  b_(b),
43  c_(c),
44  d_(d)
45 {}
46 
47 
48 template<class Point, class PointRef>
50 (
51  const UList<Point>& points,
52  const FixedList<label, 4>& indices
53 )
54 :
55  a_(points[indices[0]]),
56  b_(points[indices[1]]),
57  c_(points[indices[2]]),
58  d_(points[indices[3]])
59 {}
60 
61 
62 template<class Point, class PointRef>
64 {
65  is >> *this;
66 }
67 
68 
69 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
70 
71 template<class Point, class PointRef>
72 inline const Point& Foam::tetrahedron<Point, PointRef>::a() const
73 {
74  return a_;
75 }
76 
77 
78 template<class Point, class PointRef>
79 inline const Point& Foam::tetrahedron<Point, PointRef>::b() const
80 {
81  return b_;
82 }
83 
84 
85 template<class Point, class PointRef>
86 inline const Point& Foam::tetrahedron<Point, PointRef>::c() const
87 {
88  return c_;
89 }
90 
91 
92 template<class Point, class PointRef>
93 inline const Point& Foam::tetrahedron<Point, PointRef>::d() const
94 {
95  return d_;
96 }
97 
98 
99 template<class Point, class PointRef>
101 (
102  const label facei
103 ) const
104 {
105  // Warning. Ordering of faces needs to be the same for a tetrahedron
106  // class, a tetrahedron cell shape model and a tetCell
107 
108  if (facei == 0)
109  {
110  return triPointRef(b_, c_, d_);
111  }
112  else if (facei == 1)
113  {
114  return triPointRef(a_, d_, c_);
115  }
116  else if (facei == 2)
117  {
118  return triPointRef(a_, b_, d_);
119  }
120  else if (facei == 3)
121  {
122  return triPointRef(a_, c_, b_);
123  }
124  else
125  {
127  << "index out of range 0 -> 3. facei = " << facei
128  << abort(FatalError);
129  return triPointRef(b_, c_, d_);
130  }
131 }
132 
133 
134 template<class Point, class PointRef>
136 {
137  return triangle<Point, PointRef>(b_, c_, d_).area();
138 }
139 
140 
141 template<class Point, class PointRef>
143 {
144  return triangle<Point, PointRef>(a_, d_, c_).area();
145 }
146 
147 
148 template<class Point, class PointRef>
150 {
151  return triangle<Point, PointRef>(a_, b_, d_).area();
152 }
153 
154 
155 template<class Point, class PointRef>
157 {
158  return triangle<Point, PointRef>(a_, c_, b_).area();
159 }
160 
161 
162 template<class Point, class PointRef>
164 {
165  return 0.25*(a_ + b_ + c_ + d_);
166 }
167 
168 
169 template<class Point, class PointRef>
170 inline Foam::scalar Foam::tetrahedron<Point, PointRef>::mag() const
171 {
172  return (1.0/6.0)*(((b_ - a_) ^ (c_ - a_)) & (d_ - a_));
173 }
174 
175 
176 template<class Point, class PointRef>
179 {
180  const vector a = b_ - a_;
181  const vector b = c_ - a_;
182  const vector c = d_ - a_;
183 
184  const vector ba = b ^ a;
185  const vector ca = c ^ a;
186 
187  const scalar lambda = magSqr(c) - (a & c);
188  const scalar mu = magSqr(b) - (a & b);
189 
190  const vector num = lambda*ba - mu*ca;
191  const scalar denom = (c & ba);
192 
193  if (Foam::mag(denom) < rootVSmall)
194  {
195  // Degenerate. Return an invalid sphere.
196  return Tuple2<Point, scalar>(point::uniform(NaN), -vGreat);
197  }
198  else
199  {
200  const vector v = (a + num/denom)/2;
201  return Tuple2<Point, scalar>(a_ + v, magSqr(v));
202  }
203 }
204 
205 
206 template<class Point, class PointRef>
209 {
210  const Tuple2<Point, scalar> crSqr = circumSphereSqr();
211 
212  // Invalid. Return without conversion.
213  if (crSqr.second() < 0) return crSqr;
214 
215  return Tuple2<Point, scalar>(crSqr.first(), sqrt(crSqr.second()));
216 }
217 
218 
219 template<class Point, class PointRef>
221 {
222  const scalar r = circumSphere().second();
223 
224  // Invalid. Return zero.
225  if (r < 0) return 0;
226 
227  static const scalar sqrt3 = sqrt(scalar(3));
228 
229  return mag()/(8.0/27.0*sqrt3*pow3(min(r, great)) + rootVSmall);
230 }
231 
232 
233 template<class Point, class PointRef>
235 (
237 ) const
238 {
239  return barycentricToPoint(barycentric01(rndGen));
240 }
241 
242 
243 template<class Point, class PointRef>
245 (
246  const barycentric& bary
247 ) const
248 {
249  return bary[0]*a_ + bary[1]*b_ + bary[2]*c_ + bary[3]*d_;
250 }
251 
252 
253 template<class Point, class PointRef>
255 (
256  const point& pt
257 ) const
258 {
259  barycentric bary;
260  pointToBarycentric(pt, bary);
261  return bary;
262 }
263 
264 
265 template<class Point, class PointRef>
267 (
268  const point& pt,
269  barycentric& bary
270 ) const
271 {
272  // Reference:
273  // http://en.wikipedia.org/wiki/Barycentric_coordinate_system_(mathematics)
274 
275  vector e0(a_ - d_);
276  vector e1(b_ - d_);
277  vector e2(c_ - d_);
278 
279  tensor t
280  (
281  e0.x(), e1.x(), e2.x(),
282  e0.y(), e1.y(), e2.y(),
283  e0.z(), e1.z(), e2.z()
284  );
285 
286  scalar detT = det(t);
287 
288  if (Foam::mag(detT) < small)
289  {
290  // Degenerate tetrahedron, returning 1/4 barycentric coordinates
291 
292  bary = barycentric(0.25, 0.25, 0.25, 0.25);
293 
294  return detT;
295  }
296 
297  vector res = inv(t, detT) & (pt - d_);
298 
299  bary[0] = res.x();
300  bary[1] = res.y();
301  bary[2] = res.z();
302  bary[3] = 1 - cmptSum(res);
303 
304  return detT;
305 }
306 
307 
308 template<class Point, class PointRef>
310 (
311  const point& p
312 ) const
313 {
314  // Adapted from:
315  // Real-time collision detection, Christer Ericson, 2005, p142-144
316 
317  // Assuming initially that the point is inside all of the
318  // halfspaces, so closest to itself.
319 
320  point closestPt = p;
321 
322  scalar minOutsideDistance = vGreat;
323 
324  bool inside = true;
325 
326  if (((p - b_) & Sa()) >= 0)
327  {
328  // p is outside halfspace plane of tri
329  pointHit info = triangle<Point, PointRef>(b_, c_, d_).nearestPoint(p);
330 
331  inside = false;
332 
333  if (info.distance() < minOutsideDistance)
334  {
335  closestPt = info.rawPoint();
336 
337  minOutsideDistance = info.distance();
338  }
339  }
340 
341  if (((p - a_) & Sb()) >= 0)
342  {
343  // p is outside halfspace plane of tri
344  pointHit info = triangle<Point, PointRef>(a_, d_, c_).nearestPoint(p);
345 
346  inside = false;
347 
348  if (info.distance() < minOutsideDistance)
349  {
350  closestPt = info.rawPoint();
351 
352  minOutsideDistance = info.distance();
353  }
354  }
355 
356  if (((p - a_) & Sc()) >= 0)
357  {
358  // p is outside halfspace plane of tri
359  pointHit info = triangle<Point, PointRef>(a_, b_, d_).nearestPoint(p);
360 
361  inside = false;
362 
363  if (info.distance() < minOutsideDistance)
364  {
365  closestPt = info.rawPoint();
366 
367  minOutsideDistance = info.distance();
368  }
369  }
370 
371  if (((p - a_) & Sd()) >= 0)
372  {
373  // p is outside halfspace plane of tri
374  pointHit info = triangle<Point, PointRef>(a_, c_, b_).nearestPoint(p);
375 
376  inside = false;
377 
378  if (info.distance() < minOutsideDistance)
379  {
380  closestPt = info.rawPoint();
381 
382  minOutsideDistance = info.distance();
383  }
384  }
385 
386  // If the point is inside, then the distance to the closest point
387  // is zero
388  if (inside)
389  {
390  minOutsideDistance = 0;
391  }
392 
393  return pointHit
394  (
395  inside,
396  closestPt,
397  minOutsideDistance,
398  !inside
399  );
400 }
401 
402 
403 template<class Point, class PointRef>
405 {
406  // For robustness, assuming that the point is in the tet unless
407  // "definitively" shown otherwise by obtaining a positive dot
408  // product greater than a tolerance of small.
409 
410  // The tet is defined: tet(Cc, tetBasePt, pA, pB) where the area
411  // vectors and base points for the half-space planes are:
412  // area[0] = Sa();
413  // area[1] = Sb();
414  // area[2] = Sc();
415  // area[3] = Sd();
416  // planeBase[0] = tetBasePt = b_
417  // planeBase[1] = ptA = c_
418  // planeBase[2] = tetBasePt = b_
419  // planeBase[3] = tetBasePt = b_
420 
421  vector n = Zero;
422 
423  {
424  // 0, a
425  const point& basePt = b_;
426 
427  n = Sa();
428  n /= (Foam::mag(n) + vSmall);
429 
430  if (((pt - basePt) & n) > small)
431  {
432  return false;
433  }
434  }
435 
436  {
437  // 1, b
438  const point& basePt = c_;
439 
440  n = Sb();
441  n /= (Foam::mag(n) + vSmall);
442 
443  if (((pt - basePt) & n) > small)
444  {
445  return false;
446  }
447  }
448 
449  {
450  // 2, c
451  const point& basePt = b_;
452 
453  n = Sc();
454  n /= (Foam::mag(n) + vSmall);
455 
456  if (((pt - basePt) & n) > small)
457  {
458  return false;
459  }
460  }
461 
462  {
463  // 3, d
464  const point& basePt = b_;
465 
466  n = Sd();
467  n /= (Foam::mag(n) + vSmall);
468 
469  if (((pt - basePt) & n) > small)
470  {
471  return false;
472  }
473  }
474 
475  return true;
476 }
477 
478 
479 template<class Point, class PointRef>
481 {
482  return
483  boundBox
484  (
485  min(a(), min(b(), min(c(), d()))),
486  max(a(), max(b(), max(c(), d())))
487  );
488 }
489 
490 
491 // * * * * * * * * * * * * * * * Ostream Operator * * * * * * * * * * * * * //
492 
493 template<class Point, class PointRef>
494 inline Foam::Istream& Foam::operator>>
495 (
496  Istream& is,
498 )
499 {
500  is.readBegin("tetrahedron");
501  is >> t.a_ >> t.b_ >> t.c_ >> t.d_;
502  is.readEnd("tetrahedron");
503 
504  is.check("Istream& operator>>(Istream&, tetrahedron&)");
505 
506  return is;
507 }
508 
509 
510 template<class Point, class PointRef>
511 inline Foam::Ostream& Foam::operator<<
512 (
513  Ostream& os,
514  const tetrahedron<Point, PointRef>& t
515 )
516 {
517  os << nl
519  << t.a_ << token::SPACE
520  << t.b_ << token::SPACE
521  << t.c_ << token::SPACE
522  << t.d_
523  << token::END_LIST;
524 
525  return os;
526 }
527 
528 
529 // ************************************************************************* //
Useful combination of include files which define Sin, Sout and Serr and the use of IO streams general...
label n
virtual bool check(const char *operation) const
Check IOstream status for given operation.
Definition: IOstream.C:108
An Istream is an abstract base class for all input systems (streams, files, token lists etc)....
Definition: Istream.H:60
Istream & readEnd(const char *funcName)
Definition: Istream.C:123
Istream & readBegin(const char *funcName)
Definition: Istream.C:106
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:57
scalar distance() const
Return distance to hit.
Definition: PointHit.H:139
const Point & rawPoint() const
Return point with no checking.
Definition: PointHit.H:158
A 2-tuple for storing two objects of different types.
Definition: Tuple2.H:66
const Type2 & second() const
Return second.
Definition: Tuple2.H:131
const Type1 & first() const
Return first.
Definition: Tuple2.H:119
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition: UList.H:74
static Form uniform(const Cmpt &s)
Return a VectorSpace with all elements = s.
Definition: VectorSpaceI.H:168
const Cmpt & z() const
Definition: VectorI.H:87
const Cmpt & y() const
Definition: VectorI.H:81
const Cmpt & x() const
Definition: VectorI.H:75
A bounding box defined in terms of the points at its extremities.
Definition: boundBox.H:60
Random number generator.
A tetrahedron primitive.
Definition: tetrahedron.H:82
barycentric pointToBarycentric(const point &pt) const
Calculate the barycentric coordinates from the given point.
Definition: tetrahedronI.H:255
vector Sd() const
Definition: tetrahedronI.H:156
triPointRef tri(const label facei) const
Return i-th face.
Definition: tetrahedronI.H:101
boundBox bounds() const
Calculate the bounding box.
Definition: tetrahedronI.H:480
const Point & a() const
Return vertices.
Definition: tetrahedronI.H:72
Point centre() const
Return centre (centroid)
Definition: tetrahedronI.H:163
vector Sc() const
Definition: tetrahedronI.H:149
bool inside(const point &pt) const
Return true if point is inside tetrahedron.
Definition: tetrahedronI.H:404
vector Sb() const
Definition: tetrahedronI.H:142
Tuple2< Point, scalar > circumSphereSqr() const
Return the circum-centre and radius-squared.
Definition: tetrahedronI.H:178
Tuple2< Point, scalar > circumSphere() const
Return the circum-centre and radius.
Definition: tetrahedronI.H:208
const Point & c() const
Definition: tetrahedronI.H:86
scalar mag() const
Return volume.
Definition: tetrahedronI.H:170
pointHit nearestPoint(const point &p) const
Return nearest point to p on tetrahedron. Is p itself.
Definition: tetrahedronI.H:310
Point randomPoint(randomGenerator &rndGen) const
Return a random point in the tetrahedron from a.
Definition: tetrahedronI.H:235
Point barycentricToPoint(const barycentric &bary) const
Calculate the point from the given barycentric coordinates.
Definition: tetrahedronI.H:245
tetrahedron(const Point &a, const Point &b, const Point &c, const Point &d)
Construct from points.
Definition: tetrahedronI.H:34
const Point & b() const
Definition: tetrahedronI.H:79
scalar quality() const
Return quality: Ratio of tetrahedron and circum-sphere.
Definition: tetrahedronI.H:220
const Point & d() const
Definition: tetrahedronI.H:93
vector Sa() const
Return face normal.
Definition: tetrahedronI.H:135
@ BEGIN_LIST
Definition: token.H:110
@ END_LIST
Definition: token.H:111
A triangle primitive used to calculate face areas and swept volumes.
Definition: triangle.H:80
vector area() const
Return vector area.
Definition: triangleI.H:96
pointHit nearestPoint(const point &p) const
Return nearest point to p on triangle.
Definition: triangleI.H:660
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:334
const pointField & points
volScalarField & b
Definition: createFields.H:27
dimensionedScalar lambda(viscosity->lookup("lambda"))
const dimensionedScalar mu
Atomic mass unit.
const dimensionedScalar c
Speed of light in a vacuum.
static const zero Zero
Definition: zero.H:97
Barycentric< scalar > barycentric
A scalar version of the templated Barycentric.
Definition: barycentric.H:45
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
errorManip< error > abort(error &err)
Definition: errorManip.H:131
barycentric barycentric01(randomGenerator &rndGen)
Generate a random barycentric coordinate within the unit tetrahedron.
Definition: barycentric.C:31
void inv(pointPatchField< tensor > &, const pointPatchField< tensor > &)
dimensioned< Type > min(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
PointHit< point > pointHit
Definition: pointHit.H:41
void pow3(LagrangianPatchField< scalar > &f, const LagrangianPatchField< scalar > &f1)
void det(pointPatchField< scalar > &, const pointPatchField< tensor > &)
triangle< point, const point & > triPointRef
Definition: triPointRef.H:44
tmp< DimensionedField< scalar, GeoMesh, Field > > mag(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
error FatalError
Cmpt cmptSum(const VectorSpace< Form, Cmpt, Ncmpts > &vs)
Definition: VectorSpaceI.H:507
void sqrt(LagrangianPatchField< scalar > &f, const LagrangianPatchField< scalar > &f1)
tmp< DimensionedField< scalar, GeoMesh, Field > > magSqr(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
static const char nl
Definition: Ostream.H:297
dimensioned< Type > max(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
randomGenerator rndGen(653213)
volScalarField & p