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."
217 argList::noParallel();
218 argList::noFunctionObjects();
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"))
270 surfaceFeaturesExtraction::method::New
278 surfaceIntersection::selfIntersectionNames.getOrDefault
280 "intersectionMethod",
282 surfaceIntersection::NONE
285 const Switch writeObj(
"writeObj", surfaceDict, Switch::OFF);
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;
326 triSurfaceLoader::loadingOptionNames.getOrDefault
331 selfIntersect == surfaceIntersection::SELF_REGION
332 ? triSurfaceLoader::FILE_REGION
333 : triSurfaceLoader::OFFSET_REGION
337 Info<<
"Load options : "
338 << triSurfaceLoader::loadingOptionNames[loadingOption] <<
nl
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];
385 if (surfaceDict.
isDict(
"trimFeatures"))
389 const scalar minLen =
391 const label minElem =
395 if (minLen > 0 || minElem > 0)
399 Info<<
"Removing features of length < "
404 Info<<
"Removing features with number of edges < "
408 features().trimFeatures
410 minLen, minElem, extractor().includedAngle()
422 if (surfaceDict.
isDict(
"subsetFeatures"))
430 if (subsetDict.
found(
"insideBox"))
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 "
448 else if (subsetDict.
found(
"outsideBox"))
452 Info<<
"Exclude edges outside box " << bb <<
endl;
453 features().excludeBox(edgeStat, bb);
458 Info<<
"Dumping bounding box " << bb
459 <<
" as lines to obj file "
469 Info<<
"Removing all non-manifold edges"
470 <<
" (edges with > 2 connected faces) unless they"
471 <<
" cross multiple regions" <<
endl;
473 features().checkFlatRegionEdge
477 extractor().includedAngle()
484 Info<<
"Removing all open edges"
485 <<
" (edges with 1 connected face)" <<
endl;
487 features().excludeOpen(edgeStat);
491 if (subsetDict.
found(
"plane"))
495 Info<<
"Only include feature edges that intersect the plane"
496 <<
" with normal " << cutPlane.normal()
497 <<
" and origin " << cutPlane.origin() <<
endl;
499 features().subsetPlane(edgeStat, cutPlane);
504 newSet.setFromStatus(edgeStat, extractor().includedAngle());
507 newSet.writeStats(Info);
510 if (surfaceDict.
found(
"baffles"))
522 for (
const label
patchId : indices)
524 surfBaffleRegions[
patchId] =
true;
529 Info<<
"Adding " << indices.size() <<
" baffle regions: (";
531 forAll(surfBaffleRegions, patchi)
533 if (surfBaffleRegions[patchi])
552 if (surfaceDict.
isDict(
"addFeatures"))
559 Info<<
"Adding (without merging) features from " << addFeName
568 "extendedFeatureEdgeMesh",
574 Info<<
"Read " << addFeMesh.name() <<
nl;
575 edgeMeshTools::writeStats(Info, addFeMesh);
577 feMesh.add(addFeMesh);
580 if (selfIntersect != surfaceIntersection::NONE)
588 intersect.mergePoints(10*SMALL);
592 intersect.cutPoints().size(),
593 intersect.cutEdges().size()
596 if (intersect.cutEdges().size())
600 intersect.cutPoints(),
606 sizeInfo[0] = addMesh.points().size();
607 sizeInfo[1] = addMesh.edges().size();
611 << surfaceIntersection::selfIntersectionNames[selfIntersect]
613 <<
" points : " << sizeInfo[0] <<
nl
614 <<
" edges : " << sizeInfo[1] <<
nl;
618 edgeMeshTools::writeStats(Info, feMesh);
620 Info<<
nl <<
"Writing extendedFeatureEdgeMesh to "
621 << feMesh.objectPath() <<
endl;
623 mkDir(feMesh.path());
645 IOobject::AUTO_WRITE,
652 Info<<
nl <<
"Writing featureEdgeMesh to "
653 << bfeMesh.objectPath() <<
endl;
655 bfeMesh.regIOobject::write();
661 const bool optCloseness =
664 const bool optProximity =
667 const bool optCurvature =
677 if (optCloseness || optProximity || optCurvature)
692 vtkWriter->writeGeometry();
694 Info<<
"Writing VTK to "
695 <<
runTime.relativePath(vtkWriter->output()) <<
nl;
708 triSurfaceTools::writeCloseness
719 vtkWriter->beginCellData();
720 vtkWriter->write(
"internalCloseness", tcloseness[0]());
721 vtkWriter->write(
"externalCloseness", tcloseness[1]());
728 const scalar maxProximity =
729 surfaceDict.
getOrDefault<scalar>(
"maxFeatureProximity", 1);
732 edgeMeshTools::writeFeatureProximity
743 vtkWriter->beginCellData();
744 vtkWriter->write(
"featureProximity", tproximity());
752 triSurfaceTools::writeCurvature
761 vtkWriter->beginPointData();
762 vtkWriter->write(
"curvature", tcurvature());
769 runTime.printExecutionTime(Info);
IOdictionary is derived from dictionary and IOobject to give the dictionary automatic IO functionalit...
Defines the attributes of an object for which implicit objectRegistry management is supported,...
void setSize(const label n)
Alias for resize()
OFstream that keeps track of vertices.
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.
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
bool empty() const noexcept
Deprecated(2020-07) True if the managed pointer is null.
void reset(autoPtr< T > &&other) 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
const dictionary & subDict(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a sub-dictionary.
T getOrDefault(const word &keyword, const T &deflt, enum keyType::option matchOpt=keyType::REGEX) const
ITstream & lookup(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
bool found(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Search for an entry (const access) with the given keyword.
bool readIfPresent(const word &keyword, T &val, enum keyType::option matchOpt=keyType::REGEX) const
bool isDict(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Check if entry is found and is a sub-dictionary.
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.
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...
loadingOption
The file loading options for triSurfaceLoader.
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")
void writeVTK(OFstream &os, const Type &value)
messageStream Info
Information stream (stdout output on master, null elsewhere)
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.
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.