cutTemplates.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) 2017 OpenFOAM Foundation
9 -------------------------------------------------------------------------------
10 License
11  This file is part of OpenFOAM.
12 
13  OpenFOAM is free software: you can redistribute it and/or modify it
14  under the terms of the GNU General Public License as published by
15  the Free Software Foundation, either version 3 of the License, or
16  (at your option) any later version.
17 
18  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21  for more details.
22 
23  You should have received a copy of the GNU General Public License
24  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25 
26 \*---------------------------------------------------------------------------*/
27 
28 #include "cut.H"
29 
30 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
31 
32 template<class AboveOp, class BelowOp>
34 (
35  const FixedList<point, 3>& tri,
36  const FixedList<scalar, 3>& level,
37  const AboveOp& aboveOp,
38  const BelowOp& belowOp
39 )
40 {
41  // If everything is positive or negative, then process the triangle as a
42  // whole, and do a quick return
43  if (level[0] >= 0 && level[1] >= 0 && level[2] >= 0)
44  {
45  return aboveOp(tri) + belowOp();
46  }
47  if (level[0] <= 0 && level[1] <= 0 && level[2] <= 0)
48  {
49  return aboveOp() + belowOp(tri);
50  }
51 
52  // There will be just one edge without a sign change. Find it, and put it
53  // opposite the first vertex. This may change the sign of the tri.
54  FixedList<label, 3> indices({0, 1, 2});
55  label i;
56  for (i = 0; i < 3; ++i)
57  {
58  if (level[(i + 1)%3]*level[(i + 2)%3] >= 0)
59  {
60  Swap(indices[0], indices[i]);
61  break;
62  }
63  }
64  if (i == 3)
65  {
67  << "The number of tri vertices above the level set should always "
68  << "be 1" << exit(FatalError);
69  }
70 
71  // Correct the sign
72  if (indices[0] != 0)
73  {
74  Swap(indices[1], indices[2]);
75  }
76 
77  // Permute the data
78  const FixedList<point, 3> p = triReorder(tri, indices);
79  const FixedList<scalar, 3> l = triReorder(level, indices);
80  AboveOp a = triReorder(aboveOp, indices);
81  BelowOp b = triReorder(belowOp, indices);
82 
83  // Slice off one corner to form a tri and a quad
84  Pair<scalar> f;
85  for (label i = 0; i < 2; ++i)
86  {
87  f[i] = l[0]/(l[0] - l[i+1]);
88  }
89  if (l[0] > 0)
90  {
91  return triCutTri(a, p, f) + triCutQuad(b, p, f);
92  }
93  else
94  {
95  return triCutQuad(a, p, f) + triCutTri(b, p, f);
96  }
97 }
98 
99 
100 template<class AboveOp, class BelowOp>
102 (
103  const FixedList<point, 3>& tri,
104  const plane& pln,
105  const AboveOp& aboveOp,
106  const BelowOp& belowOp
107 )
108 {
109  // Set the level set to the signed distance from the plane
110  FixedList<scalar, 3> level;
111  for (label i = 0; i < 3; ++i)
112  {
113  level[i] = pln.signedDistance(tri[i]);
114  }
115 
116  // Run the level set function
117  return triCut(tri, level, aboveOp, belowOp);
118 }
119 
120 
121 template<class AboveOp, class BelowOp>
123 (
124  const FixedList<point, 4>& tet,
125  const FixedList<scalar, 4>& level,
126  const AboveOp& aboveOp,
127  const BelowOp& belowOp
128 )
129 {
130  // Get the min and max over all four vertices and quick return if there is
131  // no change of sign
132  scalar levelMin = VGREAT, levelMax = - VGREAT;
133  for (label i = 0; i < 4; ++i)
134  {
135  levelMin = min(levelMin, level[i]);
136  levelMax = max(levelMax, level[i]);
137  }
138  if (levelMin >= 0)
139  {
140  return aboveOp(tet) + belowOp();
141  }
142  if (levelMax <= 0)
143  {
144  return aboveOp() + belowOp(tet);
145  }
146 
147  // Partition the level so that positive values are at the start. This is
148  // like a single iteration of quick-sort, except that the pivot is a hard-
149  // coded zero, rather than an element of the array. This can change the sign
150  // of the tet.
151  FixedList<label, 4> indices({0, 1, 2, 3});
152  bool signChange = false;
153  label i = 0, j = 3;
154  while (true)
155  {
156  while (i < j && level[indices[i]] > 0)
157  {
158  i ++;
159  }
160  while (j > i && level[indices[j]] <= 0)
161  {
162  j --;
163  }
164  if (i == j)
165  {
166  break;
167  }
168  Swap(indices[i], indices[j]);
169  signChange = !signChange;
170  }
171 
172  // The number of vertices above the slice
173  label n = i;
174 
175  // If there are more positives than negatives then reverse the order so that
176  // the negatives are at the start
177  if (n > 2)
178  {
179  n = 4 - n;
180  for (label i = 0; i < 2; ++i)
181  {
182  Swap(indices[i], indices[3-i]);
183  }
184  }
185 
186  // Correct the sign
187  if (signChange)
188  {
189  Swap(indices[2], indices[3]);
190  }
191 
192  // Permute the data
193  const FixedList<point, 4> p = tetReorder(tet, indices);
194  const FixedList<scalar, 4> l = tetReorder(level, indices);
195  AboveOp a = tetReorder(aboveOp, indices);
196  BelowOp b = tetReorder(belowOp, indices);
197 
198  // Calculate the integrals above and below the level set
199  if (n == 1)
200  {
201  // Slice off one corner to form a tet and a prism
202  FixedList<scalar, 3> f;
203  for (label i = 0; i < 3; ++i)
204  {
205  f[i] = l[0]/(l[0] - l[i+1]);
206  }
207  if (l[0] > 0)
208  {
209  return tetCutTet(a, p, f) + tetCutPrism0(b, p, f);
210  }
211  else
212  {
213  return tetCutPrism0(a, p, f) + tetCutTet(b, p, f);
214  }
215  }
216  else if (n == 2)
217  {
218  // Slice off two corners to form two prisms
219  FixedList<scalar, 4> f;
220  for (label i = 0; i < 2; ++i)
221  {
222  for (label j = 0; j < 2; ++j)
223  {
224  f[2*i+j] = l[i]/(l[i] - l[j+2]);
225  }
226  }
227  if (l[0] > 0)
228  {
229  return tetCutPrism01(a, p, f) + tetCutPrism23(b, p, f);
230  }
231  else
232  {
233  return tetCutPrism23(a, p, f) + tetCutPrism01(b, p, f);
234  }
235  }
236 
238  << "The number of tet vertices above the level set should always be "
239  << "either 1 or 2" << exit(FatalError);
240 
241  return aboveOp() + belowOp();
242 }
243 
244 
245 template<class AboveOp, class BelowOp>
247 (
248  const FixedList<point, 4>& tet,
249  const plane& pln,
250  const AboveOp& aboveOp,
251  const BelowOp& belowOp
252 )
253 {
254  // Set the level set to the signed distance from the plane
255  FixedList<scalar, 4> level;
256  for (label i = 0; i < 4; ++i)
257  {
258  level[i] = pln.signedDistance(tet[i]);
259  }
260 
261  // Run the level set function
262  return tetCut(tet, level, aboveOp, belowOp);
263 }
264 
265 // ************************************************************************* //
Foam::triCutTri
const cut::uniformOp< Type > & triCutTri(const cut::uniformOp< Type > &x, const Pair< scalar > &)
Modify a uniform operation for cutting a tri from a tri (does nothing)
Definition: cutI.H:52
p
volScalarField & p
Definition: createFieldRefs.H:8
Foam::tetCutTet
const cut::uniformOp< Type > & tetCutTet(const cut::uniformOp< Type > &x, const FixedList< scalar, 3 > &)
Modify a uniform operation for cutting a tet from a tet (does nothing)
Definition: cutI.H:88
Foam::tetCutPrism23
const cut::uniformOp< Type > & tetCutPrism23(const cut::uniformOp< Type > &x, const FixedList< scalar, 4 > &)
Modify a uniform operation for cutting prism23 from a tet (does nothing)
Definition: cutI.H:124
Foam::cut::opAddResult
Trait to determine the result of the addition of two operations.
Definition: cut.H:437
Foam::Swap
void Swap(DynamicList< T, SizeMin1 > &a, DynamicList< T, SizeMin2 > &b)
Definition: DynamicListI.H:909
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
Foam::tetReorder
const cut::uniformOp< Type > & tetReorder(const cut::uniformOp< Type > &x, const FixedList< label, 4 > &)
Modify a uniform operation for reordering a tet (does nothing)
Definition: cutI.H:76
n
label n
Definition: TABSMDCalcMethod2.H:31
Foam::tetCutPrism01
const cut::uniformOp< Type > & tetCutPrism01(const cut::uniformOp< Type > &x, const FixedList< scalar, 4 > &)
Modify a uniform operation for cutting prism01 from a tet (does nothing)
Definition: cutI.H:112
Foam::constant::physicoChemical::b
const dimensionedScalar b
Wien displacement law constant: default SI units: [m.K].
Definition: createFields.H:27
cut.H
Functions for cutting triangles and tetrahedra. Generic operations are applied to each half of a cut.
Foam::tetCutPrism0
const cut::uniformOp< Type > & tetCutPrism0(const cut::uniformOp< Type > &x, const FixedList< scalar, 3 > &)
Modify a uniform operation for cutting prism0 from a tet (does nothing)
Definition: cutI.H:100
Foam::max
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:47
Foam::FatalError
error FatalError
Foam::triReorder
const cut::uniformOp< Type > & triReorder(const cut::uniformOp< Type > &x, const FixedList< label, 3 > &)
Modify a uniform operation for reordering a tri (does nothing)
Definition: cutI.H:40
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
Foam::triCutQuad
const cut::uniformOp< Type > & triCutQuad(const cut::uniformOp< Type > &x, const Pair< scalar > &)
Modify a uniform operation for cutting a quad from a tri (does nothing)
Definition: cutI.H:64
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:372
Foam::tetCut
cut::opAddResult< AboveOp, BelowOp >::type tetCut(const FixedList< point, 4 > &tet, const FixedList< scalar, 4 > &level, const AboveOp &aboveOp, const BelowOp &belowOp)
As triCut, but for a tetrahedron.
f
labelList f(nPoints)
Foam::triCut
cut::opAddResult< AboveOp, BelowOp >::type triCut(const FixedList< point, 3 > &tri, const FixedList< scalar, 3 > &level, const AboveOp &aboveOp, const BelowOp &belowOp)
Cut a triangle along the zero plane defined by the given levels.