mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
Enhance edgeMesh to support more formats.
Read only support:
.bdf, .nas - NASTRAN format. Handles both CBEAM and CROD as lines.
CROD is what Hypermesh happens to output.
Write only support:
.vtk - VTK legacy format in ASCII
Read/write support:
.eMesh - native format, which is simply a list of points, edges
with an additional IOobject header that lets them be moved about
easily to use as a featureEdgeMesh.
.inp - STAR-CD inp/cel/vrt combination
IOobject header)
.obj - Alias waverfront format
Radically simplify surfaceFeatureConvert by using the new edgeMesh
functionality.
This commit is contained in:
@ -21,7 +21,7 @@ surfaceFind
|
||||
- Finds nearest vertex and face to given point.
|
||||
|
||||
surfaceMeshTriangulate
|
||||
- Triangulate external facses of mesh and write as surface.
|
||||
- Triangulate external faces of mesh and write as surface.
|
||||
|
||||
surfacePointMerge
|
||||
- Explicit point merge of surface.
|
||||
|
||||
@ -26,266 +26,85 @@ Application
|
||||
surfaceFeatureConvert
|
||||
|
||||
Description
|
||||
Extracts and writes surface features to file
|
||||
Convert between edgeMesh formats
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "featureEdgeMesh.H"
|
||||
#include "argList.H"
|
||||
#include "Time.H"
|
||||
#include "IFstream.H"
|
||||
#include "IStringStream.H"
|
||||
#include "OFstream.H"
|
||||
#include "Map.H"
|
||||
|
||||
#include "edgeMesh.H"
|
||||
|
||||
using namespace Foam;
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
void readNASEdges
|
||||
(
|
||||
const fileName& inFileName,
|
||||
pointField& allPoints,
|
||||
edgeList& allEdges
|
||||
)
|
||||
{
|
||||
IFstream is(inFileName);
|
||||
|
||||
if (!is.good())
|
||||
{
|
||||
FatalErrorIn("readNASEdges")
|
||||
<< "Cannot read file " << inFileName
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
// coordinates of point
|
||||
DynamicList<point> points;
|
||||
// Nastran index of point
|
||||
DynamicList<label> pointIndices;
|
||||
|
||||
// beams
|
||||
DynamicList<edge> edges;
|
||||
DynamicList<label> edgeIndices;
|
||||
|
||||
|
||||
while (is.good())
|
||||
{
|
||||
string line;
|
||||
is.getLine(line);
|
||||
|
||||
if (line.empty() || line[0] == '$')
|
||||
{
|
||||
// Skip empty and comment
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if character 72 is continuation
|
||||
if (line.size() > 72 && line[72] == '+')
|
||||
{
|
||||
line = line.substr(0, 72);
|
||||
|
||||
while (true)
|
||||
{
|
||||
string buf;
|
||||
is.getLine(buf);
|
||||
|
||||
if (buf.size() > 72 && buf[72] == '+')
|
||||
{
|
||||
line += buf.substr(8, 64);
|
||||
}
|
||||
else
|
||||
{
|
||||
line += buf.substr(8, buf.size()-8);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Read first word
|
||||
IStringStream lineStream(line);
|
||||
word cmd;
|
||||
lineStream >> cmd;
|
||||
|
||||
if (cmd == "GRID")
|
||||
{
|
||||
label index;
|
||||
lineStream >> index;
|
||||
pointIndices.append(index);
|
||||
|
||||
scalar x = readScalar(IStringStream(line.substr(24, 8))());
|
||||
scalar y = readScalar(IStringStream(line.substr(32, 8))());
|
||||
scalar z = readScalar(IStringStream(line.substr(40, 8))());
|
||||
points.append(point(x, y, z));
|
||||
}
|
||||
else if (cmd == "CBEAM")
|
||||
{
|
||||
// Read shell type since gives patchnames.
|
||||
label index, group, v0, v1;
|
||||
lineStream >> index >> group >> v0 >> v1;
|
||||
|
||||
edgeIndices.append(index);
|
||||
edges.append(edge(v0, v1));
|
||||
}
|
||||
}
|
||||
|
||||
points.shrink();
|
||||
pointIndices.shrink();
|
||||
edges.shrink();
|
||||
edgeIndices.shrink();
|
||||
|
||||
Pout<< "Read from " << inFileName
|
||||
<< " edges:" << edges.size() << " points:" << points.size()
|
||||
<< endl;
|
||||
|
||||
{
|
||||
// Build inverse mapping (index to point)
|
||||
Map<label> indexToPoint(2*pointIndices.size());
|
||||
forAll(pointIndices, i)
|
||||
{
|
||||
indexToPoint.insert(pointIndices[i], i);
|
||||
}
|
||||
|
||||
// Relabel edges
|
||||
forAll(edges, i)
|
||||
{
|
||||
edge& e = edges[i];
|
||||
e[0] = indexToPoint[e[0]];
|
||||
e[1] = indexToPoint[e[1]];
|
||||
}
|
||||
}
|
||||
|
||||
allPoints.transfer(points);
|
||||
allEdges.transfer(edges);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void write
|
||||
(
|
||||
const Time& runTime,
|
||||
const fileName& inFileName,
|
||||
const fileName& outFileName,
|
||||
const edgeMesh& eMesh
|
||||
)
|
||||
{
|
||||
if (outFileName.ext() == "eMesh")
|
||||
{
|
||||
featureEdgeMesh fem
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
outFileName, // name
|
||||
runTime.constant(), // instance
|
||||
runTime, // registry
|
||||
IOobject::NO_READ,
|
||||
IOobject::AUTO_WRITE,
|
||||
false
|
||||
),
|
||||
eMesh.points(),
|
||||
eMesh.edges()
|
||||
);
|
||||
|
||||
Pout<< "Writing feature edge mesh to " << fem.objectPath()
|
||||
<< endl;
|
||||
|
||||
fem.write();
|
||||
}
|
||||
else if (outFileName.ext() == "vtk")
|
||||
{
|
||||
OFstream str(outFileName);
|
||||
|
||||
str << "# vtk DataFile Version 2.0" << nl
|
||||
<< "featureEdgeMesh " << inFileName << nl
|
||||
<< "ASCII" << nl
|
||||
<< "DATASET POLYDATA" << nl;
|
||||
|
||||
str << "POINTS " << eMesh.points().size() << " float" << nl;
|
||||
forAll(eMesh.points(), pointI)
|
||||
{
|
||||
const point& pt = eMesh.points()[pointI];
|
||||
|
||||
str << pt.x() << ' ' << pt.y() << ' ' << pt.z() << nl;
|
||||
}
|
||||
|
||||
str << "LINES " << eMesh.edges().size() << ' '
|
||||
<< 3*eMesh.edges().size() << nl;
|
||||
forAll(eMesh.edges(), edgeI)
|
||||
{
|
||||
const edge& e = eMesh.edges()[edgeI];
|
||||
|
||||
str << "2 " << e[0] << ' ' << e[1] << nl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FatalErrorIn("write")
|
||||
<< "Supported output formats: .eMesh, .vtk"
|
||||
<< exit(FatalError);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Main program:
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
argList::addNote
|
||||
(
|
||||
"Convert between edgeMesh formats"
|
||||
);
|
||||
argList::noParallel();
|
||||
argList::validArgs.append("input file");
|
||||
argList::validArgs.append("output file");
|
||||
# include "setRootCase.H"
|
||||
# include "createTime.H"
|
||||
argList::validArgs.append("inputFile");
|
||||
argList::validArgs.append("outputFile");
|
||||
argList::addOption
|
||||
(
|
||||
"scale",
|
||||
"factor",
|
||||
"specify a scaling factor for the points"
|
||||
);
|
||||
|
||||
const fileName inFileName(args.additionalArgs()[0]);
|
||||
const word outFileName(args.additionalArgs()[1]);
|
||||
argList args(argc, argv);
|
||||
Time runTime(args.rootPath(), args.caseName());
|
||||
const stringList& params = args.additionalArgs();
|
||||
|
||||
Pout<< "Input features file : " << inFileName << nl
|
||||
<< "Output features file : " << outFileName << nl
|
||||
<< endl;
|
||||
const fileName importName(params[0]);
|
||||
const fileName exportName(params[1]);
|
||||
|
||||
|
||||
// Read
|
||||
// ~~~~
|
||||
|
||||
if (inFileName.ext() == "nas")
|
||||
{
|
||||
pointField points;
|
||||
edgeList edges;
|
||||
readNASEdges(inFileName, points, edges);
|
||||
|
||||
edgeMesh eMesh(points, edges);
|
||||
|
||||
write(runTime, inFileName, outFileName, eMesh);
|
||||
}
|
||||
else if (inFileName.ext() == "eMesh")
|
||||
{
|
||||
featureEdgeMesh fem
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
inFileName, // name
|
||||
runTime.constant(), // instance
|
||||
runTime, // registry
|
||||
IOobject::MUST_READ,
|
||||
IOobject::AUTO_WRITE,
|
||||
false
|
||||
)
|
||||
);
|
||||
|
||||
Pout<< "Read from " << inFileName
|
||||
<< " edges:" << fem.edges().size()
|
||||
<< " points:" << fem.points().size()
|
||||
<< endl;
|
||||
|
||||
write(runTime, inFileName, outFileName, fem);
|
||||
}
|
||||
else
|
||||
// disable inplace editing
|
||||
if (importName == exportName)
|
||||
{
|
||||
FatalErrorIn(args.executable())
|
||||
<< "Can only handle NASTRAN data formats (.nas extension)."
|
||||
<< "Output file " << exportName << " would overwrite input file."
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
Pout<< "End\n" << endl;
|
||||
// check that reading/writing is supported
|
||||
if
|
||||
(
|
||||
!edgeMesh::canReadType(importName.ext(), true)
|
||||
|| !edgeMesh::canWriteType(exportName.ext(), true)
|
||||
)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
edgeMesh mesh(importName);
|
||||
|
||||
Info<< "\nRead edgeMesh " << importName << nl;
|
||||
mesh.writeStats(Info);
|
||||
Info<< nl
|
||||
<< "\nwriting " << exportName;
|
||||
|
||||
scalar scaleFactor = 0;
|
||||
if (args.optionReadIfPresent("scale", scaleFactor) && scaleFactor > 0)
|
||||
{
|
||||
Info<< " with scaling " << scaleFactor << endl;
|
||||
mesh.scalePoints(scaleFactor);
|
||||
}
|
||||
else
|
||||
{
|
||||
Info<< " without scaling" << endl;
|
||||
}
|
||||
|
||||
mesh.write(exportName);
|
||||
mesh.writeStats(Info);
|
||||
Info<< endl;
|
||||
|
||||
Info<< "\nEnd\n" << endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user