surfaceFeatureExtract.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-2022 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  surfaceFeatureExtract
29 
30 Group
31  grpSurfaceUtilities
32 
33 Description
34  Extracts and writes surface features to file. All but the basic feature
35  extraction is a work-in-progress.
36 
37  The extraction process is driven by the \a system/surfaceFeatureExtractDict
38  dictionary, but the \a -dict option can be used to define an alternative
39  location.
40 
41  The \a system/surfaceFeatureExtractDict dictionary contains entries
42  for each extraction process.
43  The name of the individual dictionary is used to load the input surface
44  (found under \a constant/triSurface) and also as the basename for the
45  output.
46 
47  If the \c surfaces entry is present in a sub-dictionary, it has absolute
48  precedence over a surface name deduced from the dictionary name.
49  If the dictionary name itself does not have an extension, the \c surfaces
50  entry becomes mandatory since in this case the dictionary name cannot
51  represent an input surface file (ie, there is no file extension).
52  The \c surfaces entry is a wordRe list, which allows loading and
53  combining of multiple surfaces. Any exactly specified surface names must
54  exist, but surfaces selected via regular expressions need not exist.
55  The selection mechanism preserves order and is without duplicates.
56  For example,
57  \verbatim
58  dictName
59  {
60  surfaces (surface1.stl "other.*" othersurf.obj);
61  ...
62  }
63  \endverbatim
64 
65  When loading surfaces, the points/faces/regions of each surface are
66  normally offset to create an aggregated surface. No merging of points
67  or faces is done. The optional entry \c loadingOption can be used to
68  adjust the treatment of the regions when loading single or multiple files,
69  with selections according to the Foam::triSurfaceLoader::loadingOption
70  enumeration.
71  \verbatim
72  dictName
73  {
74  // Optional treatment of surface regions when loading
75  // (single, file, offset, merge)
76  loadingOption file;
77  ...
78  }
79  \endverbatim
80  The \c loadingOption is primarily used in combination with the
81  \c intersectionMethod (specifically its \c region option).
82  The default \c loadingOption is normally \c offset,
83  but this changes to \c file if the \c intersectionMethod
84  \c region is being used.
85 
86  Once surfaces have been loaded, the first stage is to extract
87  features according to the specified \c extractionMethod with values
88  as per the following table:
89  \table
90  extractionMethod | Description
91  none | No feature extraction
92  extractFromFile | Load features from the file named in featureEdgeFile
93  extractFromSurface | Extract features from surface geometry
94  \endtable
95 
96  There are a few entries that influence the extraction behaviour:
97  \verbatim
98  // File to use for extractFromFile input
99  featureEdgeFile "FileName"
100 
101  // Mark edges whose adjacent surface normals are at an angle less
102  // than includedAngle as features
103  // - 0 : selects no edges
104  // - 180: selects all edges
105  includedAngle 120;
106 
107  // Do not mark region edges
108  geometricTestOnly yes;
109  \endverbatim
110 
111  This initial set of edges can be trimmed:
112  \verbatim
113  trimFeatures
114  {
115  // Remove features with fewer than the specified number of edges
116  minElem 0;
117 
118  // Remove features shorter than the specified cumulative length
119  minLen 0.0;
120  }
121  \endverbatim
122 
123  and subsetted
124  \verbatim
125  subsetFeatures
126  {
127  // Use a plane to select feature edges (normal)(basePoint)
128  // Only keep edges that intersect the plane
129  plane (1 0 0)(0 0 0);
130 
131  // Select feature edges using a box // (minPt)(maxPt)
132  // Only keep edges inside the box:
133  insideBox (0 0 0)(1 1 1);
134 
135  // Only keep edges outside the box:
136  outsideBox (0 0 0)(1 1 1);
137 
138  // Keep nonManifold edges (edges with >2 connected faces where
139  // the faces form more than two different normal planes)
140  nonManifoldEdges yes;
141 
142  // Keep open edges (edges with 1 connected face)
143  openEdges yes;
144  }
145  \endverbatim
146 
147  Subsequently, additional features can be added from another file:
148  \verbatim
149  addFeatures
150  {
151  // Add (without merging) another extendedFeatureEdgeMesh
152  name axZ.extendedFeatureEdgeMesh;
153  }
154  \endverbatim
155 
156  The intersectionMethod provides a final means of adding additional
157  features. These are loosely termed "self-intersection", since it
158  detects the face/face intersections of the loaded surface or surfaces.
159 
160  \table
161  intersectionMethod | Description
162  none | Do nothing
163  self | All face/face intersections
164  region | Limit face/face intersections to those between different regions.
165  \endtable
166  The optional \c tolerance tuning parameter is available for handling
167  the face/face intersections, but should normally not be touched.
168 
169  As well as the normal extendedFeatureEdgeMesh written,
170  other items can be selected with boolean switches:
171 
172  \table
173  Output option | Description
174  closeness | Output the closeness of surface elements to other surface elements.
175  curvature | Output surface curvature
176  featureProximity | Output the proximity of feature points and edges to another
177  writeObj | Write features to OBJ format for postprocessing
178  writeVTK | Write closeness/curvature/proximity fields as VTK for postprocessing
179  \endtable
180 
181 Note
182  Although surfaceFeatureExtract can do many things, there are still a fair
183  number of corner cases where it may not produce the desired result.
184 \*---------------------------------------------------------------------------*/
185 
186 #include "argList.H"
187 #include "Time.H"
188 #include "triSurface.H"
189 #include "triSurfaceTools.H"
190 #include "edgeMeshTools.H"
192 #include "surfaceIntersection.H"
193 #include "featureEdgeMesh.H"
194 #include "extendedFeatureEdgeMesh.H"
195 #include "treeBoundBox.H"
196 #include "meshTools.H"
197 #include "OBJstream.H"
198 #include "triSurfaceMesh.H"
199 #include "foamVtkSurfaceWriter.H"
200 #include "unitConversion.H"
201 #include "plane.H"
202 #include "point.H"
203 #include "triSurfaceLoader.H"
204 
205 using namespace Foam;
206 
207 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
208 
209 int main(int argc, char *argv[])
210 {
212  (
213  "Extract and write surface feature lines to file.\n"
214  "Feature line extraction only valid on closed manifold surfaces."
215  );
216 
218  argList::noFunctionObjects(); // Never use function objects
219 
221  (
222  "dict",
223  "file",
224  "Read surfaceFeatureExtractDict from specified location"
225  );
226 
227  #include "setRootCase.H"
228  #include "createTime.H"
229 
230  Info<< nl
231  << "Note: "
232  << "Feature line extraction only valid on closed manifold surfaces"
233  << nl << nl;
234 
235  const word dictName("surfaceFeatureExtractDict");
237 
238  Info<< "Reading " << dictIO.name() << nl << endl;
239  const IOdictionary dict(dictIO);
240 
241  // Loader for available triSurface surface files
242  triSurfaceLoader loader(runTime);
243 
244  // Where to write VTK output files
245  const fileName vtkOutputDir = runTime.constantPath()/"triSurface";
246 
247  for (const entry& dEntry : dict)
248  {
249  if (!dEntry.isDict()) // dictionary entries only
250  {
251  continue;
252  }
253 
254  // Note - do not check for shell meta-characters
255  // - user responsibility
256 
257  const word& dictName = dEntry.keyword();
258  const dictionary& surfaceDict = dEntry.dict();
259 
260  if (!surfaceDict.found("extractionMethod"))
261  {
262  // Insist on an extractionMethod
263  continue;
264  }
265 
266  // The output name based in dictionary name (without extensions)
267  const word outputName = dictName.lessExt();
268 
271  (
272  surfaceDict
273  );
274 
275  // We don't needs the intersectionMethod yet, but can use it
276  // for setting a reasonable loading option
277  const surfaceIntersection::intersectionType selfIntersect =
279  (
280  "intersectionMethod",
281  surfaceDict,
283  );
284 
285  const Switch writeObj("writeObj", surfaceDict, Switch::OFF);
286 
287  const Switch writeVTK("writeVTK", surfaceDict, Switch::OFF);
288 
289  // The "surfaces" entry is normally optional, but make it mandatory
290  // if the dictionary name doesn't have an extension
291  // (ie, probably not a surface filename at all).
292  // If it is missing, this will fail nicely with an appropriate error
293  // message.
294  if (surfaceDict.found("surfaces") || !dictName.has_ext())
295  {
296  loader.select(surfaceDict.get<wordRes>("surfaces"));
297  }
298  else
299  {
300  loader.select(dictName);
301  }
302 
303  // DebugVar(loader.available());
304  // DebugVar(outputName);
305 
306  if (loader.selected().empty())
307  {
309  << "No surfaces specified/found for entry: "
310  << dictName << exit(FatalError);
311  }
312 
313  Info<< "Surfaces : ";
314  if (loader.selected().size() == 1)
315  {
316  Info<< loader.selected().first() << nl;
317  }
318  else
319  {
320  Info<< flatOutput(loader.selected()) << nl;
321  }
322  Info<< "Output : " << outputName << nl;
323 
324  // Loading option - default depends on context
325  triSurfaceLoader::loadingOption loadingOption =
327  (
328  "loadingOption",
329  surfaceDict,
330  (
331  selfIntersect == surfaceIntersection::SELF_REGION
334  )
335  );
336 
337  Info<<"Load options : "
338  << triSurfaceLoader::loadingOptionNames[loadingOption] << nl
339  << "Write options:"
340  << " writeObj=" << writeObj
341  << " writeVTK=" << writeVTK << nl;
342 
343  scalar scaleFactor = -1;
344  // Allow rescaling of the surface points (eg, mm -> m)
345  if (surfaceDict.readIfPresent("scale", scaleFactor) && scaleFactor > 0)
346  {
347  Info<<"Scaling : " << scaleFactor << nl;
348  }
349 
350  // Load a single file, or load and combine multiple selected files
351  autoPtr<triSurface> surfPtr = loader.load(loadingOption, scaleFactor);
352  if (!surfPtr || surfPtr->empty())
353  {
355  << "Problem loading surface(s) for entry: "
356  << dictName << exit(FatalError);
357  }
358 
359  triSurface surf = *surfPtr;
360 
361  Info<< nl
362  << "Statistics:" << nl;
363  surf.writeStats(Info);
364 
365  // Need a copy as plain faces if outputting VTK format
366  faceList faces;
367  if (writeVTK)
368  {
369  faces.setSize(surf.size());
370  forAll(surf, fi)
371  {
372  faces[fi] = surf[fi];
373  }
374  }
375 
376 
377  const dictionary* subDictPtr = nullptr;
378 
379  //
380  // Extract features using the preferred extraction method
381  //
382  autoPtr<surfaceFeatures> features = extractor().features(surf);
383 
384  // Trim set
385  // ~~~~~~~~
386 
387  // Option: "trimFeatures" (dictionary)
388  if ((subDictPtr = surfaceDict.findDict("trimFeatures")) != nullptr)
389  {
390  const dictionary& trimDict = *subDictPtr;
391 
392  const scalar minLen =
393  trimDict.getOrDefault<scalar>("minLen", 0);
394  const label minElem =
395  trimDict.getOrDefault<label>("minElem", 0);
396 
397  // Trim away small groups of features
398  if (minLen > 0 || minElem > 0)
399  {
400  if (minLen > 0)
401  {
402  Info<< "Removing features of length < "
403  << minLen << endl;
404  }
405  if (minElem > 0)
406  {
407  Info<< "Removing features with number of edges < "
408  << minElem << endl;
409  }
410 
411  features().trimFeatures
412  (
413  minLen, minElem, extractor().includedAngle()
414  );
415  }
416  }
417 
418  // Subset
419  // ~~~~~~
420 
421  // Convert to marked edges, points
422  List<surfaceFeatures::edgeStatus> edgeStat(features().toStatus());
423 
424  // Option: "subsetFeatures" (dictionary)
425  if ((subDictPtr = surfaceDict.findDict("subsetFeatures")) != nullptr)
426  {
427  const dictionary& subsetDict = *subDictPtr;
428 
429  treeBoundBox bb;
430 
431  // Suboption: "insideBox"
432  if (subsetDict.readIfPresent("insideBox", bb))
433  {
434  Info<< "Subset edges inside box " << bb << endl;
435  features().subsetBox(edgeStat, bb);
436 
437  {
438  OBJstream os("subsetBox.obj");
439 
440  Info<< "Dumping bounding box " << bb
441  << " as lines to obj file "
442  << os.name() << endl;
443 
444  os.write(bb);
445  }
446  }
447  // Suboption: "outsideBox"
448  else if (subsetDict.readIfPresent("outsideBox", bb))
449  {
450  Info<< "Exclude edges outside box " << bb << endl;
451  features().excludeBox(edgeStat, bb);
452 
453  {
454  OBJstream os("deleteBox.obj");
455 
456  Info<< "Dumping bounding box " << bb
457  << " as lines to obj file "
458  << os.name() << endl;
459 
460  os.write(bb);
461  }
462  }
463 
464  // Suboption: "nonManifoldEdges" (false: remove non-manifold edges)
465  if (!subsetDict.getOrDefault("nonManifoldEdges", true))
466  {
467  Info<< "Removing all non-manifold edges"
468  << " (edges with > 2 connected faces) unless they"
469  << " cross multiple regions" << endl;
470 
471  features().checkFlatRegionEdge
472  (
473  edgeStat,
474  1e-5, // tol
475  extractor().includedAngle()
476  );
477  }
478 
479  // Suboption: "openEdges" (false: remove open edges)
480  if (!subsetDict.getOrDefault("openEdges", true))
481  {
482  Info<< "Removing all open edges"
483  << " (edges with 1 connected face)" << endl;
484 
485  features().excludeOpen(edgeStat);
486  }
487 
488  // Suboption: "plane"
489  if (subsetDict.found("plane"))
490  {
491  plane cutPlane(subsetDict.lookup("plane"));
492 
493  Info<< "Only include feature edges that intersect the plane"
494  << " with normal " << cutPlane.normal()
495  << " and origin " << cutPlane.origin() << endl;
496 
497  features().subsetPlane(edgeStat, cutPlane);
498  }
499  }
500 
501  surfaceFeatures newSet(surf);
502  newSet.setFromStatus(edgeStat, extractor().includedAngle());
503 
504  Info<< nl << "Initial ";
505  newSet.writeStats(Info);
506 
507  boolList surfBaffleRegions(surf.patches().size(), false);
508  if (surfaceDict.found("baffles"))
509  {
510  wordRes baffleSelect(surfaceDict.get<wordRes>("baffles"));
511 
512  wordList patchNames(surf.patches().size());
513  forAll(surf.patches(), patchi)
514  {
515  patchNames[patchi] = surf.patches()[patchi].name();
516  }
517 
518  labelList indices(baffleSelect.matching(patchNames));
519 
520  for (const label patchId : indices)
521  {
522  surfBaffleRegions[patchId] = true;
523  }
524 
525  if (indices.size())
526  {
527  Info<< "Adding " << indices.size() << " baffle regions: (";
528 
529  forAll(surfBaffleRegions, patchi)
530  {
531  if (surfBaffleRegions[patchi])
532  {
533  Info<< ' ' << patchNames[patchi];
534  }
535  }
536  Info<< " )" << nl << nl;
537  }
538  }
539 
540  // Extracting and writing a extendedFeatureEdgeMesh
542  (
543  newSet,
544  runTime,
545  outputName + ".extendedFeatureEdgeMesh",
546  surfBaffleRegions
547  );
548 
549 
550  if ((subDictPtr = surfaceDict.findDict("addFeatures")) != nullptr)
551  {
552  const dictionary& addFeaturesDict = *subDictPtr;
553 
554  const word addFeName = addFeaturesDict.get<word>("name");
555 
556  Info<< "Adding (without merging) features from " << addFeName
557  << nl << endl;
558 
559  extendedFeatureEdgeMesh addFeMesh
560  (
561  IOobject
562  (
563  addFeName,
564  runTime.time().constant(),
565  "extendedFeatureEdgeMesh",
566  runTime.time(),
569  )
570  );
571  Info<< "Read " << addFeMesh.name() << nl;
572  edgeMeshTools::writeStats(Info, addFeMesh);
573 
574  feMesh.add(addFeMesh);
575  }
576 
577  if (selfIntersect != surfaceIntersection::NONE)
578  {
579  triSurfaceSearch query(surf);
580  surfaceIntersection intersect(query, surfaceDict);
581 
582  // Remove rounding noise. For consistency could use 1e-6,
583  // as per extractFromFile implementation
584 
585  intersect.mergePoints(10*SMALL);
586 
587  labelPair sizeInfo
588  (
589  intersect.cutPoints().size(),
590  intersect.cutEdges().size()
591  );
592 
593  if (intersect.cutEdges().size())
594  {
595  extendedEdgeMesh addMesh
596  (
597  intersect.cutPoints(),
598  intersect.cutEdges()
599  );
600 
601  feMesh.add(addMesh);
602 
603  sizeInfo[0] = addMesh.points().size();
604  sizeInfo[1] = addMesh.edges().size();
605  }
606  Info<< nl
607  << "intersection: "
609  << nl
610  << " points : " << sizeInfo[0] << nl
611  << " edges : " << sizeInfo[1] << nl;
612  }
613 
614  Info<< nl << "Final ";
616 
617  Info<< nl << "Writing extendedFeatureEdgeMesh to "
618  << feMesh.objectPath() << endl;
619 
620  mkDir(feMesh.path());
621 
622  if (writeObj)
623  {
624  feMesh.writeObj(feMesh.path()/outputName);
625  }
626 
627  feMesh.write();
628 
629  // Write a featureEdgeMesh (.eMesh) for backwards compatibility
630  // Used by snappyHexMesh (JUN-2017)
631  if (true)
632  {
633  featureEdgeMesh bfeMesh
634  (
635  IOobject
636  (
637  outputName + ".eMesh", // name
638  runTime.constant(), // instance
639  "triSurface",
640  runTime, // registry
644  ),
645  feMesh.points(),
646  feMesh.edges()
647  );
648 
649  Info<< nl << "Writing featureEdgeMesh to "
650  << bfeMesh.objectPath() << endl;
651 
652  bfeMesh.regIOobject::write();
653  }
654 
655 
656  // Output information
657 
658  const bool optCloseness =
659  surfaceDict.getOrDefault("closeness", false);
660 
661  const bool optProximity =
662  surfaceDict.getOrDefault("featureProximity", false);
663 
664  const bool optCurvature =
665  surfaceDict.getOrDefault("curvature", false);
666 
667 
668  // For VTK legacy format, we would need an a priori count of
669  // CellData and PointData fields.
670  // For convenience, we therefore only use the XML formats
671 
672  autoPtr<vtk::surfaceWriter> vtkWriter;
673 
674  if (optCloseness || optProximity || optCurvature)
675  {
676  if (writeVTK)
677  {
678  vtkWriter.reset
679  (
681  (
682  surf.points(),
683  faces,
684  (vtkOutputDir / outputName),
685  false // serial only
686  )
687  );
688 
689  vtkWriter->writeGeometry();
690 
691  Info<< "Writing VTK to "
692  << runTime.relativePath(vtkWriter->output()) << nl;
693  }
694  }
695  else
696  {
697  continue; // Nothing to output
698  }
699 
700 
701  // Option: "closeness"
702  if (optCloseness)
703  {
704  Pair<tmp<scalarField>> tcloseness =
706  (
707  runTime,
708  outputName,
709  surf,
710  45, // internalAngleTolerance
711  10 // externalAngleTolerance
712  );
713 
714  if (vtkWriter)
715  {
716  vtkWriter->beginCellData();
717  vtkWriter->write("internalCloseness", tcloseness[0]());
718  vtkWriter->write("externalCloseness", tcloseness[1]());
719  }
720  }
721 
722  // Option: "featureProximity"
723  if (optCloseness)
724  {
725  const scalar maxProximity =
726  surfaceDict.getOrDefault<scalar>("maxFeatureProximity", 1);
727 
728  tmp<scalarField> tproximity =
730  (
731  runTime,
732  outputName,
733  feMesh,
734  surf,
735  maxProximity
736  );
737 
738  if (vtkWriter)
739  {
740  vtkWriter->beginCellData();
741  vtkWriter->write("featureProximity", tproximity());
742  }
743  }
744 
745  // Option: "curvature"
746  if (optCurvature)
747  {
748  tmp<scalarField> tcurvature =
750  (
751  runTime,
752  outputName,
753  surf
754  );
755 
756  if (vtkWriter)
757  {
758  vtkWriter->beginPointData();
759  vtkWriter->write("curvature", tcurvature());
760  }
761  }
762 
763  Info<< endl;
764  }
765 
767 
768  Info<< "End\n" << endl;
769 
770  return 0;
771 }
772 
773 
774 // ************************************************************************* //
label patchId(-1)
ITstream & lookup(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return an entry data stream. FatalIOError if not found, or not a stream. ...
Definition: dictionary.C:367
dictionary dict
static void noFunctionObjects(bool addWithOption=false)
Remove &#39;-noFunctionObjects&#39; option and ignore any occurrences.
Definition: argList.C:547
static void addNote(const string &note)
Add extra notes for the usage information.
Definition: argList.C:462
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:116
fileName constantPath() const
Return constant path.
Definition: TimePathsI.H:146
A class for handling file names.
Definition: fileName.H:72
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
static tmp< scalarField > writeCurvature(const Time &runTime, const word &basename, const triSurface &surf)
Write surface curvature at the vertex points and return the field.
virtual Ostream & write(const char c) override
Write character.
Definition: OBJstream.C:69
void writeStats(Ostream &os) const
Write some statistics.
Definition: triSurfaceIO.C:348
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:129
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:598
virtual const fileName & name() const override
Read/write access to the name of the stream.
Definition: OSstream.H:128
const word & name() const noexcept
Return the object name.
Definition: IOobjectI.H:195
Unit conversion functions.
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
Basic surface-surface intersection description. Constructed from two surfaces it creates a descriptio...
Description of feature edges and points.
bool empty() const noexcept
True if List is empty (ie, size() is zero)
Definition: UList.H:666
Write faces/points (optionally with fields) as a vtp file or a legacy vtk file.
const word dictName("faMeshDefinition")
engineTime & runTime
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
A simple wrapper around bool so that it can be read as a word: true/false, on/off, yes/no, any/none. Also accepts 0/1 as a string and shortcuts t/f, y/n.
Definition: Switch.H:77
fileName relativePath(const fileName &input, const bool caseTag=false) const
Return the input relative to the globalPath by stripping off a leading value of the globalPath...
Definition: TimePathsI.H:103
static void noParallel()
Remove the parallel options.
Definition: argList.C:584
Ignore writing from objectRegistry::writeObject()
Geometric class that creates a 3D plane and can return the intersection point between a line and the ...
Definition: plane.H:90
T get(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a T. FatalIOError if not found, or if the number of tokens is incorrect.
void write(const word &fieldName, const UList< Type > &field)
Write primitive field of CellData (Poly or Line) or PointData values.
void add(const extendedEdgeMesh &fem)
Add extendedEdgeMesh. No filtering of duplicates.
EnumType getOrDefault(const word &key, const dictionary &dict, const EnumType deflt, const bool warnOnly=false) const
Find the key in the dictionary and return the corresponding enumeration element based on its name...
Definition: Enum.C:173
"offset" = Offset regions per file
bool found(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find an entry (const access) with the given keyword.
Definition: dictionaryI.H:104
IOdictionary is derived from dictionary and IOobject to give the dictionary automatic IO functionalit...
Definition: IOdictionary.H:50
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
void reset(T *p=nullptr) noexcept
Delete managed object and set to new given pointer.
Definition: autoPtrI.H:37
Helper class to search on triSurface.
virtual bool beginPointData(label nFields=0)
Begin PointData for specified number of fields.
const geometricSurfacePatchList & patches() const noexcept
Definition: triSurface.H:509
word outputName("finiteArea-edges.obj")
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
void setSize(const label n)
Alias for resize()
Definition: List.H:316
bool mkDir(const fileName &pathName, mode_t mode=0777)
Make a directory and return an error if it could not be created.
Definition: POSIX.C:614
bool has_ext() const
Various checks for extensions.
Definition: stringI.H:43
A class for handling words, derived from Foam::string.
Definition: word.H:63
const Time & time() const noexcept
Return time registry.
Self-intersection, region-wise only.
wordList patchNames(nPatches)
word lessExt() const
Return word without extension (part before last .)
Definition: wordI.H:192
A List of wordRe with additional matching capabilities.
Definition: wordRes.H:53
static void addOption(const word &optName, const string &param="", const string &usage="", bool advanced=false)
Add an option to validOptions with usage information.
Definition: argList.C:385
const Field< point_type > & points() const noexcept
Return reference to global points.
static Pair< tmp< scalarField > > writeCloseness(const Time &runTime, const word &basename, const triSurface &surf, const scalar internalAngleTolerance=45, const scalar externalAngleTolerance=10)
Check and write internal/external closeness fields.
virtual bool beginCellData(label nFields=0)
Begin CellData output section for specified number of fields.
static autoPtr< method > New(const dictionary &dict)
Select constructed from dictionary.
An OFstream that keeps track of vertices and provides convenience output methods for OBJ files...
Definition: OBJstream.H:55
const word & constant() const noexcept
Return constant name.
Definition: TimePathsI.H:112
bool readIfPresent(const word &keyword, T &val, enum keyType::option matchOpt=keyType::REGEX) const
Find an entry if present, and assign to T val. FatalIOError if it is found and the number of tokens i...
OBJstream os(runTime.globalPath()/outputName)
Ostream & printExecutionTime(OSstream &os) const
Print the elapsed ExecutionTime (cpu-time), ClockTime.
Definition: TimeIO.C:604
"file" = One region for each file
Nothing to be read.
loadingOption
The file loading options for triSurfaceLoader.
Standard boundBox with extra functionality for use in octree.
Definition: treeBoundBox.H:90
messageStream Info
Information stream (stdout output on master, null elsewhere)
intersectionType
Surface intersection types for classify, doCutEdges.
IOobject dictIO
None = invalid (for input only)
Pointer management similar to std::unique_ptr, with some additional methods and type checking...
Definition: HashPtrTable.H:48
void writeStats(Ostream &os, const extendedFeatureEdgeMesh &emesh)
Write some information.
Definition: edgeMeshTools.C:29
T getOrDefault(const word &keyword, const T &deflt, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a T, or return the given default value. FatalIOError if it is found and the number of...
virtual bool writeGeometry()
Write patch topology.
void writeVTK(OFstream &os, const Type &value)
A class for managing temporary objects.
Definition: HashPtrTable.H:50
const fileName & output() const noexcept
The current output file name.
Convenience class for loading single or multiple surface files from the constant/triSurface (or other...
Triangulated surface description with patch information.
Definition: triSurface.H:71
static const Enum< loadingOption > loadingOptionNames
The loading enumeration names.
Defines the attributes of an object for which implicit objectRegistry management is supported...
Definition: IOobject.H:172
Do not request registration (bool: false)
Holds feature edges/points of surface.
Namespace for OpenFOAM.
tmp< scalarField > writeFeatureProximity(const Time &runTime, const word &basename, const extendedEdgeMesh &emesh, const triSurface &surf, const scalar searchDistance)
Calculate proximity of the features to the surface and write the field.
A keyword and a list of tokens is an &#39;entry&#39;.
Definition: entry.H:63
static const Enum< intersectionType > selfIntersectionNames
The user-selectable self-intersection enumeration names.
FlatOutput::OutputAdaptor< Container, Delimiters > flatOutput(const Container &obj, Delimiters delim)
Global flatOutput() function with specified output delimiters.
Definition: FlatOutput.H:225
const dictionary * findDict(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a sub-dictionary pointer if present (and a sub-dictionary) otherwise return nullptr...
Definition: dictionaryI.H:124