surfaceSubset.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) 2011-2016 OpenFOAM Foundation
9  Copyright (C) 2015-2020 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
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 Application
28  surfaceSubset
29 
30 Group
31  grpSurfaceUtilities
32 
33 Description
34  A surface analysis tool that subsets the triSurface to choose a
35  region of interest. Based on subsetMesh.
36 
37 \*---------------------------------------------------------------------------*/
38 
39 #include "triSurfaceSearch.H"
40 #include "MeshedSurfaces.H"
41 #include "argList.H"
42 #include "Fstream.H"
43 #include "IOdictionary.H"
44 #include "boundBox.H"
45 #include "indexedOctree.H"
46 #include "treeDataTriSurface.H"
47 #include "Random.H"
48 #include "volumeType.H"
49 #include "plane.H"
50 
51 using namespace Foam;
52 
53 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
54 
55 int main(int argc, char *argv[])
56 {
58  (
59  "A surface analysis tool that subsets the surface to choose a"
60  " region of interest."
61  );
62 
64  argList::addArgument("dict", "The surfaceSubsetDict");
65  argList::addArgument("input", "The input surface file");
66  argList::addArgument("output", "The output surface file");
67  argList args(argc, argv);
68 
69  Info<< "Reading dictionary " << args[1] << " ..." << endl;
70  IFstream dictFile(args[1]);
71  dictionary meshSubsetDict(dictFile);
72 
73  Info<< "Reading surface " << args[2] << " ..." << endl;
74 
75  meshedSurface surf1(args[2]);
76 
77  const fileName outFileName(args[3]);
78 
79 
80  Info<< "Original:" << endl;
81  surf1.writeStats(Info);
82  Info<< endl;
83 
84 
85  labelList markedPoints
86  (
87  meshSubsetDict.lookup("localPoints")
88  );
89 
90  labelList markedEdges
91  (
92  meshSubsetDict.lookup("edges")
93  );
94 
95  labelList markedFaces
96  (
97  meshSubsetDict.lookup("faces")
98  );
99 
100  pointField markedZone
101  (
102  meshSubsetDict.lookup("zone")
103  );
104 
105 
106  boundBox zoneBb;
107 
108  if (markedZone.size())
109  {
110  if (markedZone.size() != 2)
111  {
113  << "zone specification should be two points, min and max of "
114  << "the boundingbox" << endl
115  << "zone:" << markedZone
116  << exit(FatalError);
117  }
118 
119  zoneBb.min() = markedZone[0];
120  zoneBb.max() = markedZone[1];
121 
122  if (!zoneBb.valid())
123  {
125  << "Defined zone is invalid: " << zoneBb << nl;
126  }
127  }
128 
129 
130  const bool addFaceNeighbours =
131  meshSubsetDict.get<bool>("addFaceNeighbours");
132 
133  const bool invertSelection =
134  meshSubsetDict.getOrDefault("invertSelection", false);
135 
136  // Mark the cells for the subset
137 
138  // Faces to subset
139  bitSet facesToSubset(surf1.size(), false);
140 
141 
142  //
143  // Faces connected to "localPoints"
144  //
145 
146  if (markedPoints.size())
147  {
148  Info<< "Found " << markedPoints.size() << " marked point(s)." << endl;
149 
150  for (const label pointi : markedPoints)
151  {
152  if (pointi < 0 || pointi >= surf1.nPoints())
153  {
155  << "localPoint label " << pointi << "out of range."
156  << " Surface has " << surf1.nPoints() << " localPoints."
157  << exit(FatalError);
158  }
159 
160  const labelList& curFaces = surf1.pointFaces()[pointi];
161 
162  facesToSubset.set(curFaces);
163  }
164  }
165 
166 
167  //
168  // Faces connected to "edges"
169  //
170 
171  if (markedEdges.size())
172  {
173  Info<< "Found " << markedEdges.size() << " marked edge(s)." << endl;
174 
175  for (const label edgei : markedEdges)
176  {
177  if (edgei < 0 || edgei >= surf1.nEdges())
178  {
180  << "edge label " << edgei << "out of range."
181  << " Surface has " << surf1.nEdges() << " edges."
182  << exit(FatalError);
183  }
184 
185  const labelList& curFaces = surf1.edgeFaces()[edgei];
186 
187  facesToSubset.set(curFaces);
188  }
189  }
190 
191 
192  //
193  // Faces with centre inside "zone"
194  //
195 
196  if (zoneBb.valid())
197  {
198  Info<< "Using zone " << zoneBb << endl;
199 
200  forAll(surf1, facei)
201  {
202  const point centre = surf1[facei].centre(surf1.points());
203 
204  if (zoneBb.contains(centre))
205  {
206  facesToSubset.set(facei);
207  }
208  }
209  }
210 
211 
212  //
213  // Faces on certain side of surface
214  //
215 
216  if (meshSubsetDict.found("surface"))
217  {
218  const dictionary& surfDict = meshSubsetDict.subDict("surface");
219 
220  const fileName surfName(surfDict.get<fileName>("name"));
221 
222  const volumeType::type volType =
223  (
224  surfDict.getOrDefault("outside", false)
227  );
228 
229  Info<< "Selecting faces with centre located "
230  << volumeType::names[volType] << " of surface "
231  << surfName << endl;
232 
233  // Read surface to select on
234  triSurface selectSurf(surfName);
235 
236  triSurfaceSearch searchSelectSurf
237  (
238  selectSurf,
240  8
241  );
242 
243  const indexedOctree<treeDataTriSurface>& selectTree =
244  searchSelectSurf.tree();
245 
246  // Check if face (centre) is in outside or inside.
247  forAll(surf1, facei)
248  {
249  if (!facesToSubset[facei])
250  {
251  const point fc(surf1[facei].centre(surf1.points()));
252 
253  if (volType == selectTree.getVolumeType(fc))
254  {
255  facesToSubset.set(facei);
256  }
257  }
258  }
259  }
260 
261 
262  if (meshSubsetDict.found("plane"))
263  {
264  const dictionary& planeDict = meshSubsetDict.subDict("plane");
265 
266  const plane pl(planeDict);
267  const scalar distance(planeDict.get<scalar>("distance"));
268  const scalar cosAngle(planeDict.get<scalar>("cosAngle"));
269 
270  // Select all triangles that are close to the plane and
271  // whose normal aligns with the plane as well.
272 
273  forAll(surf1.faceCentres(), facei)
274  {
275  const point& fc = surf1.faceCentres()[facei];
276  const point& nf = surf1.faceNormals()[facei];
277 
278  if (pl.distance(fc) < distance && mag(pl.normal() & nf) > cosAngle)
279  {
280  facesToSubset.set(facei);
281  }
282  }
283  }
284 
285 
286 
287  //
288  // pick up specified "faces"
289  //
290 
291  // Number of additional faces picked up because of addFaceNeighbours
292  label nFaceNeighbours = 0;
293 
294  if (markedFaces.size())
295  {
296  Info<< "Found " << markedFaces.size() << " marked face(s)." << endl;
297 
298  // Check and mark faces to pick up
299  for (const label facei : markedFaces)
300  {
301  if (facei < 0 || facei >= surf1.size())
302  {
304  << "Face label " << facei << "out of range."
305  << " Surface has " << surf1.size() << " faces."
306  << exit(FatalError);
307  }
308 
309  // Mark the face
310  facesToSubset.set(facei);
311 
312  // Mark its neighbours if requested
313  if (addFaceNeighbours)
314  {
315  const labelList& curFaces = surf1.faceFaces()[facei];
316 
317  for (const label neiFacei : curFaces)
318  {
319  if (facesToSubset.set(neiFacei))
320  {
321  ++nFaceNeighbours;
322  }
323  }
324  }
325  }
326  }
327 
328  if (addFaceNeighbours)
329  {
330  Info<< "Added " << nFaceNeighbours
331  << " faces because of addFaceNeighbours" << endl;
332  }
333 
334 
335  if (invertSelection)
336  {
337  Info<< "Inverting selection." << endl;
338 
339  facesToSubset.flip();
340  }
341 
342 
343  // Create subsetted surface
344  meshedSurface surf2(surf1.subsetMesh(facesToSubset));
345 
346  Info<< "Subset:" << endl;
347  surf2.writeStats(Info);
348  Info<< endl;
349 
350  Info<< "Writing surface to " << outFileName << endl;
351 
352  surf2.write(outFileName);
353 
354  Info<< "\nEnd\n" << endl;
355 
356  return 0;
357 }
358 
359 
360 // ************************************************************************* //
Foam::volumeType::type
type
Volume classification types.
Definition: volumeType.H:65
Foam::fileName
A class for handling file names.
Definition: fileName.H:69
Foam::bitSet
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
Definition: bitSet.H:64
Foam::IFstream
Input from file stream, using an ISstream.
Definition: IFstream.H:85
indexedOctree.H
Foam::argList::addNote
static void addNote(const string &note)
Add extra notes for the usage information.
Definition: argList.C:413
Foam::argList
Extract command arguments and options from the supplied argc and argv parameters.
Definition: argList.H:123
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:350
Foam::dictionary::get
T get(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Definition: dictionaryTemplates.C:81
Foam::triSurfaceSearch
Helper class to search on triSurface.
Definition: triSurfaceSearch.H:58
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
Foam::plane
Geometric class that creates a 3D plane and can return the intersection point between a line and the ...
Definition: plane.H:89
Foam::argList::addArgument
static void addArgument(const string &argName, const string &usage="")
Append a (mandatory) argument to validArgs.
Definition: argList.C:302
volumeType.H
Foam::Field< vector >
plane.H
Foam::triSurface
Triangulated surface description with patch information.
Definition: triSurface.H:76
Foam::Info
messageStream Info
Information stream (uses stdout - output is on the master only)
Foam::volumeType::names
static const Enum< volumeType::type > names
Names for the classification enumeration.
Definition: volumeType.H:76
argList.H
Foam::dictionary::subDict
const dictionary & subDict(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a sub-dictionary.
Definition: dictionary.C:528
Foam::Vector::centre
const Vector< Cmpt > & centre(const Foam::List< Vector< Cmpt >> &) const
Return *this (used for point which is a typedef to Vector<scalar>.
Definition: VectorI.H:114
Foam::indexedOctree
Non-pointer based hierarchical recursive searching.
Definition: treeDataEdge.H:50
Foam::FatalError
error FatalError
Foam::dictionary
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:121
Foam::Ostream::write
virtual bool write(const token &tok)=0
Write token to stream or otherwise handle it.
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
Foam::distance
scalar distance(const vector &p1, const vector &p2)
Definition: curveTools.C:12
Random.H
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
treeDataTriSurface.H
boundBox.H
IOdictionary.H
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:372
Foam::nl
constexpr char nl
Definition: Ostream.H:385
Fstream.H
Input/output from file streams.
Foam::Vector< scalar >
Foam::List< label >
Foam::mag
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
MeshedSurfaces.H
Foam::volumeType::INSIDE
A location inside the volume.
Definition: volumeType.H:68
Foam::List::set
std::enable_if< std::is_same< bool, TypeT >::value, bool >::type set(const label i, bool val=true)
A bitSet::set() method for a list of bool.
Definition: List.H:325
triSurfaceSearch.H
Foam::boundBox
A bounding box defined in terms of min/max extrema points.
Definition: boundBox.H:63
Foam::argList::noParallel
static void noParallel()
Remove the parallel options.
Definition: argList.C:491
Foam::dictionary::getOrDefault
T getOrDefault(const word &keyword, const T &deflt, enum keyType::option matchOpt=keyType::REGEX) const
Definition: dictionaryTemplates.C:122
Foam::MeshedSurface< face >
args
Foam::argList args(argc, argv)
WarningInFunction
#define WarningInFunction
Report a warning using Foam::Warning.
Definition: messageStream.H:298
Foam::volumeType::OUTSIDE
A location outside the volume.
Definition: volumeType.H:69