48 os <<
" points : " << fem.
points().
size() << nl
58 <<
" edges : " << fem.
edges().
size() << nl
60 <<
" external edges : " 62 <<
" internal edges : " 68 <<
" multiply connected : " 75 int main(
int argc,
char *argv[])
79 "extract and write surface features to file" 102 const dictionary& surfaceDict = iter().dict();
104 if (!surfaceDict.
found(
"extractionMethod"))
109 const word extractionMethod = surfaceDict.
lookup(
"extractionMethod");
111 const fileName surfFileName = iter().keyword();
114 Info<<
"Surface : " << surfFileName << nl <<
endl;
123 const Switch featureProximity =
129 Info<< nl <<
"Feature line extraction is only valid on closed manifold " 130 <<
"surfaces." <<
endl;
138 surf.writeStats(
Info);
146 autoPtr<surfaceFeatures>
set;
148 scalar includedAngle = 0.0;
150 if (extractionMethod ==
"extractFromFile")
153 surfaceDict.
subDict(
"extractFromFileCoeffs");
156 extractFromFileDict.
lookup(
"featureEdgeFile");
158 const Switch geometricTestOnly =
170 Info<< nl <<
"Reading existing feature edges from file " 171 << featureEdgeFile << nl
172 <<
"Selecting edges purely based on geometric tests: " 187 else if (extractionMethod ==
"extractFromSurface")
190 surfaceDict.
subDict(
"extractFromSurfaceCoeffs");
195 const Switch geometricTestOnly =
203 <<
"Constructing feature set from included angle " 204 << includedAngle << nl
205 <<
"Selecting edges purely based on geometric tests: " 206 << geometricTestOnly.asText() <<
endl;
223 <<
"No initial feature set. Provide either one" 224 <<
" of extractFromFile (to read existing set)" << nl
225 <<
" or extractFromSurface (to construct new set from angle)" 233 if (surfaceDict.
isDict(
"trimFeatures"))
243 if (minElem > 0 || minLen > 0)
245 Info<<
"Removing features of length < " 247 Info<<
"Removing features with number of edges < " 250 set().trimFeatures(minLen, minElem, includedAngle);
261 if (surfaceDict.
isDict(
"subsetFeatures"))
268 if (subsetDict.
found(
"insideBox"))
272 Info<<
"Selecting edges inside bb " << bb
273 <<
" see insideBox.obj" <<
endl;
274 bb.writeOBJ(
"insideBox.obj");
277 else if (subsetDict.
found(
"outsideBox"))
281 Info<<
"Removing all edges inside bb " << bb
282 <<
" see outsideBox.obj" <<
endl;
283 bb.writeOBJ(
"outsideBox.obj");
287 const Switch nonManifoldEdges =
290 if (!nonManifoldEdges)
292 Info<<
"Removing all non-manifold edges" 293 <<
" (edges with > 2 connected faces) unless they" 294 <<
" cross multiple regions" <<
endl;
304 Info<<
"Removing all open edges" 305 <<
" (edges with 1 connected face)" <<
endl;
309 if (surf.edgeFaces()[edgei].size() == 1)
316 if (subsetDict.
found(
"plane"))
318 const plane cutPlane(subsetDict.
lookup(
"plane")());
322 Info<<
"Only edges that intersect the plane with normal " 324 <<
" and base point " << cutPlane.refPoint()
325 <<
" will be included as feature edges."<<
endl;
331 newSet.setFromStatus(edgeStat, includedAngle);
334 <<
"Initial feature set:" << nl
335 <<
" feature points : " << newSet.featurePoints().size() << nl
336 <<
" feature edges : " << newSet.featureEdges().size() << nl
338 <<
" region edges : " << newSet.nRegionEdges() << nl
339 <<
" external edges : " << newSet.nExternalEdges() << nl
340 <<
" internal edges : " << newSet.nInternalEdges() << nl
343 boolList surfBaffleRegions(surf.patches().size(),
false);
348 forAll(surf.patches(), pI)
350 const word& name = surf.patches()[pI].name();
352 if (
findIndex(surfBaffleNames, name) != -1)
354 Info<<
"Adding baffle region " << name <<
endl;
355 surfBaffleRegions[pI] =
true;
364 sFeatFileName +
".extendedFeatureEdgeMesh",
369 if (surfaceDict.
isDict(
"addFeatures"))
371 const word addFeName = surfaceDict.
subDict(
"addFeatures")[
"name"];
372 Info<<
"Adding (without merging) features from " << addFeName
381 "extendedFeatureEdgeMesh",
387 Info<<
"Read " << addFeMesh.name() <<
nl;
388 writeStats(addFeMesh,
Info);
390 feMesh.add(addFeMesh);
395 <<
"Final feature set:" <<
nl;
396 writeStats(feMesh,
Info);
398 Info<< nl <<
"Writing extendedFeatureEdgeMesh to " 399 << feMesh.objectPath() <<
endl;
401 mkDir(feMesh.path());
405 feMesh.writeObj(feMesh.path()/surfFileName.
lessExt().
name());
427 Info<< nl <<
"Writing featureEdgeMesh to " 428 << bfeMesh.objectPath() <<
endl;
430 bfeMesh.regIOobject::write();
436 Info<< nl <<
"Extracting internal and external closeness of " 437 <<
"surface." <<
endl;
444 sFeatFileName +
".closeness",
455 searchSurf.extractCloseness()
458 closenessFields.
first()->write();
459 closenessFields.second()->write();
463 const faceList faces(searchSurf.faces());
468 searchSurf.objectRegistry::name(),
472 closenessFields.first(),
480 searchSurf.objectRegistry::name(),
484 closenessFields.second(),
494 searchSurf.extractPointCloseness()
497 closenessFields.
first()->write();
498 closenessFields.second()->write();
502 const faceList faces(searchSurf.faces());
503 const Map<label>& meshPointMap = searchSurf.meshPointMap();
506 internalClosenessPointField = closenessFields.
first();
509 externalClosenessPointField = closenessFields.second();
511 scalarField internalCloseness(searchSurf.nPoints(), great);
512 scalarField externalCloseness(searchSurf.nPoints(), great);
516 internalCloseness[
pi] =
517 internalClosenessPointField[meshPointMap[
pi]];
519 externalCloseness[
pi] =
520 externalClosenessPointField[meshPointMap[
pi]];
526 searchSurf.objectRegistry::name(),
529 "internalPointCloseness",
538 searchSurf.objectRegistry::name(),
541 "externalPointCloseness",
553 Info<< nl <<
"Extracting curvature of surface at the points." 560 sFeatFileName +
".curvature",
589 if (featureProximity)
591 Info<< nl <<
"Extracting proximity of close feature points and " 592 <<
"edges to the surface" <<
endl;
594 const scalar searchDistance =
597 scalarField featureProximity(surf.size(), searchDistance);
601 const triPointRef& tri = surf[fi].tri(surf.points());
604 const scalar radiusSqr =
min 612 feMesh.allNearestFeatureEdges(triCentre, radiusSqr, hitList);
613 featureProximity[fi] =
min 615 feMesh.minDisconnectedDist(hitList),
619 feMesh.allNearestFeaturePoints(triCentre, radiusSqr, hitList);
620 featureProximity[fi] =
min 631 sFeatFileName +
".featureProximity",
643 featureProximityField.write();
label nonFeatureStart() const
Return the index of the start of the non-feature points.
bool found(const word &, bool recursive=false, bool patternMatch=true) const
Search dictionary for given keyword.
#define forAll(list, i)
Loop across all elements in list.
A triangle primitive used to calculate face areas and swept volumes.
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
A class for handling file names.
errorManipArg< error, int > exit(error &err, const int errNo=1)
A list of keyword definitions, which are a keyword followed by any number of values (e...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
void selectCutEdges(const triSurface &surf, const plane &cutPlane, List< surfaceFeatures::edgeStatus > &edgeStat)
Select edges that are intersected by the given plane.
T lookupOrAddDefault(const word &, const T &, bool recursive=false, bool patternMatch=true)
Find and return a T, if not found return the given.
dimensionedSymmTensor sqr(const dimensionedVector &dv)
void size(const label)
Override size to be inconsistent with allocated storage.
label multipleStart() const
Return the index of the start of the multiply-connected feature.
Ostream & endl(Ostream &os)
Add newline and flush stream.
A simple wrapper around bool so that it can be read as a word: true/false, on/off, yes/no, y/n, t/f, or none/any.
static void noParallel()
Remove the parallel options.
label openStart() const
Return the index of the start of the open feature edges.
void selectBox(const triSurface &surf, const boundBox &bb, const bool removeInside, List< surfaceFeatures::edgeStatus > &edgeStat)
Select edges inside or outside bounding box.
label k
Boltzmann constant.
Geometric class that creates a 2D plane and can return the intersection point between a line and the ...
fileName constantPath() const
Return constant path.
T & first()
Return the first element of the list.
scalar minDist(const List< pointIndexHit > &hitList)
bool isDict(const word &) const
Check if entry is a sub-dictionary.
IOdictionary is derived from dictionary and IOobject to give the dictionary automatic IO functionalit...
const dictionary & subDict(const word &) const
Find and return a sub-dictionary.
IOoject and searching on triSurface.
void selectManifoldEdges(const triSurface &surf, const scalar tol, const scalar includedAngle, List< surfaceFeatures::edgeStatus > &edgeStat)
Select manifold edges.
An ordered pair of two objects of type <T> with first() and second() elements.
label flatStart() const
Return the index of the start of the flat feature edges.
label internalStart() const
Return the index of the start of the internal feature edges.
A class for handling words, derived from string.
const edgeList & edges() const
Return edges.
const word & constant() const
Return constant name.
word name() const
Return file name (part beyond last /)
bool readIfPresent(const word &, T &, bool recursive=false, bool patternMatch=true) const
Find an entry if present, and assign to T.
const word dictName("particleTrackDict")
bool readScalar(const char *buf, doubleScalar &s)
Read whole of buf as a scalar. Return true if successful.
scalar circumRadius() const
Return circum-radius.
forAllConstIter(PtrDictionary< phaseModel >, mixture.phases(), phase)
label mixedStart() const
Return the index of the start of the mixed type feature points.
An Ostream is an abstract base class for all output systems (streams, files, token lists...
virtual void write(const fileName &outputDir, const fileName &surfaceName, const pointField &points, const faceList &faces, const bool verbose=false) const
Write single surface geometry to file.
const pointField & points() const
Return points.
const Time & time() const
Return time.
Points connected by edges.
const char * asText() const
Return a text representation of the Switch.
label findIndex(const ListType &, typename ListType::const_reference, const label start=0)
Find first occurrence of given element and return index,.
dimensioned< Type > min(const dimensioned< Type > &, const dimensioned< Type > &)
bool mkDir(const fileName &, mode_t=0777)
Make a directory and return an error if it could not be created.
IOobject dictIO(dictName, runTime.constant(), mesh, IOobject::MUST_READ_IF_MODIFIED, IOobject::NO_WRITE)
Point circumCentre() const
Return circum-centre.
time_t elapsedClockTime() const
Returns wall-clock time from clock instantiation.
double elapsedCpuTime() const
Return CPU time (in seconds) from the start.
T lookupOrDefault(const word &, const T &, bool recursive=false, bool patternMatch=true) const
Find and return a T,.
A surfaceWriter for VTK legacy format.
const dimensionSet dimLength(0, 1, 0, 0, 0, 0, 0)
fileName lessExt() const
Return file name without extension (part before last .)
Standard boundBox + extra functionality for use in octree.
const doubleScalar e
Elementary charge.
static void addNote(const string &)
Add extra notes for the usage information.
Triangulated surface description with patch information.
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
const Type & first() const
Return first.
Holds feature edges/points of surface.
label concaveStart() const
Return the index of the start of the concave feature points.
ITstream & lookup(const word &, bool recursive=false, bool patternMatch=true) const
Find and return an entry data stream.