cut.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) 2014 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"
28 #include "searchableSurfaces.H"
29 #include "triSurfaceMesh.H"
30 #include "searchableBox.H"
31 #include "searchableRotatedBox.H"
32 #include "surfaceIntersection.H"
33 #include "intersectedSurface.H"
34 #include "edgeIntersections.H"
35 
36 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
37 
38 namespace Foam
39 {
40 namespace searchableSurfaceModifiers
41 {
43  addToRunTimeSelectionTable(searchableSurfaceModifier, cut, dictionary);
44 }
45 }
46 
47 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
48 
50 (
51  const faceList& fcs,
52  pointField& pts,
53  triSurface& cutSurf
54 ) const
55 {
56  label nTris = 0;
57  forAll(fcs, i)
58  {
59  nTris += fcs[i].size()-2;
60  }
61 
62  DynamicList<labelledTri> tris(nTris);
63 
64  forAll(fcs, i)
65  {
66  const face& f = fcs[i];
67  // Triangulate around vertex 0
68  for (label fp = 1; fp < f.size()-1; fp++)
69  {
70  tris.append(labelledTri(f[0], f[fp], f[f.fcIndex(fp)], i));
71  }
72  }
74  forAll(patches, patchI)
75  {
76  patches[patchI] = geometricSurfacePatch
77  (
78  "",
79  "patch" + Foam::name(patchI),
80  patchI
81  );
82  }
83  cutSurf = triSurface(tris.xfer(), patches, pts.xfer());
84 }
85 
86 
88 (
89  const searchableSurface& cutter,
90  triSurface& cutSurf
91 ) const
92 {
93  if (isA<searchableBox>(cutter))
94  {
95  const searchableBox& bb = refCast<const searchableBox>(cutter);
96 
97  pointField pts(bb.points());
98  triangulate(treeBoundBox::faces, pts, cutSurf);
99 
100  return cutSurf;
101  }
102  else if (isA<searchableRotatedBox>(cutter))
103  {
104  const searchableRotatedBox& bb =
105  refCast<const searchableRotatedBox>(cutter);
106 
107  pointField pts(bb.points());
108  triangulate(treeBoundBox::faces, pts, cutSurf);
109 
110  return cutSurf;
111  }
112  else if (isA<triSurfaceMesh>(cutter))
113  {
114  return const_cast<triSurfaceMesh&>
115  (
116  refCast<const triSurfaceMesh>(cutter)
117  );
118  }
119  else
120  {
122  << "Triangulation only supported for triSurfaceMesh, searchableBox"
123  << ", not for surface " << cutter.name()
124  << " of type " << cutter.type()
125  << exit(FatalError);
126  return const_cast<triSurfaceMesh&>
127  (
128  refCast<const triSurfaceMesh>(cutter)
129  );
130  }
131 }
132 
133 
134 // Keep on shuffling surface points until no more degenerate intersections.
135 // Moves both surfaces and updates set of edge cuts.
137 (
138  triSurface& surf1,
139  edgeIntersections& edgeCuts1,
140  triSurface& surf2,
141  edgeIntersections& edgeCuts2
142 ) const
143 {
144  bool hasMoved1 = false;
145  bool hasMoved2 = false;
146 
147  for (label iter = 0; iter < 10; iter++)
148  {
149  Info<< "Determining intersections of surf1 edges with surf2"
150  << " faces" << endl;
151 
152  // Determine surface1 edge intersections. Allow surface to be moved.
153 
154  // Number of iterations needed to resolve degenerates
155  label nIters1 = 0;
156  {
157  triSurfaceSearch querySurf2(surf2);
158 
159  scalarField surf1PointTol
160  (
162  );
163 
164  // Determine raw intersections
165  edgeCuts1 = edgeIntersections
166  (
167  surf1,
168  querySurf2,
169  surf1PointTol
170  );
171 
172  // Shuffle a bit to resolve degenerate edge-face hits
173  {
174  pointField points1(surf1.points());
175 
176  nIters1 =
177  edgeCuts1.removeDegenerates
178  (
179  5, // max iterations
180  surf1,
181  querySurf2,
182  surf1PointTol,
183  points1 // work array
184  );
185 
186  if (nIters1 != 0)
187  {
188  // Update geometric quantities
189  surf1.movePoints(points1);
190  hasMoved1 = true;
191  }
192  }
193  }
194 
195  Info<< "Determining intersections of surf2 edges with surf1"
196  << " faces" << endl;
197 
198  label nIters2 = 0;
199  {
200  triSurfaceSearch querySurf1(surf1);
201 
202  scalarField surf2PointTol
203  (
205  );
206 
207  // Determine raw intersections
208  edgeCuts2 = edgeIntersections
209  (
210  surf2,
211  querySurf1,
212  surf2PointTol
213  );
214 
215  // Shuffle a bit to resolve degenerate edge-face hits
216  {
217  pointField points2(surf2.points());
218 
219  nIters2 =
220  edgeCuts2.removeDegenerates
221  (
222  5, // max iterations
223  surf2,
224  querySurf1,
225  surf2PointTol,
226  points2 // work array
227  );
228 
229  if (nIters2 != 0)
230  {
231  // Update geometric quantities
232  surf2.movePoints(points2);
233  hasMoved2 = true;
234  }
235  }
236  }
237 
238 
239  if (nIters1 == 0 && nIters2 == 0)
240  {
241  //Info<< "** Resolved all intersections to be proper"
242  // << "edge-face pierce" << endl;
243  break;
244  }
245  }
246 
247  //if (hasMoved1)
248  //{
249  // fileName newFile("surf1.ftr");
250  // Info<< "Surface 1 has been moved. Writing to " << newFile
251  // << endl;
252  // surf1.write(newFile);
253  //}
254  //
255  //if (hasMoved2)
256  //{
257  // fileName newFile("surf2.ftr");
258  // Info<< "Surface 2 has been moved. Writing to " << newFile
259  // << endl;
260  // surf2.write(newFile);
261  //}
262 
263  return hasMoved1 || hasMoved2;
264 }
265 
266 
267 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
268 
270 (
271  const searchableSurfaces& geometry,
272  const dictionary& dict
273 )
274 :
275  searchableSurfaceModifier(geometry, dict),
276  cutterNames_(dict_.lookup("cutters"))
277 {}
278 
279 
280 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
281 
283 {}
284 
285 
286 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
287 
289 (
290  const labelList& regions,
291  searchableSurface& geom
292 ) const
293 {
294  triSurface& surf = refCast<triSurfaceMesh>(geom);
295 
296  bool changed = false;
297 
298  // Find the surfaces to cut with
299  forAll(cutterNames_, cutNameI)
300  {
301  labelList geomIDs =
302  findStrings(cutterNames_[cutNameI], geometry_.names());
303 
304  forAll(geomIDs, j)
305  {
306  label geomI = geomIDs[j];
307  const searchableSurface& cutter = geometry_[geomI];
308 
309  // Triangulate
310  triSurface work;
311  triSurface& cutSurf = triangulate(cutter, work);
312 
313  // Determine intersection (with perturbation)
314  edgeIntersections edge1Cuts;
315  edgeIntersections edge2Cuts;
316  intersectSurfaces
317  (
318  surf,
319  edge1Cuts,
320  cutSurf,
321  edge2Cuts
322  );
323 
324 
325  // Determine intersection edges
326  surfaceIntersection inter(surf, edge1Cuts, cutSurf, edge2Cuts);
327 
328 
329  // Use intersection edges to cut up faces. (does all the hard work)
330  intersectedSurface surf3(surf, true, inter);
331 
332 
333  // Mark triangles based on whether they are inside or outside
334  List<volumeType> volTypes;
335  cutter.getVolumeType(surf3.faceCentres(), volTypes);
336 
337  label nInside = 0;
338  forAll(volTypes, i)
339  {
340  if (volTypes[i] == volumeType::INSIDE)
341  {
342  nInside++;
343  }
344  }
345 
346  // Add a patch for inside the box
347  if (nInside > 0 && surf3.patches().size() > 0)
348  {
349  geometricSurfacePatchList newPatches(surf3.patches());
350  label sz = newPatches.size();
351  newPatches.setSize(sz+1);
352  newPatches[sz] = geometricSurfacePatch
353  (
354  newPatches[sz-1].geometricType(),
355  newPatches[sz-1].name() + "_inside",
356  newPatches[sz-1].index()
357  );
358 
359  Info<< "Moving " << nInside << " out of " << surf3.size()
360  << " triangles to region "
361  << newPatches[sz].name() << endl;
362 
363 
364  List<labelledTri> newTris(surf3);
365  forAll(volTypes, i)
366  {
367  if (volTypes[i] == volumeType::INSIDE)
368  {
369  newTris[i].region() = sz;
370  }
371  }
372  pointField newPoints(surf3.points());
373  surf = triSurface(newTris.xfer(), newPatches, newPoints.xfer());
374 
375  changed = true;
376  }
377  }
378  }
379 
380  return changed;
381 }
382 
383 
384 // ************************************************************************* //
Foam::pointField
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:42
Foam::scalarField
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
Definition: primitiveFieldsFwd.H:48
Foam::volumeType::INSIDE
@ INSIDE
Definition: volumeType.H:63
edgeIntersections.H
Foam::labelList
List< label > labelList
A List of labels.
Definition: labelList.H:56
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:406
Foam::searchableSurfaceModifiers::cut::modify
virtual bool modify(const labelList &regions, searchableSurface &) const
Apply this selector.
searchableBox.H
Foam::addToRunTimeSelectionTable
addToRunTimeSelectionTable(ensightPart, ensightPartCells, istream)
Foam::searchableSurfaceModifiers::cut::~cut
virtual ~cut()
Destructor.
Foam::geometricSurfacePatchList
List< geometricSurfacePatch > geometricSurfacePatchList
Definition: geometricSurfacePatchList.H:44
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
surfaceIntersection.H
searchableSurfaces.H
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:59
Foam::triSurface
Triangulated surface description with patch information.
Definition: triSurface.H:57
Foam::Info
messageStream Info
Foam::treeBoundBox::faces
static const faceList faces
Face to point addressing.
Definition: treeBoundBox.H:154
Foam::searchableSurfaceModifiers::cut::intersectSurfaces
bool intersectSurfaces(triSurface &surf1, edgeIntersections &edgeCuts1, triSurface &surf2, edgeIntersections &edgeCuts2) const
Intersect surfaces. Perturb to avoid degenerates.
Foam::edgeIntersections::minEdgeLength
static scalarField minEdgeLength(const triSurface &surf)
Calculate min edge length for every surface point.
Definition: edgeIntersections.C:494
cut
Patchify triangles based on orientation w.r.t other (triangulated or triangulatable) surfaces.
dict
dictionary dict
Definition: searchingEngine.H:14
Foam::FatalError
error FatalError
intersectedSurface.H
addToRunTimeSelectionTable.H
Macros for easy insertion into run-time selection tables.
cut.H
Foam
Namespace for OpenFOAM.
Definition: combustionModel.C:30
Foam::searchableSurfaceModifiers::cut::cut
cut(const searchableSurfaces &, const dictionary &)
Construct from dictionary.
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
Foam::findStrings
bool findStrings(const wordReListMatcher &matcher, const std::string &str)
Return true if string matches one of the regular expressions.
Definition: stringListOps.H:52
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:318
f
labelList f(nPoints)
Foam::faceList
List< face > faceList
Definition: faceListFwd.H:43
patches
patches[0]
Definition: createSingleCellMesh.H:36
List
Definition: Test.C:19
searchableRotatedBox.H
Foam::searchableSurfaceModifiers::cut::triangulate
void triangulate(const faceList &, pointField &, triSurface &) const
Triangulate faces around 0th vertex.
triSurfaceMesh.H
Foam::defineTypeNameAndDebug
defineTypeNameAndDebug(combustionModel, 0)
Foam::name
word name(const complex &)
Return a string representation of a complex.
Definition: complex.C:47
lookup
stressControl lookup("compactNormalStress") >> compactNormalStress