Commit d016db1b authored by Mark Olesen's avatar Mark Olesen
Browse files

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.
parent 46a455cc
......@@ -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);
// Main program:
if (!is.good())
int main(int argc, char *argv[])
{
argList::addNote
(
"Convert between edgeMesh formats"
);
argList::noParallel();
argList::validArgs.append("inputFile");
argList::validArgs.append("outputFile");
argList::addOption
(
"scale",
"factor",
"specify a scaling factor for the points"
);
argList args(argc, argv);
Time runTime(args.rootPath(), args.caseName());
const stringList& params = args.additionalArgs();
const fileName importName(params[0]);
const fileName exportName(params[1]);
// disable inplace editing
if (importName == exportName)
{
FatalErrorIn("readNASEdges")
<< "Cannot read file " << inFileName
FatalErrorIn(args.executable())
<< "Output file " << exportName << " would overwrite input file."
<< 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())
// check that reading/writing is supported
if
(
!edgeMesh::canReadType(importName.ext(), true)
|| !edgeMesh::canWriteType(exportName.ext(), true)
)
{
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));
}
return 1;
}
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]];
}
}
edgeMesh mesh(importName);
allPoints.transfer(points);
allEdges.transfer(edges);
}
Info<< "\nRead edgeMesh " << importName << nl;
mesh.writeStats(Info);
Info<< nl
<< "\nwriting " << exportName;
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")
scalar scaleFactor = 0;
if (args.optionReadIfPresent("scale", scaleFactor) && scaleFactor > 0)
{
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;
}
Info<< " with scaling " << scaleFactor << endl;
mesh.scalePoints(scaleFactor);
}
else
{
FatalErrorIn("write")
<< "Supported output formats: .eMesh, .vtk"
<< exit(FatalError);
Info<< " without scaling" << endl;
}
}
// Main program:
int main(int argc, char *argv[])
{
argList::noParallel();
argList::validArgs.append("input file");
argList::validArgs.append("output file");
# include "setRootCase.H"
# include "createTime.H"
const fileName inFileName(args.additionalArgs()[0]);
const word outFileName(args.additionalArgs()[1]);
Pout<< "Input features file : " << inFileName << nl
<< "Output features file : " << outFileName << nl
<< endl;
mesh.write(exportName);
mesh.writeStats(Info);
Info<< endl;
// 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
{
FatalErrorIn(args.executable())
<< "Can only handle NASTRAN data formats (.nas extension)."
<< exit(FatalError);
}
Pout<< "End\n" << endl;
Info<< "\nEnd\n" << endl;
return 0;
}
......
edgeMesh.C
edgeMeshIO.C
featureEdgeMesh.C
edgeMeshNew.C
edgeFormats = edgeFormats
$(edgeFormats)/edgeFormatsCore.C
$(edgeFormats)/emesh/EMESHedgeFormat.C
$(edgeFormats)/emesh/EMESHedgeFormatRunTime.C
$(edgeFormats)/nas/NASedgeFormat.C
$(edgeFormats)/nas/NASedgeFormatRunTime.C
$(edgeFormats)/obj/OBJedgeFormat.C
$(edgeFormats)/obj/OBJedgeFormatRunTime.C
$(edgeFormats)/starcd/STARCDedgeFormat.C
$(edgeFormats)/starcd/STARCDedgeFormatRunTime.C
$(edgeFormats)/vtk/VTKedgeFormat.C
$(edgeFormats)/vtk/VTKedgeFormatRunTime.C
featureEdgeMesh/featureEdgeMesh.C
LIB = $(FOAM_LIBBIN)/libedgeMesh
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2009-2009 OpenCFD Ltd.
\\/ 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 2 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, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
\*---------------------------------------------------------------------------*/
#include "edgeFormatsCore.H"
#include "Time.H"
#include "IFstream.H"
#include "OFstream.H"
#include "edgeMesh.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
Foam::word Foam::fileFormats::edgeFormatsCore::nativeExt("eMesh");
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
Foam::string Foam::fileFormats::edgeFormatsCore::getLineNoComment
(
IFstream& is
)
{
string line;
do
{
is.getLine(line);
}
while ((line.empty() || line[0] == '#') && is.good());
return line;
}
#if 0
Foam::fileName Foam::fileFormats::edgeFormatsCore::localMeshFileName
(
const word& meshName
)
{
const word name(meshName.size() ? meshName : surfaceRegistry::defaultName);
return fileName
(
surfaceRegistry::prefix/name/surfMesh::meshSubDir
/ name + "." + nativeExt
);
}
Foam::fileName Foam::fileFormats::edgeFormatsCore::findMeshInstance
(
const Time& t,
const word& meshName
)
{
fileName localName = localMeshFileName(meshName);
// Search back through the time directories list to find the time
// closest to and lower than current time
instantList ts = t.times();
label instanceI;
for (instanceI = ts.size()-1; instanceI >= 0; --instanceI)
{
if (ts[instanceI].value() <= t.timeOutputValue())
{
break;
}
}
// Noting that the current directory has already been searched
// for mesh data, start searching from the previously stored time directory
if (instanceI >= 0)
{
for (label i = instanceI; i >= 0; --i)
{
if (isFile(t.path()/ts[i].name()/localName))
{
return ts[i].name();
}
}
}
return "constant";
}
Foam::fileName Foam::fileFormats::edgeFormatsCore::findMeshFile
(
const Time& t,
const word& meshName
)
{
fileName localName = localMeshFileName(meshName);
// Search back through the time directories list to find the time
// closest to and lower than current time
instantList ts = t.times();
label instanceI;
for (instanceI = ts.size()-1; instanceI >= 0; --instanceI)
{
if (ts[instanceI].value() <= t.timeOutputValue())
{
break;
}
}
// Noting that the current directory has already been searched
// for mesh data, start searching from the previously stored time directory
if (instanceI >= 0)
{
for (label i = instanceI; i >= 0; --i)
{
fileName testName(t.path()/ts[i].name()/localName);
if (isFile(testName))
{
return testName;
}
}
}
// fallback to "constant"
return t.path()/"constant"/localName;
}
#endif
bool Foam::fileFormats::edgeFormatsCore::checkSupport
(
const wordHashSet& available,
const word& ext,
const bool verbose,
const word& functionName
)
{
if (available.found(ext))
{
return true;
}
else if (verbose)
{
wordList known = available.sortedToc();
Info<<"Unknown file extension for " << functionName
<< " : " << ext << nl
<<"Valid types: (";
// compact output:
forAll(known, i)
{
Info<<" " << known[i];
}
Info<<" )" << endl;
}
return false;
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::fileFormats::edgeFormatsCore::edgeFormatsCore()
{}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::fileFormats::edgeFormatsCore::~edgeFormatsCore()
{}
// ************************************************************************* //
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2009-2009 OpenCFD Ltd.
\\/ 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 2 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, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Class
Foam::fileFormats::edgeFormatsCore
Description
A collection of helper functions for reading/writing edge formats.
SourceFiles
edgeFormatsCore.C
\*---------------------------------------------------------------------------*/
#ifndef edgeFormatsCore_H
#define edgeFormatsCore_H
#include "Map.H"
#include "HashSet.H"
#include "labelList.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{