triSurfaceLoader.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-2018 OpenCFD Ltd.
9 -------------------------------------------------------------------------------
10 License
11  This file is part of OpenFOAM.
12 
13  OpenFOAM is free software: you can redistribute it and/or modify it
14  under the terms of the GNU General Public License as published by
15  the Free Software Foundation, either version 3 of the License, or
16  (at your option) any later version.
17 
18  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21  for more details.
22 
23  You should have received a copy of the GNU General Public License
24  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25 
26 \*---------------------------------------------------------------------------*/
27 
28 #include "triSurfaceLoader.H"
29 #include "fileNameList.H"
30 #include "Time.H"
31 #include "OSspecific.H"
32 
33 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
34 
35 const Foam::Enum
36 <
38 >
40 ({
41  { loadingOption::SINGLE_REGION, "single" },
42  { loadingOption::FILE_REGION, "file" },
43  { loadingOption::OFFSET_REGION, "offset" },
44  { loadingOption::MERGE_REGION, "merge" },
45 });
46 
47 
48 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
49 
50 Foam::triSurfaceLoader::triSurfaceLoader(const fileName& directory)
51 :
52  directory_(directory),
53  available_(),
54  selected_()
55 {
56  readDir();
57 }
58 
59 
60 Foam::triSurfaceLoader::triSurfaceLoader(const Time& runTime)
61 :
62  directory_(runTime.constantPath()/"triSurface"),
63  available_(),
64  selected_()
65 {
66  readDir();
67 }
68 
69 
70 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
71 
73 {
74  fileNameList files = Foam::readDir(directory_, fileName::FILE);
75 
76  // Will be using triSurface
77  //
78  // - filter according to what is supported
79  //
80  // Transform from fileName to word and eliminate duplicates
81  // (eg, files with/without .gz)
82  wordHashSet names(2*files.size());
83 
84  for (const fileName& f : files)
85  {
87  {
88  names.insert(f.name());
89  }
90  }
91  available_ = names.sortedToc(); // Also hashes the names
92 
93  return available_.size();
94 }
95 
96 
98 {
99  selected_ = available_;
100  return selected_.size();
101 }
102 
103 
105 {
106  if (available_.found(name))
107  {
108  selected_ = wordList{name}; // hashedWordList::operator[] is hidden!
109  }
110  else
111  {
112  selected_.clear();
113  }
114 
115  return selected_.size();
116 }
117 
118 
119 Foam::label Foam::triSurfaceLoader::select(const wordRe& mat)
120 {
121  DynamicList<label> foundIds(available_.size());
122 
123  if (mat.isPattern())
124  {
125  foundIds = findStrings(mat, available_);
126  sort(foundIds);
127  }
128  else
129  {
130  const word& plain = mat;
131  if (available_.found(plain))
132  {
133  foundIds.append(available_[plain]);
134  }
135  else
136  {
138  << "Specified the surfaces " << mat << nl
139  << " - but could not find it"
140  << exit(FatalError);
141  }
142  }
143 
144  selected_ = wordList(available_, foundIds);
145  return selected_.size();
146 }
147 
148 
150 {
151  // Need to be more careful when select.
152  // - preserve same order as the input matcher itself
153  // - avoid duplicate selections
154  // - flag explicitly named files as missing.
155  // (Eg, foo.stl must exist, but "foo.*\.stl" is optional)
156 
157  // Track which files have already been selected
158  DynamicList<label> foundIds(available_.size());
159  labelHashSet hashedFound(2*available_.size());
160 
161  DynamicList<word> missing(matcher.size());
162  wordHashSet hashedMissing(2*matcher.size());
163 
164  // Exact matches must exist
165  for (const wordRe& mat : matcher)
166  {
167  if (mat.isPattern())
168  {
169  labelList indices = findStrings(mat, available_);
170  sort(indices);
171 
172  for (const label idx : indices)
173  {
174  if (hashedFound.insert(idx))
175  {
176  foundIds.append(idx);
177  }
178  }
179  }
180  else
181  {
182  const word& plain = mat;
183  if (available_.found(plain))
184  {
185  const label idx = available_[plain];
186  if (hashedFound.insert(idx))
187  {
188  foundIds.append(idx);
189  }
190  }
191  else if (hashedMissing.insert(plain))
192  {
193  missing.append(plain);
194  }
195  }
196  }
197 
198  if (missing.size())
199  {
201  << "Specified the surfaces " << flatOutput(matcher) << nl
202  << " - but could not find " << flatOutput(missing)
203  << exit(FatalError);
204  }
205 
206  selected_ = wordList(available_, foundIds);
207  return selected_.size();
208 }
209 
210 
212 (
213  const enum loadingOption opt,
214  const scalar scaleFactor
215 ) const
216 {
218 
219  if (selected_.empty())
220  {
221  return output;
222  }
223  else if (selected_.size() == 1)
224  {
225  // Use scaling (if any)
226  output.reset(new triSurface(directory_/selected_[0], scaleFactor));
227 
228  triSurface& surf = output();
229 
230  if
231  (
232  opt == loadingOption::SINGLE_REGION
233  || opt == loadingOption::FILE_REGION
234  )
235  {
236  for (labelledTri& f : surf)
237  {
238  f.region() = 0;
239  }
240 
241  if (surf.patches().size())
242  {
243  surf.patches().setSize(1);
244  }
245  else
246  {
247  surf.patches().append
248  (
249  geometricSurfacePatch(selected_[0].lessExt(), 0)
250  );
251  }
252  }
253 
254  return output;
255  }
256 
257 
258  List<labelledTri> faces;
260 
261  Map<label> oldToNew;
262  HashTable<label> patchNameLookup;
263  DynamicList<geometricSurfacePatch> patches(16*selected_.size());
264 
265  forAll(selected_, surfi)
266  {
267  List<labelledTri> addfaces;
268  pointField addpoints;
269 
270  triSurface addsurf(directory_/selected_[surfi]);
271 
272  addsurf.swapFaces(addfaces);
273  addsurf.swapPoints(addpoints);
274 
275  // Offset the points for all additional surfaces
276  if (surfi)
277  {
278  const label ptoff = points.size();
279 
280  for (labelledTri& f : addfaces)
281  {
282  forAll(f, fi)
283  {
284  f[fi] += ptoff;
285  }
286  }
287  }
288 
289  switch (opt)
290  {
291  case loadingOption::SINGLE_REGION:
292  {
293  for (labelledTri& f : addfaces)
294  {
295  f.region() = 0;
296  }
297 
298  if (patches.empty() && !addsurf.patches().empty())
299  {
300  patches.append(addsurf.patches().first());
301  }
302 
303  break;
304  }
305 
306  case loadingOption::FILE_REGION:
307  {
308  for (labelledTri& f : addfaces)
309  {
310  f.region() = surfi;
311  }
312 
313  // Use surface name for region
315  (
316  geometricSurfacePatch(selected_[surfi].lessExt(), surfi)
317  );
318 
319  break;
320  }
321 
322  case loadingOption::OFFSET_REGION:
323  {
324  // Collect all patches, preserving names.
325  // This will be horrible for output, but is good if we rely
326  // on the names for defining baffles.
327 
328  // region offset
329  const label regoff = patches.size();
330  patches.append(addsurf.patches());
331 
332  if (surfi)
333  {
334  for (labelledTri& f : addfaces)
335  {
336  f.region() += regoff;
337  }
338  }
339  break;
340  }
341 
342  case loadingOption::MERGE_REGION:
343  {
344  // Merge by name
345  geometricSurfacePatchList& addpatches = addsurf.patches();
346 
347  // Build lookup tables with name->id and localId -> mergedId
348  oldToNew.clear();
349  forAll(addpatches, patchi)
350  {
351  geometricSurfacePatch& p = addpatches[patchi];
352  const word& patchName = p.name();
353 
354  label patchId = patches.size();
355  if (patchNameLookup.insert(patchName, patchId))
356  {
357  p.index() = patchId;
358  patches.append(p);
359  }
360  else
361  {
362  patchId = patchNameLookup[patchName];
363  }
364 
365  oldToNew.insert(patchi, patchId);
366  }
367 
368  if (surfi)
369  {
370  // Relabel regions accordingly
371  for (labelledTri& f : addfaces)
372  {
373  f.region() = oldToNew[f.region()];
374  }
375  }
376  break;
377  }
378  }
379 
380  if (surfi)
381  {
382  faces.append(addfaces);
383  points.append(addpoints);
384  }
385  else
386  {
387  faces.transfer(addfaces);
388  points.transfer(addpoints);
389  }
390  }
391 
392  // Apply scaling (if any)
393  if (scaleFactor > VSMALL)
394  {
395  points *= scaleFactor;
396  }
397 
398  output.reset(new triSurface(faces, patches, points, true));
399 
400  return output;
401 }
402 
403 
404 // ************************************************************************* //
runTime
engineTime & runTime
Definition: createEngineTime.H:13
Foam::wordRe::isPattern
bool isPattern() const noexcept
The wordRe is treated as a pattern, not as literal string.
Definition: wordReI.H:107
OSspecific.H
Functions used by OpenFOAM that are specific to POSIX compliant operating systems and need to be repl...
p
volScalarField & p
Definition: createFieldRefs.H:8
Foam::Enum
Enum is a wrapper around a list of names/values that represent particular enumeration (or int) values...
Definition: IOstreamOption.H:57
Foam::Time
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:73
Foam::output
static Ostream & output(Ostream &os, const IntRange< T > &range)
Definition: IntRanges.C:66
Foam::fileName::FILE
A file.
Definition: fileName.H:83
Foam::triSurfaceLoader::loadingOption
loadingOption
The file loading options for triSurfaceLoader.
Definition: triSurfaceLoader.H:67
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:65
Foam::fileName
A class for handling file names.
Definition: fileName.H:73
Foam::DynamicList< label >
Foam::geometricSurfacePatch
Identifies a surface patch/zone by name and index, with geometric type.
Definition: geometricSurfacePatch.H:53
Foam::triSurfaceLoader::loadingOptionNames
static const Enum< loadingOption > loadingOptionNames
The loading enumeration names.
Definition: triSurfaceLoader.H:76
Foam::HashTable::insert
bool insert(const Key &key, const T &obj)
Copy insert a new entry, not overwriting existing entries.
Definition: HashTableI.H:180
Foam::Map< label >
Foam::List::append
void append(const T &val)
Append an element at the end of the list.
Definition: ListI.H:175
Foam::HashSet< word, Hash< word > >
Foam::triSurface::patches
const geometricSurfacePatchList & patches() const noexcept
Definition: triSurface.H:399
Foam::wordRe
A wordRe is a Foam::word, but can contain a regular expression for matching words or strings.
Definition: wordRe.H:80
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
Foam::wordList
List< word > wordList
A List of words.
Definition: fileName.H:62
Foam::triSurface::swapFaces
void swapFaces(List< labelledTri > &faceLst)
Swap the list of faces being addressed.
Definition: triSurface.C:953
Foam::triSurfaceLoader::select
label select(const word &name)
Populates 'selected' with a subset of the available files.
Definition: triSurfaceLoader.C:104
Foam::Field< vector >
Foam::triSurface
Triangulated surface description with patch information.
Definition: triSurface.H:76
Foam::triSurface::swapPoints
virtual void swapPoints(pointField &pts)
Swap points. Similar to movePoints, but returns the old points.
Definition: triSurface.C:625
Foam::List::setSize
void setSize(const label n)
Alias for resize()
Definition: List.H:222
Foam::List::transfer
void transfer(List< T > &list)
Definition: List.C:456
Foam::sort
void sort(UList< T > &a)
Definition: UList.C:261
Foam::PtrList::append
void append(T *ptr)
Append an element to the end of the list.
Definition: PtrListI.H:113
Foam::FatalError
error FatalError
Foam::flatOutput
FlatOutput::OutputAdaptor< Container, Delimiters > flatOutput(const Container &obj, Delimiters delim)
Global flatOutput() function with specified output delimiters.
Definition: FlatOutput.H:216
Foam::findStrings
labelList findStrings(const regExp &matcher, const UList< StringType > &input, const bool invert=false)
Return list indices for strings matching the regular expression.
Definition: stringListOps.H:86
Foam::triSurfaceLoader::readDir
label readDir()
Read directory and populate the 'available' files.
Definition: triSurfaceLoader.C:72
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
Foam::HashTable< label >
Time.H
Foam::autoPtr< Foam::triSurface >
fileNameList.H
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
Foam::nl
constexpr char nl
Definition: Ostream.H:404
f
labelList f(nPoints)
Foam::List< fileName >
Foam::UList
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition: HashTable.H:103
points
const pointField & points
Definition: gmvOutputHeader.H:1
Foam::triSurfaceLoader::selectAll
label selectAll()
Populates 'selected' with all available files.
Definition: triSurfaceLoader.C:97
patches
const polyBoundaryMesh & patches
Definition: convertProcessorPatches.H:65
Foam::labelledTri
A triFace with additional (region) index.
Definition: labelledTri.H:57
Foam::name
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:59
patchId
label patchId(-1)
Foam::UList::size
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
Foam::PtrListOps::names
List< word > names(const UPtrList< T > &list, const UnaryMatchPredicate &matcher)
Foam::readDir
fileNameList readDir(const fileName &directory, const fileName::Type type=fileName::FILE, const bool filtergz=true, const bool followLink=true)
Read a directory and return the entries as a fileName List.
Definition: MSwindows.C:707
triSurfaceLoader.H
Foam::triSurfaceLoader::load
autoPtr< triSurface > load(const enum loadingOption opt=loadingOption::OFFSET_REGION, const scalar scaleFactor=-1) const
Load a single file, or load and combine multiple selected files.
Definition: triSurfaceLoader.C:212
Foam::triSurface::canRead
static bool canRead(const fileName &name, bool verbose=false)
Can we read this file format?
Definition: triSurfaceIO.C:99