tetrahedronI.H
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | Copyright (C) 2011-2017 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_).normal();
138 }
139 
140 
141 template<class Point, class PointRef>
143 {
144  return triangle<Point, PointRef>(a_, d_, c_).normal();
145 }
146 
147 
148 template<class Point, class PointRef>
150 {
151  return triangle<Point, PointRef>(a_, b_, d_).normal();
152 }
153 
154 
155 template<class Point, class PointRef>
157 {
158  return triangle<Point, PointRef>(a_, c_, b_).normal();
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>
178 {
179  vector a = b_ - a_;
180  vector b = c_ - a_;
181  vector c = d_ - a_;
182 
183  scalar lambda = magSqr(c) - (a & c);
184  scalar mu = magSqr(b) - (a & b);
185 
186  vector ba = b ^ a;
187  vector ca = c ^ a;
188 
189  vector num = lambda*ba - mu*ca;
190  scalar denom = (c & ba);
191 
192  if (Foam::mag(denom) < ROOTVSMALL)
193  {
194  // Degenerate tetrahedron, returning centre instead of circumCentre.
195 
196  return centre();
197  }
198 
199  return a_ + 0.5*(a + num/denom);
200 }
201 
202 
203 template<class Point, class PointRef>
205 {
206  vector a = b_ - a_;
207  vector b = c_ - a_;
208  vector c = d_ - a_;
209 
210  scalar lambda = magSqr(c) - (a & c);
211  scalar mu = magSqr(b) - (a & b);
212 
213  vector ba = b ^ a;
214  vector ca = c ^ a;
215 
216  vector num = lambda*ba - mu*ca;
217  scalar denom = (c & ba);
218 
219  if (Foam::mag(denom) < ROOTVSMALL)
220  {
221  // Degenerate tetrahedron, returning GREAT for circumRadius.
222  return GREAT;
223  }
224 
225  return Foam::mag(0.5*(a + num/denom));
226 }
227 
228 
229 template<class Point, class PointRef>
231 {
232  return
233  mag()
234  /(
235  8.0/(9.0*sqrt(3.0))
236  *pow3(min(circumRadius(), GREAT))
237  + ROOTVSMALL
238  );
239 }
240 
241 
242 template<class Point, class PointRef>
244 (
245  Random& rndGen
246 ) const
247 {
248  return barycentricToPoint(barycentric01(rndGen));
249 }
250 
251 
252 template<class Point, class PointRef>
254 (
255  cachedRandom& rndGen
256 ) const
257 {
258  return barycentricToPoint(barycentric01(rndGen));
259 }
260 
261 
262 template<class Point, class PointRef>
264 (
265  const barycentric& bary
266 ) const
267 {
268  return bary[0]*a_ + bary[1]*b_ + bary[2]*c_ + bary[3]*d_;
269 }
270 
271 
272 template<class Point, class PointRef>
274 (
275  const point& pt
276 ) const
277 {
278  barycentric bary;
279  pointToBarycentric(pt, bary);
280  return bary;
281 }
282 
283 
284 template<class Point, class PointRef>
286 (
287  const point& pt,
288  barycentric& bary
289 ) const
290 {
291  // Reference:
292  // http://en.wikipedia.org/wiki/Barycentric_coordinate_system_(mathematics)
293 
294  vector e0(a_ - d_);
295  vector e1(b_ - d_);
296  vector e2(c_ - d_);
297 
298  tensor t
299  (
300  e0.x(), e1.x(), e2.x(),
301  e0.y(), e1.y(), e2.y(),
302  e0.z(), e1.z(), e2.z()
303  );
304 
305  scalar detT = det(t);
306 
307  if (Foam::mag(detT) < SMALL)
308  {
309  // Degenerate tetrahedron, returning 1/4 barycentric coordinates
310 
311  bary = barycentric(0.25, 0.25, 0.25, 0.25);
312 
313  return detT;
314  }
315 
316  vector res = inv(t, detT) & (pt - d_);
317 
318  bary[0] = res.x();
319  bary[1] = res.y();
320  bary[2] = res.z();
321  bary[3] = 1 - cmptSum(res);
322 
323  return detT;
324 }
325 
326 
327 template<class Point, class PointRef>
329 (
330  const point& p
331 ) const
332 {
333  // Adapted from:
334  // Real-time collision detection, Christer Ericson, 2005, p142-144
335 
336  // Assuming initially that the point is inside all of the
337  // halfspaces, so closest to itself.
338 
339  point closestPt = p;
340 
341  scalar minOutsideDistance = VGREAT;
342 
343  bool inside = true;
344 
345  if (((p - b_) & Sa()) >= 0)
346  {
347  // p is outside halfspace plane of tri
348  pointHit info = triangle<Point, PointRef>(b_, c_, d_).nearestPoint(p);
349 
350  inside = false;
351 
352  if (info.distance() < minOutsideDistance)
353  {
354  closestPt = info.rawPoint();
355 
356  minOutsideDistance = info.distance();
357  }
358  }
359 
360  if (((p - a_) & Sb()) >= 0)
361  {
362  // p is outside halfspace plane of tri
363  pointHit info = triangle<Point, PointRef>(a_, d_, c_).nearestPoint(p);
364 
365  inside = false;
366 
367  if (info.distance() < minOutsideDistance)
368  {
369  closestPt = info.rawPoint();
370 
371  minOutsideDistance = info.distance();
372  }
373  }
374 
375  if (((p - a_) & Sc()) >= 0)
376  {
377  // p is outside halfspace plane of tri
378  pointHit info = triangle<Point, PointRef>(a_, b_, d_).nearestPoint(p);
379 
380  inside = false;
381 
382  if (info.distance() < minOutsideDistance)
383  {
384  closestPt = info.rawPoint();
385 
386  minOutsideDistance = info.distance();
387  }
388  }
389 
390  if (((p - a_) & Sd()) >= 0)
391  {
392  // p is outside halfspace plane of tri
393  pointHit info = triangle<Point, PointRef>(a_, c_, b_).nearestPoint(p);
394 
395  inside = false;
396 
397  if (info.distance() < minOutsideDistance)
398  {
399  closestPt = info.rawPoint();
400 
401  minOutsideDistance = info.distance();
402  }
403  }
404 
405  // If the point is inside, then the distance to the closest point
406  // is zero
407  if (inside)
408  {
409  minOutsideDistance = 0;
410  }
411 
412  return pointHit
413  (
414  inside,
415  closestPt,
416  minOutsideDistance,
417  !inside
418  );
419 }
420 
421 
422 template<class Point, class PointRef>
424 {
425  // For robustness, assuming that the point is in the tet unless
426  // "definitively" shown otherwise by obtaining a positive dot
427  // product greater than a tolerance of SMALL.
428 
429  // The tet is defined: tet(Cc, tetBasePt, pA, pB) where the normal
430  // vectors and base points for the half-space planes are:
431  // area[0] = Sa();
432  // area[1] = Sb();
433  // area[2] = Sc();
434  // area[3] = Sd();
435  // planeBase[0] = tetBasePt = b_
436  // planeBase[1] = ptA = c_
437  // planeBase[2] = tetBasePt = b_
438  // planeBase[3] = tetBasePt = b_
439 
440  vector n = Zero;
441 
442  {
443  // 0, a
444  const point& basePt = b_;
445 
446  n = Sa();
447  n /= (Foam::mag(n) + VSMALL);
448 
449  if (((pt - basePt) & n) > SMALL)
450  {
451  return false;
452  }
453  }
454 
455  {
456  // 1, b
457  const point& basePt = c_;
458 
459  n = Sb();
460  n /= (Foam::mag(n) + VSMALL);
461 
462  if (((pt - basePt) & n) > SMALL)
463  {
464  return false;
465  }
466  }
467 
468  {
469  // 2, c
470  const point& basePt = b_;
471 
472  n = Sc();
473  n /= (Foam::mag(n) + VSMALL);
474 
475  if (((pt - basePt) & n) > SMALL)
476  {
477  return false;
478  }
479  }
480 
481  {
482  // 3, d
483  const point& basePt = b_;
484 
485  n = Sd();
486  n /= (Foam::mag(n) + VSMALL);
487 
488  if (((pt - basePt) & n) > SMALL)
489  {
490  return false;
491  }
492  }
493 
494  return true;
495 }
496 
497 
498 // * * * * * * * * * * * * * * * Ostream Operator * * * * * * * * * * * * * //
499 
500 template<class Point, class PointRef>
501 inline Foam::Istream& Foam::operator>>
502 (
503  Istream& is,
505 )
506 {
507  is.readBegin("tetrahedron");
508  is >> t.a_ >> t.b_ >> t.c_ >> t.d_;
509  is.readEnd("tetrahedron");
510 
511  is.check("Istream& operator>>(Istream&, tetrahedron&)");
512 
513  return is;
514 }
515 
516 
517 template<class Point, class PointRef>
518 inline Foam::Ostream& Foam::operator<<
519 (
520  Ostream& os,
522 )
523 {
524  os << nl
525  << token::BEGIN_LIST
526  << t.a_ << token::SPACE
527  << t.b_ << token::SPACE
528  << t.c_ << token::SPACE
529  << t.d_
530  << token::END_LIST;
531 
532  return os;
533 }
534 
535 
536 // ************************************************************************* //
Istream & readBegin(const char *funcName)
Definition: Istream.C:86
A tetrahedron primitive.
Definition: tetrahedron.H:62
A triangle primitive used to calculate face normals and swept volumes.
Definition: triangle.H:58
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
error FatalError
scalar circumRadius() const
Return circum-radius.
Definition: tetrahedronI.H:204
tetrahedron(const Point &a, const Point &b, const Point &c, const Point &d)
Construct from points.
Definition: tetrahedronI.H:34
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:319
virtual bool check(const char *operation) const
Check IOstream status for given operation.
Definition: IOstream.C:92
Point circumCentre() const
Return circum-centre.
Definition: tetrahedronI.H:177
const Point & c() const
Definition: tetrahedronI.H:86
vector Sd() const
Definition: tetrahedronI.H:156
dimensionedSphericalTensor inv(const dimensionedSphericalTensor &dt)
An Istream is an abstract base class for all input systems (streams, files, token lists etc)...
Definition: Istream.H:57
const Point & a() const
Return vertices.
Definition: tetrahedronI.H:72
Cmpt cmptSum(const VectorSpace< Form, Cmpt, Ncmpts > &vs)
Definition: VectorSpaceI.H:509
dimensionedScalar sqrt(const dimensionedScalar &ds)
const Cmpt & z() const
Definition: VectorI.H:87
Random number generator.
Definition: cachedRandom.H:63
Foam::barycentric barycentric01(Foam::scalar s, Foam::scalar t, Foam::scalar u)
Definition: barycentric.C:33
Barycentric< scalar > barycentric
A scalar version of the templated Barycentric.
Definition: barycentric.H:46
dimensionedScalar det(const dimensionedSphericalTensor &dt)
const Cmpt & y() const
Definition: VectorI.H:81
Point barycentricToPoint(const barycentric &bary) const
Calculate the point from the given barycentric coordinates.
Definition: tetrahedronI.H:264
Useful combination of include files which define Sin, Sout and Serr and the use of IO streams general...
const Point & d() const
Definition: tetrahedronI.H:93
Istream & readEnd(const char *funcName)
Definition: Istream.C:103
const Point & b() const
Definition: tetrahedronI.H:79
const dimensionedScalar b
Wien displacement law constant: default SI units: [m.K].
Definition: createFields.H:27
scalar quality() const
Return quality: Ratio of tetrahedron and circum-sphere.
Definition: tetrahedronI.H:230
vector Sb() const
Definition: tetrahedronI.H:142
scalar mag() const
Return volume.
Definition: tetrahedronI.H:170
vector Sa() const
Return face normal.
Definition: tetrahedronI.H:135
static const zero Zero
Definition: zero.H:91
Point centre() const
Return centre (centroid)
Definition: tetrahedronI.H:163
bool inside(const point &pt) const
Return true if point is inside tetrahedron.
Definition: tetrahedronI.H:423
errorManip< error > abort(error &err)
Definition: errorManip.H:131
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition: HashTable.H:61
const Cmpt & x() const
Definition: VectorI.H:75
Simple random number generator.
Definition: Random.H:49
dimensioned< scalar > magSqr(const dimensioned< Type > &)
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:53
const Point & rawPoint() const
Return point with no checking.
Definition: PointHit.H:158
static const char nl
Definition: Ostream.H:262
dimensioned< Type > min(const dimensioned< Type > &, const dimensioned< Type > &)
A normal distribution model.
const dimensionedScalar mu
Atomic mass unit.
triPointRef tri(const label facei) const
Return i-th face.
Definition: tetrahedronI.H:101
dimensionedScalar pow3(const dimensionedScalar &ds)
barycentric pointToBarycentric(const point &pt) const
Calculate the barycentric coordinates from the given point.
Definition: tetrahedronI.H:274
const dimensionedScalar c
Speed of light in a vacuum.
dimensionedScalar lambda(laminarTransport.lookup("lambda"))
pointHit nearestPoint(const point &p) const
Return nearest point to p on tetrahedron. Is p itself.
Definition: tetrahedronI.H:329
triangle< point, const point & > triPointRef
Definition: triPointRef.H:44
dimensioned< scalar > mag(const dimensioned< Type > &)
label n
PointHit< point > pointHit
Definition: pointHit.H:41
Point randomPoint(Random &rndGen) const
Return a random point in the tetrahedron from a.
Definition: tetrahedronI.H:244
scalar distance() const
Return distance to hit.
Definition: PointHit.H:139
volScalarField & p
vector Sc() const
Definition: tetrahedronI.H:149