cutTemplates.C
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) 2017-2018 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 "cut.H"
27 
28 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
29 
30 template<class AboveOp, class BelowOp>
32 (
33  const FixedList<point, 3>& tri,
34  const FixedList<scalar, 3>& level,
35  const AboveOp& aboveOp,
36  const BelowOp& belowOp
37 )
38 {
39  // If everything is positive or negative, then process the triangle as a
40  // whole, and do a quick return
41  if (level[0] >= 0 && level[1] >= 0 && level[2] >= 0)
42  {
43  return aboveOp(tri) + belowOp();
44  }
45  if (level[0] <= 0 && level[1] <= 0 && level[2] <= 0)
46  {
47  return aboveOp() + belowOp(tri);
48  }
49 
50  // There will be just one edge without a sign change. Find it, and put it
51  // opposite the first vertex. This may change the sign of the tri.
52  FixedList<label, 3> indices({0, 1, 2});
53  label i;
54  for (i = 0; i < 3; ++ i)
55  {
56  if (level[(i + 1)%3]*level[(i + 2)%3] >= 0)
57  {
58  Swap(indices[0], indices[i]);
59  break;
60  }
61  }
62  if (i == 3)
63  {
65  << "The number of tri vertices above the level set should always "
66  << "be 1" << exit(FatalError);
67  }
68 
69  // Correct the sign
70  if (indices[0] != 0)
71  {
72  Swap(indices[1], indices[2]);
73  }
74 
75  // Permute the data
76  const FixedList<point, 3> p = triReorder(tri, indices);
77  const FixedList<scalar, 3> l = triReorder(level, indices);
78  AboveOp a = triReorder(aboveOp, indices);
79  BelowOp b = triReorder(belowOp, indices);
80 
81  // Slice off one corner to form a tri and a quad
82  Pair<scalar> f;
83  for (label i = 0; i < 2; ++ i)
84  {
85  f[i] = l[0]/(l[0] - l[i+1]);
86  }
87  if (l[0] > 0)
88  {
89  return triCutTri(a, p, f) + triCutQuad(b, p, f);
90  }
91  else
92  {
93  return triCutQuad(a, p, f) + triCutTri(b, p, f);
94  }
95 }
96 
97 
98 template<class AboveOp, class BelowOp>
100 (
101  const FixedList<point, 3>& tri,
102  const plane& p,
103  const AboveOp& aboveOp,
104  const BelowOp& belowOp
105 )
106 {
107  // Set the level set to the signed distance from the plane
108  FixedList<scalar, 3> level;
109  for (label i = 0; i < 3; ++ i)
110  {
111  level[i] = (tri[i] - p.refPoint()) & p.normal();
112  }
113 
114  // Run the level set function
115  return triCut(tri, level, aboveOp, belowOp);
116 }
117 
118 
119 template<class AboveOp, class BelowOp>
121 (
122  const FixedList<point, 4>& tet,
123  const FixedList<scalar, 4>& level,
124  const AboveOp& aboveOp,
125  const BelowOp& belowOp
126 )
127 {
128  // Get the min and max over all four vertices and quick return if there is
129  // no change of sign
130  scalar levelMin = vGreat, levelMax = - vGreat;
131  for (label i = 0; i < 4; ++ i)
132  {
133  levelMin = min(levelMin, level[i]);
134  levelMax = max(levelMax, level[i]);
135  }
136  if (levelMin >= 0)
137  {
138  return aboveOp(tet) + belowOp();
139  }
140  if (levelMax <= 0)
141  {
142  return aboveOp() + belowOp(tet);
143  }
144 
145  // Partition the level so that positive values are at the start. This is
146  // like a single iteration of quick-sort, except that the pivot is a hard-
147  // coded zero, rather than an element of the array. This can change the sign
148  // of the tet.
149  FixedList<label, 4> indices({0, 1, 2, 3});
150  bool signChange = false;
151  label i = 0, j = 3;
152  while (true)
153  {
154  while (i < j && level[indices[i]] > 0)
155  {
156  i ++;
157  }
158  while (j > i && level[indices[j]] <= 0)
159  {
160  j --;
161  }
162  if (i == j)
163  {
164  break;
165  }
166  Swap(indices[i], indices[j]);
167  signChange = !signChange;
168  }
169 
170  // The number of vertices above the slice
171  label n = i;
172 
173  // If there are more positives than negatives then reverse the order so that
174  // the negatives are at the start
175  if (n > 2)
176  {
177  n = 4 - n;
178  for (label i = 0; i < 2; ++ i)
179  {
180  Swap(indices[i], indices[3-i]);
181  }
182  }
183 
184  // Correct the sign
185  if (signChange)
186  {
187  Swap(indices[2], indices[3]);
188  }
189 
190  // Permute the data
191  const FixedList<point, 4> p = tetReorder(tet, indices);
192  const FixedList<scalar, 4> l = tetReorder(level, indices);
193  AboveOp a = tetReorder(aboveOp, indices);
194  BelowOp b = tetReorder(belowOp, indices);
195 
196  // Calculate the integrals above and below the level set
197  if (n == 1)
198  {
199  // Slice off one corner to form a tet and a prism
200  FixedList<scalar, 3> f;
201  for (label i = 0; i < 3; ++ i)
202  {
203  f[i] = l[0]/(l[0] - l[i+1]);
204  }
205  if (l[0] > 0)
206  {
207  return tetCutTet(a, p, f) + tetCutPrism0(b, p, f);
208  }
209  else
210  {
211  return tetCutPrism0(a, p, f) + tetCutTet(b, p, f);
212  }
213  }
214  else if (n == 2)
215  {
216  // Slice off two corners to form two prisms
217  FixedList<scalar, 4> f;
218  for (label i = 0; i < 2; ++ i)
219  {
220  for (label j = 0; j < 2; ++ j)
221  {
222  f[2*i+j] = l[i]/(l[i] - l[j+2]);
223  }
224  }
225  if (l[0] > 0)
226  {
227  return tetCutPrism01(a, p, f) + tetCutPrism23(b, p, f);
228  }
229  else
230  {
231  return tetCutPrism23(a, p, f) + tetCutPrism01(b, p, f);
232  }
233  }
234 
236  << "The number of tet vertices above the level set should always be "
237  << "either 1 or 2" << exit(FatalError);
238 
239  return aboveOp() + belowOp();
240 }
241 
242 
243 template<class AboveOp, class BelowOp>
245 (
246  const FixedList<point, 4>& tet,
247  const plane& p,
248  const AboveOp& aboveOp,
249  const BelowOp& belowOp
250 )
251 {
252  // Set the level set to the signed distance from the plane
253  FixedList<scalar, 4> level;
254  for (label i = 0; i < 4; ++ i)
255  {
256  level[i] = (tet[i] - p.refPoint()) & p.normal();
257  }
258 
259  // Run the level set function
260  return tetCut(tet, level, aboveOp, belowOp);
261 }
262 
263 // ************************************************************************* //
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
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
error FatalError
Trait to determine the result of the addition of two operations.
Definition: cut.H:441
dimensioned< Type > max(const dimensioned< Type > &, const dimensioned< Type > &)
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:319
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.
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:98
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:50
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. Templated.
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:122
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:62
void Swap(T &a, T &b)
Definition: Swap.H:43
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:110
labelList f(nPoints)
dimensioned< Type > min(const dimensioned< Type > &, const dimensioned< Type > &)
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:74
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:38
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:86
label n