/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2018-2024 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see .
Description
Identifies features in a surface geometry and writes them to file,
based on control parameters specified by the user.
\*---------------------------------------------------------------------------*/
#include "argList.H"
#include "Time.H"
#include "triSurfaceMesh.H"
#include "featureEdgeMesh.H"
#include "extendedFeatureEdgeMesh.H"
#include "surfaceFeatures.H"
#include "triSurfaceFields.H"
#include "vtkWritePolyData.H"
#include "systemDict.H"
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
autoPtr extractFromFile
(
const fileName& featureEdgeFile,
const triSurface& surf,
const Switch& geometricTestOnly
)
{
edgeMesh eMesh(featureEdgeFile);
// Sometimes duplicate edges are present. Remove them.
eMesh.mergeEdges();
Info<< nl << "Reading existing feature edges from file "
<< featureEdgeFile << nl
<< "Selecting edges purely based on geometric tests: "
<< geometricTestOnly.asText() << endl;
return autoPtr
(
new surfaceFeatures
(
surf,
eMesh.points(),
eMesh.edges(),
1e-6,
geometricTestOnly
)
);
}
autoPtr extractFromSurface
(
const triSurface& surf,
const Switch& geometricTestOnly,
const scalar includedAngle
)
{
Info<< nl
<< "Constructing feature set from included angle "
<< includedAngle << nl
<< "Selecting edges purely based on geometric tests: "
<< geometricTestOnly.asText() << endl;
return autoPtr
(
new surfaceFeatures
(
surf,
includedAngle,
0,
0,
geometricTestOnly
)
);
}
autoPtr surfaceFeatureSet
(
const fileName& surfaceFileName,
const triSurface& surf,
const dictionary& dict,
const scalar includedAngle
)
{
const Switch geometricTestOnly = dict.lookupOrDefault
(
"geometricTestOnly",
"no"
);
if (dict.found("files"))
{
HashTable fileNames(dict.lookup("files"));
if (fileNames.found(surfaceFileName))
{
return extractFromFile
(
fileNames[surfaceFileName],
surf,
geometricTestOnly
);
}
else
{
return extractFromSurface
(
surf,
geometricTestOnly,
includedAngle
);
}
}
else
{
return extractFromSurface
(
surf,
geometricTestOnly,
includedAngle
);
}
}
void extractFeatures
(
const fileName& surfaceFileName,
const Time& runTime,
const dictionary& dict
)
{
const fileName sFeatFileName = surfaceFileName.lessExt().name();
Info<< "Surface : " << surfaceFileName << nl << endl;
const Switch writeVTK =
dict.lookupOrDefault("writeVTK", "off");
const Switch writeObj =
dict.lookupOrDefault("writeObj", "off");
const Switch verboseObj =
dict.lookupOrDefault("verboseObj", "off");
const Switch curvature =
dict.lookupOrDefault("curvature", "off");
const Switch featureProximity =
dict.lookupOrDefault("featureProximity", "off");
Info<< nl << "Feature line extraction is only valid on closed manifold "
<< "surfaces." << endl;
// Read
// ~~~~
triSurface surf
(
runTime.path()
/runTime.constant()
/searchableSurface::geometryDir(runTime)
/surfaceFileName
);
Info<< "Statistics:" << endl;
surf.writeStats(Info);
Info<< endl;
const faceList faces(surf.faces());
// Either construct features from surface & featureAngle or read set.
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
const scalar includedAngle =
dict.lookup("includedAngle", unitDegrees);
autoPtr set
(
surfaceFeatureSet
(
surfaceFileName,
surf,
dict,
includedAngle
)
);
// Trim set
// ~~~~~~~~
if (dict.isDict("trimFeatures"))
{
dictionary trimDict = dict.subDict("trimFeatures");
scalar minLen =
trimDict.lookupOrAddDefault("minLen", -great);
label minElem = trimDict.lookupOrAddDefault