openfoam/applications/utilities/mesh/generation/foamyMesh/foamyHexMeshSurfaceSimplify/foamyHexMeshSurfaceSimplify_non_octree.C
Mark Olesen b060378dca ENH: improve consistency of fileName handling windows/non-windows (#2057)
- wrap command-line retrieval of fileName with an implicit validate.

  Instead of this:
      fileName input(args[1]);
      fileName other(args["someopt"]);

  Now use this:
      auto input = args.get<fileName>(1);
      auto other = args.get<fileName>("someopt");

  which adds a fileName::validate on the inputs

  Because of how it is implemented, it will automatically also apply
  to argList getOrDefault<fileName>, readIfPresent<fileName> etc.

- adjust fileName::validate and clean to handle backslash conversion.
  This makes it easier to ensure that path names arising from MS-Windows
  are consistently handled internally.

- dictionarySearch: now check for initial '/' directly instead of
  relying on fileName isAbsolute(), which now does more things

BREAKING: remove fileName::clean() const method

- relying on const/non-const to control the behaviour (inplace change
  or return a copy) is too fragile and the const version was
  almost never used.

  Replace:
      fileName sanitized = constPath.clean();

  With:
      fileName sanitized(constPath);
      sanitized.clean());

STYLE: test empty() instead of comparing with fileName::null
2021-04-19 16:33:42 +00:00

358 lines
9.6 KiB
C

/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2012-2016 OpenFOAM Foundation
Copyright (C) 2020-2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
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 <http://www.gnu.org/licenses/>.
Application
foamyHexMeshSurfaceSimplify
Description
Simplifies surfaces by resampling.
Uses Thomas Lewiner's topology preserving MarchingCubes.
\*---------------------------------------------------------------------------*/
#include "argList.H"
#include "Time.H"
#include "searchableSurfaces.H"
#include "conformationSurfaces.H"
#include "triSurfaceMesh.H"
#include "labelVector.H"
#include "MarchingCubes.h"
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:
int main(int argc, char *argv[])
{
argList::addNote
(
"Re-sample surfaces used in foamyHexMesh operation"
);
argList::addArgument("(nx ny nz)", "The resampling interval");
argList::addArgument("output", "The output triSurface/ file");
argList::noFunctionObjects(); // Never use function objects
#include "setRootCase.H"
#include "createTime.H"
const auto n = args.get<labelVector>(1);
const auto exportName = args.get<fileName>(2);
Info<< "Reading surfaces as specified in the foamyHexMeshDict and"
<< " writing re-sampled " << n << " to " << exportName
<< nl << endl;
cpuTime timer;
IOdictionary foamyHexMeshDict
(
IOobject
(
"foamyHexMeshDict",
runTime.system(),
runTime,
IOobject::MUST_READ_IF_MODIFIED,
IOobject::NO_WRITE
)
);
// Define/load all geometry
searchableSurfaces allGeometry
(
IOobject
(
"cvSearchableSurfaces",
runTime.constant(),
"triSurface",
runTime,
IOobject::MUST_READ,
IOobject::NO_WRITE
),
foamyHexMeshDict.subDict("geometry"),
foamyHexMeshDict.getOrDefault("singleRegionName", true)
);
Info<< "Geometry read in = "
<< timer.cpuTimeIncrement() << " s." << nl << endl;
Random rndGen(64293*Pstream::myProcNo());
conformationSurfaces geometryToConformTo
(
runTime,
rndGen,
allGeometry,
foamyHexMeshDict.subDict("surfaceConformation")
);
Info<< "Set up geometry in = "
<< timer.cpuTimeIncrement() << " s." << nl << endl;
// Extend
treeBoundBox bb = geometryToConformTo.globalBounds();
{
const vector smallVec = 0.1*bb.span();
bb.min() -= smallVec;
bb.max() += smallVec;
}
Info<< "Meshing to bounding box " << bb << nl << endl;
const vector span(bb.span());
const vector d
(
span.x()/(n.x()-1),
span.y()/(n.y()-1),
span.z()/(n.z()-1)
);
MarchingCubes mc(span.x(), span.y(), span.z() ) ;
mc.set_resolution(n.x(), n.y(), n.z());
mc.init_all() ;
// Generate points
pointField points(mc.size_x()*mc.size_y()*mc.size_z());
label pointi = 0;
point pt;
for( int k = 0 ; k < mc.size_z() ; k++ )
{
pt.z() = bb.min().z() + k*d.z();
for( int j = 0 ; j < mc.size_y() ; j++ )
{
pt.y() = bb.min().y() + j*d.y();
for( int i = 0 ; i < mc.size_x() ; i++ )
{
pt.x() = bb.min().x() + i*d.x();
points[pointi++] = pt;
}
}
}
Info<< "Generated " << points.size() << " sampling points in = "
<< timer.cpuTimeIncrement() << " s." << nl << endl;
// Compute data
const searchableSurfaces& geometry = geometryToConformTo.geometry();
const labelList& surfaces = geometryToConformTo.surfaces();
scalarField signedDist;
labelList nearestSurfaces;
searchableSurfacesQueries::signedDistance
(
geometry,
surfaces,
points,
scalarField(points.size(), sqr(GREAT)),
searchableSurface::OUTSIDE, // for non-closed surfaces treat as
// outside
nearestSurfaces,
signedDist
);
// Fill elements
pointi = 0;
for( int k = 0 ; k < mc.size_z() ; k++ )
{
for( int j = 0 ; j < mc.size_y() ; j++ )
{
for( int i = 0 ; i < mc.size_x() ; i++ )
{
mc.set_data(float(signedDist[pointi++]), i, j, k);
}
}
}
Info<< "Determined signed distance in = "
<< timer.cpuTimeIncrement() << " s." << nl << endl;
mc.run() ;
Info<< "Constructed iso surface in = "
<< timer.cpuTimeIncrement() << " s." << nl << endl;
mc.clean_temps() ;
// Write output file
if (mc.ntrigs() > 0)
{
Triangle* triangles = mc.triangles();
List<labelledTri> tris(mc.ntrigs());
forAll(tris, triI)
{
tris[triI] = labelledTri
(
triangles[triI].v1,
triangles[triI].v2,
triangles[triI].v3,
0 // region
);
}
Vertex* vertices = mc.vertices();
pointField points(mc.nverts());
forAll(points, pointi)
{
Vertex& v = vertices[pointi];
points[pointi] = point
(
bb.min().x() + v.x*span.x()/mc.size_x(),
bb.min().y() + v.y*span.y()/mc.size_y(),
bb.min().z() + v.z*span.z()/mc.size_z()
);
}
// Find correspondence to original surfaces
labelList regionOffsets(surfaces.size());
label nRegions = 0;
forAll(surfaces, i)
{
const wordList& regions = geometry[surfaces[i]].regions();
regionOffsets[i] = nRegions;
nRegions += regions.size();
}
geometricSurfacePatchList patches(nRegions);
nRegions = 0;
forAll(surfaces, i)
{
const wordList& regions = geometry[surfaces[i]].regions();
forAll(regions, regionI)
{
patches[nRegions] = geometricSurfacePatch
(
geometry[surfaces[i]].name() + "_" + regions[regionI],
nRegions,
"patch"
);
nRegions++;
}
}
triSurface s(tris, patches, points, true);
Info<< "Extracted triSurface in = "
<< timer.cpuTimeIncrement() << " s." << nl << endl;
// Find out region on local surface of nearest point
{
List<pointIndexHit> hitInfo;
labelList hitSurfaces;
geometryToConformTo.findSurfaceNearest
(
s.faceCentres(),
scalarField(s.size(), sqr(GREAT)),
hitInfo,
hitSurfaces
);
// Get region
DynamicList<pointIndexHit> surfInfo(hitSurfaces.size());
DynamicList<label> surfIndices(hitSurfaces.size());
forAll(surfaces, surfI)
{
// Extract info on this surface
surfInfo.clear();
surfIndices.clear();
forAll(hitSurfaces, triI)
{
if (hitSurfaces[triI] == surfI)
{
surfInfo.append(hitInfo[triI]);
surfIndices.append(triI);
}
}
// Calculate sideness of these surface points
labelList region;
geometry[surfaces[surfI]].getRegion(surfInfo, region);
forAll(region, i)
{
label triI = surfIndices[i];
s[triI].region() = regionOffsets[surfI]+region[i];
}
}
}
Info<< "Re-patched surface in = "
<< timer.cpuTimeIncrement() << " s." << nl << endl;
triSurfaceMesh smesh
(
IOobject
(
exportName,
runTime.constant(), // instance
"triSurface",
runTime, // registry
IOobject::NO_READ,
IOobject::AUTO_WRITE,
false
),
s
);
Info<< "writing surfMesh:\n "
<< smesh.searchableSurface::objectPath() << nl << endl;
smesh.searchableSurface::write();
Info<< "Written surface in = "
<< timer.cpuTimeIncrement() << " s." << nl << endl;
}
mc.clean_all() ;
Info<< "End\n" << endl;
return 0;
}
// ************************************************************************* //