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-2022 OpenCFD Ltd.
9-------------------------------------------------------------------------------
10License
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
35const 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
51:
52 directory_(directory),
53 available_(),
54 selected_()
55{
56 readDir();
57}
58
59
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();
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_.resize(1);
109 selected_.first() = name;
110 }
111 else
112 {
113 selected_.clear();
114 }
115
116 return selected_.size();
117}
118
119
121{
122 if (mat.isPattern())
123 {
124 labelList foundIds = findStrings(mat, available_);
125 Foam::sort(foundIds);
126 selected_ = wordList(available_, foundIds);
127 }
128 else if (available_.found(static_cast<const word&>(mat)))
129 {
130 selected_.resize(1);
131 selected_.first() = mat;
132 }
133 else
134 {
136 << "Specified the surfaces " << mat << nl
137 << " - but could not find it"
138 << exit(FatalError);
139 }
140
141 return selected_.size();
142}
143
144
146{
147 // Need to be more careful when select.
148 // - preserve same order as the input matcher itself
149 // - avoid duplicate selections
150 // - flag explicitly named files as missing.
151 // (Eg, foo.stl must exist, but "foo.*\.stl" is optional)
152
153 // Track which files have already been selected
154 DynamicList<label> foundIds(available_.size());
155 labelHashSet hashedFound(2*available_.size());
156
157 DynamicList<word> missing(matcher.size());
158 wordHashSet hashedMissing(2*matcher.size());
159
160 // Exact matches must exist
161 for (const wordRe& mat : matcher)
162 {
163 if (mat.isPattern())
164 {
165 labelList indices = findStrings(mat, available_);
166 Foam::sort(indices);
167
168 for (const label idx : indices)
169 {
170 if (hashedFound.insert(idx))
171 {
172 foundIds.append(idx);
173 }
174 }
175 }
176 else
177 {
178 const word& plain = mat;
179 const label idx = available_.find(plain);
180
181 if (idx >= 0)
182 {
183 if (hashedFound.insert(idx))
184 {
185 foundIds.append(idx);
186 }
187 }
188 else if (hashedMissing.insert(plain))
189 {
190 missing.append(plain);
191 }
192 }
193 }
194
195 if (missing.size())
196 {
198 << "Specified the surfaces " << flatOutput(matcher) << nl
199 << " - but could not find " << flatOutput(missing)
200 << exit(FatalError);
201 }
202
203 selected_ = wordList(available_, foundIds);
204 return selected_.size();
205}
206
207
209(
210 const enum loadingOption opt,
211 const scalar scaleFactor
212) const
213{
215
216 if (selected_.empty())
217 {
218 return output;
219 }
220 else if (selected_.size() == 1)
221 {
222 // Use scaling (if any)
223 output.reset(new triSurface(directory_/selected_[0], scaleFactor));
224
225 triSurface& surf = output();
226
227 if
228 (
229 opt == loadingOption::SINGLE_REGION
230 || opt == loadingOption::FILE_REGION
231 )
232 {
233 for (labelledTri& f : surf)
234 {
235 f.region() = 0;
236 }
237
238 if (surf.patches().size())
239 {
240 surf.patches().resize(1);
241 }
242 else
243 {
244 surf.patches().append
245 (
246 geometricSurfacePatch(selected_[0].lessExt(), 0)
247 );
248 }
249 }
250
251 return output;
252 }
253
254
255 List<labelledTri> faces;
257
258 Map<label> oldToNew;
259 HashTable<label> patchNameLookup;
260 DynamicList<geometricSurfacePatch> patches(16*selected_.size());
261
262 forAll(selected_, surfi)
263 {
264 List<labelledTri> addfaces;
265 pointField addpoints;
266
267 triSurface addsurf(directory_/selected_[surfi]);
268
269 addsurf.swapFaces(addfaces);
270 addsurf.swapPoints(addpoints);
271
272 // Offset the points for all additional surfaces
273 if (surfi)
274 {
275 const label ptoff = points.size();
276
277 for (labelledTri& f : addfaces)
278 {
279 forAll(f, fi)
280 {
281 f[fi] += ptoff;
282 }
283 }
284 }
285
286 switch (opt)
287 {
288 case loadingOption::SINGLE_REGION:
289 {
290 for (labelledTri& f : addfaces)
291 {
292 f.region() = 0;
293 }
294
295 if (patches.empty() && !addsurf.patches().empty())
296 {
297 patches.append(addsurf.patches().first());
298 }
299
300 break;
301 }
302
303 case loadingOption::FILE_REGION:
304 {
305 for (labelledTri& f : addfaces)
306 {
307 f.region() = surfi;
308 }
309
310 // Use surface name for region
312 (
313 geometricSurfacePatch(selected_[surfi].lessExt(), surfi)
314 );
315
316 break;
317 }
318
319 case loadingOption::OFFSET_REGION:
320 {
321 // Collect all patches, preserving names.
322 // This will be horrible for output, but is good if we rely
323 // on the names for defining baffles.
324
325 // region offset
326 const label regoff = patches.size();
327 patches.append(addsurf.patches());
328
329 if (surfi)
330 {
331 for (labelledTri& f : addfaces)
332 {
333 f.region() += regoff;
334 }
335 }
336 break;
337 }
338
339 case loadingOption::MERGE_REGION:
340 {
341 // Merge by name
342 geometricSurfacePatchList& addpatches = addsurf.patches();
343
344 // Build lookup tables with name->id and localId -> mergedId
345 oldToNew.clear();
346 forAll(addpatches, patchi)
347 {
348 geometricSurfacePatch& p = addpatches[patchi];
349 const word& patchName = p.name();
350
351 label patchId = patches.size();
352 if (patchNameLookup.insert(patchName, patchId))
353 {
354 p.index() = patchId;
356 }
357 else
358 {
359 patchId = patchNameLookup[patchName];
360 }
361
362 oldToNew.insert(patchi, patchId);
363 }
364
365 if (surfi)
366 {
367 // Relabel regions accordingly
368 for (labelledTri& f : addfaces)
369 {
370 f.region() = oldToNew[f.region()];
371 }
372 }
373 break;
374 }
375 }
376
377 if (surfi)
378 {
379 faces.append(addfaces);
380 points.append(addpoints);
381 }
382 else
383 {
384 faces.transfer(addfaces);
385 points.transfer(addpoints);
386 }
387 }
388
389 // Apply scaling (if any)
390 if (scaleFactor > VSMALL)
391 {
392 points *= scaleFactor;
393 }
394
395 output.reset(new triSurface(faces, patches, points, true));
396
397 return output;
398}
399
400
401// ************************************************************************* //
Functions used by OpenFOAM that are specific to POSIX compliant operating systems and need to be repl...
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition: DynamicList.H:72
void append(const T &val)
Copy append an element to the end of this list.
Definition: DynamicListI.H:503
Enum is a wrapper around a list of names/values that represent particular enumeration (or int) values...
Definition: Enum.H:61
bool insert(const Key &key)
Insert a new entry, not overwriting existing entries.
Definition: HashSet.H:191
A HashTable similar to std::unordered_map.
Definition: HashTable.H:123
bool insert(const Key &key, const T &obj)
Copy insert a new entry, not overwriting existing entries.
Definition: HashTableI.H:180
void clear()
Clear all entries from table.
Definition: HashTable.C:678
const word & name() const noexcept
Return the object name.
Definition: IOobjectI.H:65
void transfer(List< T > &list)
Definition: List.C:447
void append(const T &val)
Append an element at the end of the list.
Definition: ListI.H:175
void resize(const label len)
Adjust allocated size of list.
Definition: ListI.H:139
A HashTable to objects of type <T> with a label key.
Definition: Map.H:60
void append(T *ptr)
Append an element to the end of the list.
Definition: PtrListI.H:113
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:80
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition: UList.H:94
T & first()
Return the first element of the list.
Definition: UListI.H:202
bool empty() const noexcept
True if the UList is empty (ie, size() is zero)
Definition: UListI.H:427
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
bool empty() const noexcept
True if the list is empty (ie, size() is zero)
Definition: UPtrListI.H:113
label size() const noexcept
The number of elements in the list.
Definition: UPtrListI.H:106
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition: autoPtr.H:66
virtual tmp< triSurfacePointScalarField > load()
Load the cell size field.
A class for handling file names.
Definition: fileName.H:76
@ FILE
A regular file.
Definition: fileName.H:83
Identifies a surface patch/zone by name and index, with geometric type.
A triFace with additional (region) index.
Definition: labelledTri.H:60
Convenience class for loading single or multiple surface files from the constant/triSurface (or other...
static const Enum< loadingOption > loadingOptionNames
The loading enumeration names.
label readDir()
Read directory and populate the 'available' files.
label selectAll()
Populates 'selected' with all available files.
label select(const word &name)
Populates 'selected' with a subset of the available files.
loadingOption
The file loading options for triSurfaceLoader.
Triangulated surface description with patch information.
Definition: triSurface.H:79
const geometricSurfacePatchList & patches() const noexcept
Definition: triSurface.H:399
virtual void swapPoints(pointField &pts)
Swap points. Similar to movePoints, but returns the old points.
Definition: triSurface.C:625
static bool canRead(const fileName &name, bool verbose=false)
Can we read this file format?
Definition: triSurfaceIO.C:99
void swapFaces(List< labelledTri > &faceLst)
Swap the list of faces being addressed.
Definition: triSurface.C:953
A wordRe is a Foam::word, but can contain a regular expression for matching words or strings.
Definition: wordRe.H:83
bool isPattern() const noexcept
The wordRe is a pattern, not a literal string.
Definition: wordReI.H:111
A class for handling words, derived from Foam::string.
Definition: word.H:68
volScalarField & p
const polyBoundaryMesh & patches
engineTime & runTime
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
const pointField & points
label patchId(-1)
List< word > wordList
A List of words.
Definition: fileName.H:63
FlatOutput::OutputAdaptor< Container, Delimiters > flatOutput(const Container &obj, Delimiters delim)
Global flatOutput() function with specified output delimiters.
Definition: FlatOutput.H:215
void sort(UList< T > &list)
Sort the list.
Definition: UList.C:342
static Ostream & output(Ostream &os, const IntRange< T > &range)
Definition: IntRanges.C:66
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:715
error FatalError
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:59
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
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:87
constexpr char nl
The newline '\n' character (0x0a)
Definition: Ostream.H:53
labelList f(nPoints)
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:333