tetOverlapVolume.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 | Copyright (C) 2012-2015 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 "tetOverlapVolume.H"
27 #include "tetrahedron.H"
28 #include "tetPoints.H"
29 #include "polyMesh.H"
30 #include "OFstream.H"
31 #include "treeBoundBox.H"
32 #include "indexedOctree.H"
33 #include "treeDataCell.H"
34 
35 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
36 
37 namespace Foam
38 {
39  defineTypeNameAndDebug(tetOverlapVolume, 0);
40 }
41 
42 
43 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
44 
46 {}
47 
48 
49 // * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * * //
50 
51 Foam::scalar Foam::tetOverlapVolume::tetTetOverlapVol
52 (
53  const tetPoints& tetA,
54  const tetPoints& tetB
55 ) const
56 {
57  static tetPointRef::tetIntersectionList insideTets;
58  label nInside = 0;
59  static tetPointRef::tetIntersectionList cutInsideTets;
60  label nCutInside = 0;
61 
62  tetPointRef::storeOp inside(insideTets, nInside);
63  tetPointRef::storeOp cutInside(cutInsideTets, nCutInside);
64  tetPointRef::sumVolOp volInside;
65  tetPointRef::dummyOp outside;
66 
67  if ((tetA.tet().mag() < SMALL*SMALL) || (tetB.tet().mag() < SMALL*SMALL))
68  {
69  return 0.0;
70  }
71 
72  // face0
73  plane pl0(tetB[1], tetB[3], tetB[2]);
74  tetA.tet().sliceWithPlane(pl0, cutInside, outside);
75  if (nCutInside == 0)
76  {
77  return 0.0;
78  }
79 
80  // face1
81  plane pl1(tetB[0], tetB[2], tetB[3]);
82  nInside = 0;
83  for (label i = 0; i < nCutInside; i++)
84  {
85  const tetPointRef t = cutInsideTets[i].tet();
86  t.sliceWithPlane(pl1, inside, outside);
87  }
88  if (nInside == 0)
89  {
90  return 0.0;
91  }
92 
93  // face2
94  plane pl2(tetB[0], tetB[3], tetB[1]);
95  nCutInside = 0;
96  for (label i = 0; i < nInside; i++)
97  {
98  const tetPointRef t = insideTets[i].tet();
99  t.sliceWithPlane(pl2, cutInside, outside);
100  }
101  if (nCutInside == 0)
102  {
103  return 0.0;
104  }
105 
106  // face3
107  plane pl3(tetB[0], tetB[1], tetB[2]);
108  for (label i = 0; i < nCutInside; i++)
109  {
110  const tetPointRef t = cutInsideTets[i].tet();
111  t.sliceWithPlane(pl3, volInside, outside);
112  }
113 
114  return volInside.vol_;
115 }
116 
117 
118 Foam::treeBoundBox Foam::tetOverlapVolume::pyrBb
119 (
120  const pointField& points,
121  const face& f,
122  const point& fc
123 ) const
124 {
125  treeBoundBox bb(fc, fc);
126  forAll(f, fp)
127  {
128  const point& pt = points[f[fp]];
129  bb.min() = min(bb.min(), pt);
130  bb.max() = max(bb.max(), pt);
131  }
132  return bb;
133 }
134 
135 
136 // * * * * * * * * * * * Public Member Functions * * * * * * * * * * * * * //
137 
139 (
140  const primitiveMesh& meshA,
141  const label cellAI,
142  const primitiveMesh& meshB,
143  const label cellBI,
144  const treeBoundBox& cellBbB,
145  const scalar threshold
146 ) const
147 {
148  const cell& cFacesA = meshA.cells()[cellAI];
149  const point& ccA = meshA.cellCentres()[cellAI];
150 
151  const cell& cFacesB = meshB.cells()[cellBI];
152  const point& ccB = meshB.cellCentres()[cellBI];
153 
154  scalar vol = 0.0;
155 
156  forAll(cFacesA, cFA)
157  {
158  label faceAI = cFacesA[cFA];
159 
160  const face& fA = meshA.faces()[faceAI];
161  const treeBoundBox pyrA = pyrBb(meshA.points(), fA, ccA);
162  if (!pyrA.overlaps(cellBbB))
163  {
164  continue;
165  }
166 
167  bool ownA = (meshA.faceOwner()[faceAI] == cellAI);
168 
169  label tetBasePtAI = 0;
170 
171  const point& tetBasePtA = meshA.points()[fA[tetBasePtAI]];
172 
173  for (label tetPtI = 1; tetPtI < fA.size() - 1; tetPtI++)
174  {
175  label facePtAI = (tetPtI + tetBasePtAI) % fA.size();
176  label otherFacePtAI = fA.fcIndex(facePtAI);
177 
178  label pt0I = -1;
179  label pt1I = -1;
180 
181  if (ownA)
182  {
183  pt0I = fA[facePtAI];
184  pt1I = fA[otherFacePtAI];
185  }
186  else
187  {
188  pt0I = fA[otherFacePtAI];
189  pt1I = fA[facePtAI];
190  }
191 
192  const tetPoints tetA
193  (
194  ccA,
195  tetBasePtA,
196  meshA.points()[pt0I],
197  meshA.points()[pt1I]
198  );
199  const treeBoundBox tetABb(tetA.bounds());
200 
201 
202  // Loop over tets of cellB
203  forAll(cFacesB, cFB)
204  {
205  label faceBI = cFacesB[cFB];
206 
207  const face& fB = meshB.faces()[faceBI];
208  const treeBoundBox pyrB = pyrBb(meshB.points(), fB, ccB);
209  if (!pyrB.overlaps(pyrA))
210  {
211  continue;
212  }
213 
214  bool ownB = (meshB.faceOwner()[faceBI] == cellBI);
215 
216  label tetBasePtBI = 0;
217 
218  const point& tetBasePtB = meshB.points()[fB[tetBasePtBI]];
219 
220  for (label tetPtI = 1; tetPtI < fB.size() - 1; tetPtI++)
221  {
222  label facePtBI = (tetPtI + tetBasePtBI) % fB.size();
223  label otherFacePtBI = fB.fcIndex(facePtBI);
224 
225  label pt0I = -1;
226  label pt1I = -1;
227 
228  if (ownB)
229  {
230  pt0I = fB[facePtBI];
231  pt1I = fB[otherFacePtBI];
232  }
233  else
234  {
235  pt0I = fB[otherFacePtBI];
236  pt1I = fB[facePtBI];
237  }
238 
239  const tetPoints tetB
240  (
241  ccB,
242  tetBasePtB,
243  meshB.points()[pt0I],
244  meshB.points()[pt1I]
245  );
246 
247  if (!tetB.bounds().overlaps(tetABb))
248  {
249  continue;
250  }
251 
252  vol += tetTetOverlapVol(tetA, tetB);
253 
254  if (vol > threshold)
255  {
256  return true;
257  }
258  }
259  }
260  }
261  }
262 
263  return false;
264 }
265 
266 
268 (
269  const primitiveMesh& meshA,
270  const label cellAI,
271  const primitiveMesh& meshB,
272  const label cellBI,
273  const treeBoundBox& cellBbB
274 ) const
275 {
276  const cell& cFacesA = meshA.cells()[cellAI];
277  const point& ccA = meshA.cellCentres()[cellAI];
278 
279  const cell& cFacesB = meshB.cells()[cellBI];
280  const point& ccB = meshB.cellCentres()[cellBI];
281 
282  scalar vol = 0.0;
283 
284  forAll(cFacesA, cFA)
285  {
286  label faceAI = cFacesA[cFA];
287 
288  const face& fA = meshA.faces()[faceAI];
289  const treeBoundBox pyrA = pyrBb(meshA.points(), fA, ccA);
290  if (!pyrA.overlaps(cellBbB))
291  {
292  continue;
293  }
294 
295  bool ownA = (meshA.faceOwner()[faceAI] == cellAI);
296 
297  label tetBasePtAI = 0;
298 
299  const point& tetBasePtA = meshA.points()[fA[tetBasePtAI]];
300 
301  for (label tetPtI = 1; tetPtI < fA.size() - 1; tetPtI++)
302  {
303  label facePtAI = (tetPtI + tetBasePtAI) % fA.size();
304  label otherFacePtAI = fA.fcIndex(facePtAI);
305 
306  label pt0I = -1;
307  label pt1I = -1;
308 
309  if (ownA)
310  {
311  pt0I = fA[facePtAI];
312  pt1I = fA[otherFacePtAI];
313  }
314  else
315  {
316  pt0I = fA[otherFacePtAI];
317  pt1I = fA[facePtAI];
318  }
319 
320  const tetPoints tetA
321  (
322  ccA,
323  tetBasePtA,
324  meshA.points()[pt0I],
325  meshA.points()[pt1I]
326  );
327  const treeBoundBox tetABb(tetA.bounds());
328 
329 
330  // Loop over tets of cellB
331  forAll(cFacesB, cFB)
332  {
333  label faceBI = cFacesB[cFB];
334 
335  const face& fB = meshB.faces()[faceBI];
336  const treeBoundBox pyrB = pyrBb(meshB.points(), fB, ccB);
337  if (!pyrB.overlaps(pyrA))
338  {
339  continue;
340  }
341 
342  bool ownB = (meshB.faceOwner()[faceBI] == cellBI);
343 
344  label tetBasePtBI = 0;
345 
346  const point& tetBasePtB = meshB.points()[fB[tetBasePtBI]];
347 
348  for (label tetPtI = 1; tetPtI < fB.size() - 1; tetPtI++)
349  {
350  label facePtBI = (tetPtI + tetBasePtBI) % fB.size();
351  label otherFacePtBI = fB.fcIndex(facePtBI);
352 
353  label pt0I = -1;
354  label pt1I = -1;
355 
356  if (ownB)
357  {
358  pt0I = fB[facePtBI];
359  pt1I = fB[otherFacePtBI];
360  }
361  else
362  {
363  pt0I = fB[otherFacePtBI];
364  pt1I = fB[facePtBI];
365  }
366 
367  const tetPoints tetB
368  (
369  ccB,
370  tetBasePtB,
371  meshB.points()[pt0I],
372  meshB.points()[pt1I]
373  );
374  if (!tetB.bounds().overlaps(tetABb))
375  {
376  continue;
377  }
378 
379  vol += tetTetOverlapVol(tetA, tetB);
380  }
381  }
382  }
383  }
384 
385  return vol;
386 }
387 
388 
390 (
391  const polyMesh& fromMesh,
392  const polyMesh& toMesh,
393  const label iTo
394 ) const
395 {
396  const indexedOctree<treeDataCell>& treeA = fromMesh.cellTree();
397 
398  treeBoundBox bbB(toMesh.points(), toMesh.cellPoints()[iTo]);
399 
400  return treeA.findBox(bbB);
401 }
402 
403 
404 // ************************************************************************* //
A tetrahedron primitive.
Definition: tetrahedron.H:62
labelList overlappingCells(const polyMesh &meshA, const polyMesh &meshB, const label cellBI) const
Return a list of cells in meshA which overlaps with cellBI in.
Store resulting tets.
Definition: tetrahedron.H:118
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:428
const indexedOctree< treeDataCell > & cellTree() const
Return the cell search tree.
Definition: polyMesh.C:843
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
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:75
A 1D vector of objects of type <T> with a fixed size <Size>.
Definition: FixedList.H:53
const point & min() const
Minimum describing the bounding box.
Definition: boundBoxI.H:54
dimensioned< Type > max(const dimensioned< Type > &, const dimensioned< Type > &)
Cell-face mesh analysis engine.
Definition: primitiveMesh.H:74
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:76
const labelListList & cellPoints() const
virtual const pointField & points() const =0
Return mesh points.
const point & max() const
Maximum describing the bounding box.
Definition: boundBoxI.H:60
Geometric class that creates a 2D plane and can return the intersection point between a line and the ...
Definition: plane.H:60
const cellList & cells() const
virtual const pointField & points() const
Return raw points.
Definition: polyMesh.C:979
label fcIndex(const label i) const
Return the forward circular index, i.e. the next index.
Definition: UListI.H:58
treeBoundBox bounds() const
Calculate the bounding box.
Definition: tetPoints.H:92
tetOverlapVolume()
Null constructor.
Sum resulting volumes.
Definition: tetrahedron.H:107
const vectorField & cellCentres() const
defineTypeNameAndDebug(combustionModel, 0)
scalar mag() const
Return volume.
Definition: tetrahedronI.H:171
dimensioned< Type > min(const dimensioned< Type > &, const dimensioned< Type > &)
bool cellCellOverlapMinDecomp(const primitiveMesh &meshA, const label cellAI, const primitiveMesh &meshB, const label cellBI, const treeBoundBox &cellBbB, const scalar threshold=0.0) const
Return true if olverlap volume is greater than threshold.
tetPointRef tet() const
Return the tetrahedron.
Definition: tetPoints.H:80
scalar cellCellOverlapVolumeMinDecomp(const primitiveMesh &meshA, const label cellAI, const primitiveMesh &meshB, const label cellBI, const treeBoundBox &cellBbB) const
Calculates the overlap volume.
Non-pointer based hierarchical recursive searching.
Definition: treeDataEdge.H:47
void sliceWithPlane(const plane &pl, AboveTetOp &aboveOp, BelowTetOp &belowOp) const
Decompose tet into tets above and below plane.
Definition: tetrahedronI.H:985
Tet storage. Null constructable (unfortunately tetrahedron<point, point> is not)
Definition: tetPoints.H:50
A cell is defined as a list of faces with extra functionality.
Definition: cell.H:56
virtual const faceList & faces() const =0
Return faces.
Standard boundBox + extra functionality for use in octree.
Definition: treeBoundBox.H:87
virtual const labelList & faceOwner() const =0
Face face-owner addresing.
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:74
bool overlaps(const boundBox &) const
Overlaps/touches boundingBox?
Definition: boundBoxI.H:120
Namespace for OpenFOAM.