209int main(
int argc,
char *argv[])
213 "Extract and write surface feature lines to file.\n"
214 "Feature line extraction only valid on closed manifold surfaces."
224 "Read surfaceFeatureExtractDict from specified location"
232 <<
"Feature line extraction only valid on closed manifold surfaces"
249 if (!dEntry.isDict())
258 const dictionary& surfaceDict = dEntry.dict();
260 if (!surfaceDict.
found(
"extractionMethod"))
280 "intersectionMethod",
296 loader.select(surfaceDict.
get<
wordRes>(
"surfaces"));
306 if (loader.selected().empty())
309 <<
"No surfaces specified/found for entry: "
313 Info<<
"Surfaces : ";
314 if (loader.selected().size() == 1)
316 Info<< loader.selected().first() <<
nl;
337 Info<<
"Load options : "
340 <<
" writeObj=" << writeObj
343 scalar scaleFactor = -1;
345 if (surfaceDict.
readIfPresent(
"scale", scaleFactor) && scaleFactor > 0)
347 Info<<
"Scaling : " << scaleFactor <<
nl;
352 if (!surfPtr || surfPtr->empty())
355 <<
"Problem loading surface(s) for entry: "
362 <<
"Statistics:" <<
nl;
372 faces[fi] = surf[fi];
388 if ((subDictPtr = surfaceDict.
findDict(
"trimFeatures")) !=
nullptr)
392 const scalar minLen =
394 const label minElem =
398 if (minLen > 0 || minElem > 0)
402 Info<<
"Removing features of length < "
407 Info<<
"Removing features with number of edges < "
411 features().trimFeatures
413 minLen, minElem, extractor().includedAngle()
422 List<surfaceFeatures::edgeStatus> edgeStat(features().toStatus());
425 if ((subDictPtr = surfaceDict.
findDict(
"subsetFeatures")) !=
nullptr)
434 Info<<
"Subset edges inside box " << bb <<
endl;
435 features().subsetBox(edgeStat, bb);
440 Info<<
"Dumping bounding box " << bb
441 <<
" as lines to obj file "
450 Info<<
"Exclude edges outside box " << bb <<
endl;
451 features().excludeBox(edgeStat, bb);
456 Info<<
"Dumping bounding box " << bb
457 <<
" as lines to obj file "
467 Info<<
"Removing all non-manifold edges"
468 <<
" (edges with > 2 connected faces) unless they"
469 <<
" cross multiple regions" <<
endl;
471 features().checkFlatRegionEdge
475 extractor().includedAngle()
479 if (!subsetDict.
getOrDefault(
"strictNonManifoldEdges",
true))
481 Info<<
"Removing all non-manifold edges"
482 <<
" (edges with > 2 connected faces)"
485 features().excludeNonManifold(edgeStat);
491 Info<<
"Removing all open edges"
492 <<
" (edges with 1 connected face)" <<
endl;
494 features().excludeOpen(edgeStat);
498 if (subsetDict.
found(
"plane"))
502 Info<<
"Only include feature edges that intersect the plane"
503 <<
" with normal " << cutPlane.normal()
504 <<
" and origin " << cutPlane.origin() <<
endl;
506 features().subsetPlane(edgeStat, cutPlane);
511 newSet.setFromStatus(edgeStat, extractor().includedAngle());
514 newSet.writeStats(
Info);
517 if (surfaceDict.
found(
"baffles"))
529 for (
const label
patchId : indices)
531 surfBaffleRegions[
patchId] =
true;
536 Info<<
"Adding " << indices.size() <<
" baffle regions: (";
538 forAll(surfBaffleRegions, patchi)
540 if (surfBaffleRegions[patchi])
559 if ((subDictPtr = surfaceDict.
findDict(
"addFeatures")) !=
nullptr)
561 const dictionary& addFeaturesDict = *subDictPtr;
563 const word addFeName = addFeaturesDict.
get<
word>(
"name");
565 Info<<
"Adding (without merging) features from " << addFeName
574 "extendedFeatureEdgeMesh",
580 Info<<
"Read " << addFeMesh.name() <<
nl;
583 feMesh.add(addFeMesh);
594 intersect.mergePoints(10*SMALL);
598 intersect.cutPoints().size(),
599 intersect.cutEdges().size()
602 if (intersect.cutEdges().size())
606 intersect.cutPoints(),
612 sizeInfo[0] = addMesh.points().size();
613 sizeInfo[1] = addMesh.edges().size();
619 <<
" points : " << sizeInfo[0] <<
nl
620 <<
" edges : " << sizeInfo[1] <<
nl;
626 Info<<
nl <<
"Writing extendedFeatureEdgeMesh to "
627 << feMesh.objectPath() <<
endl;
629 mkDir(feMesh.path());
658 Info<<
nl <<
"Writing featureEdgeMesh to "
659 << bfeMesh.objectPath() <<
endl;
661 bfeMesh.regIOobject::write();
667 const bool optCloseness =
670 const bool optProximity =
673 const bool optCurvature =
683 if (optCloseness || optProximity || optCurvature)
698 vtkWriter->writeGeometry();
700 Info<<
"Writing VTK to "
701 <<
runTime.relativePath(vtkWriter->output()) <<
nl;
713 Pair<tmp<scalarField>> tcloseness =
725 vtkWriter->beginCellData();
726 vtkWriter->write(
"internalCloseness", tcloseness[0]());
727 vtkWriter->write(
"externalCloseness", tcloseness[1]());
734 const scalar maxProximity =
735 surfaceDict.
getOrDefault<scalar>(
"maxFeatureProximity", 1);
749 vtkWriter->beginCellData();
750 vtkWriter->write(
"featureProximity", tproximity());
767 vtkWriter->beginPointData();
768 vtkWriter->write(
"curvature", tcurvature());
IOdictionary is derived from dictionary and IOobject to give the dictionary automatic IO functionalit...
@ NO_REGISTER
Do not request registration (bool: false).
@ NO_READ
Nothing to be read.
@ MUST_READ
Reading required.
@ NO_WRITE
Ignore writing from objectRegistry::writeObject().
Defines the attributes of an object for which implicit objectRegistry management is supported,...
void setSize(label n)
Alias for resize().
An OFstream that keeps track of vertices and provides convenience output methods for OBJ files.
const Field< point_type > & points() const noexcept
Return reference to global points.
A simple wrapper around bool so that it can be read as a word: true/false, on/off,...
void size(const label n)
Older name for setAddressableSize.
static void noFunctionObjects(bool addWithOption=false)
Remove '-noFunctionObjects' option and ignore any occurrences.
static void noParallel()
Remove the parallel options.
static void addOption(const word &optName, const string ¶m="", const string &usage="", bool advanced=false)
Add an option to validOptions with usage information.
static void addNote(const string ¬e)
Add extra notes for the usage information.
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
void reset(T *p=nullptr) noexcept
Delete managed object and set to new given pointer.
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
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.
const dictionary * findDict(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a sub-dictionary pointer if present (and it is a dictionary) otherwise return nullptr...
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...
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.
bool found(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find an entry (const access) with the given keyword.
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...
A keyword and a list of tokens is an 'entry'.
Description of feature edges and points.
A class for handling file names.
Geometric class that creates a 3D plane and can return the intersection point between a line and the ...
Holds feature edges/points of surface.
Basic surface-surface intersection description. Constructed from two surfaces it creates a descriptio...
intersectionType
Surface intersection types for classify, doCutEdges.
@ SELF_REGION
Self-intersection, region-wise only.
@ NONE
None = invalid (for input only).
static const Enum< intersectionType > selfIntersectionNames
The user-selectable self-intersection enumeration names.
A class for managing temporary objects.
Standard boundBox with extra functionality for use in octree.
Convenience class for loading single or multiple surface files from the constant/triSurface (or other...
static const Enum< loadingOption > loadingOptionNames
The loading enumeration names.
loadingOption
The file loading options for triSurfaceLoader.
@ FILE_REGION
"file" = One region for each file
@ OFFSET_REGION
"offset" = Offset regions per file
Helper class to search on triSurface.
Triangulated surface description with patch information.
const geometricSurfacePatchList & patches() const noexcept
void writeStats(Ostream &os) const
Write some statistics.
Write faces/points (optionally with fields) as a vtp file or a legacy vtk file.
A List of wordRe with additional matching capabilities.
A class for handling words, derived from Foam::string.
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
word outputName("finiteArea-edges.obj")
OBJstream os(runTime.globalPath()/outputName)
const word dictName("faMeshDefinition")
Pair< label > labelPair
A pair of labels.
List< word > wordList
List of word.
List< label > labelList
A List of labels.
void writeVTK(OFstream &os, const Type &value)
messageStream Info
Information stream (stdout output on master, null elsewhere).
List< face > faceList
List of faces.
Ostream & endl(Ostream &os)
Add newline and flush stream.
FlatOutput::OutputAdaptor< Container, Delimiters > flatOutput(const Container &obj, Delimiters delim)
Global flatOutput() function with specified output delimiters.
List< bool > boolList
A List of bools.
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
errorManipArg< error, int > exit(error &err, const int errNo=1)
constexpr char nl
The newline '\n' character (0x0a).
wordList patchNames(nPatches)
#define forAll(list, i)
Loop across all elements in list.
Unit conversion functions.