triangleFuncs.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011 OpenFOAM Foundation
9  Copyright (C) 2017 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "triangleFuncs.H"
30 #include "pointField.H"
31 #include "treeBoundBox.H"
32 #include "SortableList.H"
33 #include "boolList.H"
34 #include "triPointRef.H"
35 
36 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
37 
38 void Foam::triangleFuncs::setIntersection
39 (
40  const point& oppositeSidePt,
41  const scalar oppositeSign,
42 
43  const point& thisSidePt,
44  const scalar thisSign,
45 
46  const scalar tol,
47 
48  point& pt
49 )
50 {
51  scalar denom = oppositeSign - thisSign;
52 
53  if (mag(denom) < tol)
54  {
55  // If almost does not cut choose one which certainly cuts.
56  pt = oppositeSidePt;
57  }
58  else
59  {
60  pt = oppositeSidePt + oppositeSign/denom*(thisSidePt - oppositeSidePt);
61  }
62 }
63 
64 
65 void Foam::triangleFuncs::selectPt
66 (
67  const bool select0,
68  const point& p0,
69  const point& p1,
70  point& min
71 )
72 {
73  if (select0)
74  {
75  min = p0;
76  }
77  else
78  {
79  min = p1;
80  }
81 }
82 
83 
84 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
85 
86 // Intersect triangle with parallel edges aligned with axis i0.
87 // Returns true (and intersection in pInter) if any of them intersects triangle.
89 (
90  const point& V0,
91  const point& V10,
92  const point& V20,
93  const label i0,
94  const pointField& origin,
95  const scalar maxLength,
96  point& pInter
97 )
98 {
99  // Based on Graphics Gems - Fast Ray Triangle intersection.
100  // Since direction is coordinate axis there is no need to do projection,
101  // we can directly check u,v components for inclusion in triangle.
102 
103  // Get other components
104  label i1 = (i0 + 1) % 3;
105  label i2 = (i1 + 1) % 3;
106 
107  scalar u1 = V10[i1];
108  scalar v1 = V10[i2];
109 
110  scalar u2 = V20[i1];
111  scalar v2 = V20[i2];
112 
113  scalar localScale = mag(u1)+mag(v1)+mag(u2)+mag(v2);
114 
115  scalar det = v2*u1 - u2*v1;
116 
117  // Fix for V0:(-31.71428 0 -15.10714)
118  // V10:(-1.285715 8.99165e-16 -1.142858)
119  // V20:(0 0 -1.678573)
120  // i0:0
121  if (localScale < VSMALL || Foam::mag(det)/localScale < SMALL)
122  {
123  // Triangle parallel to dir
124  return false;
125  }
126 
127  forAll(origin, originI)
128  {
129  const point& P = origin[originI];
130 
131  scalar u0 = P[i1] - V0[i1];
132  scalar v0 = P[i2] - V0[i2];
133 
134  scalar alpha = 0;
135  scalar beta = 0;
136  bool inter = false;
137 
138  if (Foam::mag(u1) < ROOTVSMALL)
139  {
140  beta = u0/u2;
141  if ((beta >= 0) && (beta <= 1))
142  {
143  alpha = (v0 - beta*v2)/v1;
144  inter = ((alpha >= 0) && ((alpha + beta) <= 1));
145  }
146  }
147  else
148  {
149  beta = (v0*u1 - u0*v1)/det;
150  if ((beta >= 0) && (beta <= 1))
151  {
152  alpha = (u0 - beta*u2)/u1;
153  inter = ((alpha >= 0) && ((alpha + beta) <= 1));
154  }
155  }
156 
157  if (inter)
158  {
159  pInter = V0 + alpha*V10 + beta*V20;
160  scalar s = (pInter - origin[originI])[i0];
161 
162  if ((s >= 0) && (s <= maxLength))
163  {
164  return true;
165  }
166  }
167  }
168  return false;
169 }
170 
171 
172 // Intersect triangle with bounding box. Return true if
173 // any of the faces of bb intersect triangle.
174 // Note: so returns false if triangle inside bb.
176 (
177  const point& p0,
178  const point& p1,
179  const point& p2,
180  const treeBoundBox& cubeBb
181 )
182 {
183  // Slow (edge by edge) bounding box intersection. TBD: replace with call
184  // to above intersectAxesBundle. However this function is not fully
185  // correct and misses intersection between some triangles.
186  {
187  const triPointRef tri(p0, p1, p2);
188 
189  const edgeList& es = treeBoundBox::edges;
190  const pointField points(cubeBb.points());
191 
192  forAll(es, i)
193  {
194  const edge& e = es[i];
195  const point& start = points[e[0]];
196  const point& end = points[e[1]];
197 
198  pointHit inter = tri.intersection
199  (
200  start,
201  end-start,
203  );
204 
205  if (inter.hit() && inter.distance() <= 1)
206  {
207  return true;
208  }
209  }
210  }
211 
212 
213  // Intersect triangle edges with bounding box
214  point pInter;
215  if (cubeBb.intersects(p0, p1, pInter))
216  {
217  return true;
218  }
219  if (cubeBb.intersects(p1, p2, pInter))
220  {
221  return true;
222  }
223  if (cubeBb.intersects(p2, p0, pInter))
224  {
225  return true;
226  }
227 
228  return false;
229 }
230 
231 
233 (
234  const point& va0,
235  const point& va10,
236  const point& va20,
237 
238  const point& base,
239  const point& normal,
240 
241  point& pInter0,
242  point& pInter1
243 )
244 {
245  // Get triangle normal
246  vector na = va10 ^ va20;
247  scalar magArea = mag(na);
248  na/magArea;
249 
250  if (mag(na & normal) > (1 - SMALL))
251  {
252  // Parallel
253  return false;
254  }
255 
256  const point va1 = va0 + va10;
257  const point va2 = va0 + va20;
258 
259  // Find the triangle point on the other side.
260  scalar sign0 = (va0 - base) & normal;
261  scalar sign1 = (va1 - base) & normal;
262  scalar sign2 = (va2 - base) & normal;
263 
264  label oppositeVertex = -1;
265 
266  if (sign0 < 0)
267  {
268  if (sign1 < 0)
269  {
270  if (sign2 < 0)
271  {
272  // All on same side of plane
273  return false;
274  }
275  else // sign2 >= 0
276  {
277  // 2 on opposite side.
278  oppositeVertex = 2;
279  }
280  }
281  else // sign1 >= 0
282  {
283  if (sign2 < 0)
284  {
285  // 1 on opposite side.
286  oppositeVertex = 1;
287  }
288  else
289  {
290  // 0 on opposite side.
291  oppositeVertex = 0;
292  }
293  }
294  }
295  else // sign0 >= 0
296  {
297  if (sign1 < 0)
298  {
299  if (sign2 < 0)
300  {
301  // 0 on opposite side.
302  oppositeVertex = 0;
303  }
304  else // sign2 >= 0
305  {
306  // 1 on opposite side.
307  oppositeVertex = 1;
308  }
309  }
310  else // sign1 >= 0
311  {
312  if (sign2 < 0)
313  {
314  // 2 on opposite side.
315  oppositeVertex = 2;
316  }
317  else // sign2 >= 0
318  {
319  // All on same side of plane
320  return false;
321  }
322  }
323  }
324 
325  scalar tol = SMALL*Foam::sqrt(magArea);
326 
327  if (oppositeVertex == 0)
328  {
329  // 0 on opposite side. Cut edges 01 and 02
330  setIntersection(va0, sign0, va1, sign1, tol, pInter0);
331  setIntersection(va0, sign0, va2, sign2, tol, pInter1);
332  }
333  else if (oppositeVertex == 1)
334  {
335  // 1 on opposite side. Cut edges 10 and 12
336  setIntersection(va1, sign1, va0, sign0, tol, pInter0);
337  setIntersection(va1, sign1, va2, sign2, tol, pInter1);
338  }
339  else // oppositeVertex == 2
340  {
341  // 2 on opposite side. Cut edges 20 and 21
342  setIntersection(va2, sign2, va0, sign0, tol, pInter0);
343  setIntersection(va2, sign2, va1, sign1, tol, pInter1);
344  }
345 
346  return true;
347 }
348 
349 
351 (
352  const point& va0,
353  const point& va10,
354  const point& va20,
355 
356  const point& vb0,
357  const point& vb10,
358  const point& vb20,
359 
360  point& pInter0,
361  point& pInter1
362 )
363 {
364  // Get triangle normals
365  vector na = va10 ^ va20;
366  na/mag(na);
367 
368  vector nb = vb10 ^ vb20;
369  nb/mag(nb);
370 
371  // Calculate intersection of triangle a with plane of b
372  point planeB0;
373  point planeB1;
374  if (!intersect(va0, va10, va20, vb0, nb, planeB0, planeB1))
375  {
376  return false;
377  }
378 
379  // ,, triangle b with plane of a
380  point planeA0;
381  point planeA1;
382  if (!intersect(vb0, vb10, vb20, va0, na, planeA0, planeA1))
383  {
384  return false;
385  }
386 
387  // Now check if intersections overlap (w.r.t. intersection of the two
388  // planes)
389 
390  vector intersection(na ^ nb);
391 
392  scalar coordB0 = planeB0 & intersection;
393  scalar coordB1 = planeB1 & intersection;
394 
395  scalar coordA0 = planeA0 & intersection;
396  scalar coordA1 = planeA1 & intersection;
397 
398  // Put information in indexable form for sorting.
399  List<point*> pts(4);
400  boolList isFromB(4);
401  SortableList<scalar> sortCoords(4);
402 
403  pts[0] = &planeB0;
404  isFromB[0] = true;
405  sortCoords[0] = coordB0;
406 
407  pts[1] = &planeB1;
408  isFromB[1] = true;
409  sortCoords[1] = coordB1;
410 
411  pts[2] = &planeA0;
412  isFromB[2] = false;
413  sortCoords[2] = coordA0;
414 
415  pts[3] = &planeA1;
416  isFromB[3] = false;
417  sortCoords[3] = coordA1;
418 
419  sortCoords.sort();
420 
421  const labelList& indices = sortCoords.indices();
422 
423  if (isFromB[indices[0]] == isFromB[indices[1]])
424  {
425  // Entry 0 and 1 are of same region (both a or both b). Hence that
426  // region does not overlap.
427  return false;
428  }
429  else
430  {
431  // Different type. Start of overlap at indices[1], end at indices[2]
432  pInter0 = *pts[indices[1]];
433  pInter1 = *pts[indices[2]];
434 
435  return true;
436  }
437 }
438 
439 
440 // ************************************************************************* //
boolList.H
Foam::PointHit::hit
bool hit() const
Is there a hit.
Definition: PointHit.H:124
Foam::intersection::HALF_RAY
Definition: intersection.H:75
s
gmvFile<< "tracers "<< particles.size()<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().x()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().y()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
Definition: gmvOutputSpray.H:25
Foam::SortableList::sort
void sort()
Forward (stable) sort the list (if changed after construction).
Definition: SortableList.C:138
Foam::treeBoundBox::points
tmp< pointField > points() const
Vertex coordinates. In octant coding.
Definition: treeBoundBox.C:92
Foam::PointHit< point >
Foam::triangleFuncs::intersectAxesBundle
static bool intersectAxesBundle(const point &V0, const point &V10, const point &V20, const label i0, const pointField &origin, const scalar maxLength, point &pInter)
Intersect triangle with parallel edges aligned with axis i0.
Definition: triangleFuncs.C:89
Foam::constant::atomic::alpha
const dimensionedScalar alpha
Fine-structure constant: default SI units: [].
Definition: readThermalProperties.H:212
Foam::treeBoundBox
Standard boundBox with extra functionality for use in octree.
Definition: treeBoundBox.H:87
Foam::edge
An edge is a list of two point labels. The functionality it provides supports the discretisation on a...
Definition: edge.H:63
Foam::treeBoundBox::edges
static const edgeList edges
Edge to point addressing.
Definition: treeBoundBox.H:153
triPointRef.H
Foam::min
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:33
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:290
Foam::triangleFuncs::intersectBb
static bool intersectBb(const point &p0, const point &p1, const point &p2, const treeBoundBox &cubeBb)
Does triangle intersect bounding box.
Definition: triangleFuncs.C:176
Foam::triangle
A triangle primitive used to calculate face normals and swept volumes.
Definition: triangle.H:62
SortableList.H
Foam::PointHit::distance
scalar distance() const
Return distance to hit.
Definition: PointHit.H:143
Foam::label
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:62
Foam::Field< vector >
treeBoundBox.H
Foam::treeBoundBox::intersects
bool intersects(const point &overallStart, const vector &overallVec, const point &start, const point &end, point &pt, direction &ptBits) const
Intersects segment; set point to intersection position and face,.
Definition: treeBoundBox.C:162
beta
dimensionedScalar beta("beta", dimless/dimTemperature, laminarTransport)
Foam::SortableList
A list that is sorted upon construction or when explicitly requested with the sort() method.
Definition: List.H:66
stdFoam::end
constexpr auto end(C &c) -> decltype(c.end())
Return iterator to the end of the container c.
Definition: stdFoam.H:115
triangleFuncs.H
pointField.H
u0
scalar u0
Definition: readInitialConditions.H:98
Foam::Vector< scalar >
Foam::List< edge >
Foam::sqrt
dimensionedScalar sqrt(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:144
Foam::mag
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
Foam::start
label ListType::const_reference const label start
Definition: ListOps.H:408
points
const pointField & points
Definition: gmvOutputHeader.H:1
Foam::constant::electromagnetic::e
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
Foam::intersection
Foam::intersection.
Definition: intersection.H:52
Foam::triangle::intersection
pointHit intersection(const point &p, const vector &q, const intersection::algorithm alg, const scalar tol=0.0) const
Fast intersection with a ray.
Definition: triangleI.H:439
Foam::SortableList::indices
const labelList & indices() const
Return the list of sorted indices. Updated every sort.
Definition: SortableList.H:113
Foam::det
dimensionedScalar det(const dimensionedSphericalTensor &dt)
Definition: dimensionedSphericalTensor.C:62
Foam::triangleFuncs::intersect
static bool intersect(const point &va0, const point &va10, const point &va20, const point &basePoint, const vector &normal, point &pInter0, point &pInter1)
Does triangle intersect plane. Return bool and set intersection segment.
Definition: triangleFuncs.C:233
p0
const volScalarField & p0
Definition: EEqn.H:36
Foam::point
vector point
Point is a vector.
Definition: point.H:43