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