checked in surfMesh library code

- keyedSurface is similar to triSurface, but uses faces
  - meshedSurface is sorted in regions and should be more memory efficient
  - surfMesh is the placeholder name for an OpenFOAM native surface format
This commit is contained in:
Mark Olesen
2008-10-23 16:29:36 +02:00
parent 0581aeda6f
commit 2bb928ec8f
42 changed files with 10157 additions and 16 deletions

View File

@ -1,40 +1,46 @@
09/01/04 2008-10-23
Contents: Contents:
surfaceAdd surfaceAdd
adds to surface files. (but does not intersect or anything) - adds to surface files. (but does not intersect or anything)
surfaceBooleanOp surfaceBooleanOp
Boolean operations (add, or, xor) on closed surfaces. Probably not working. - Boolean operations (add, or, xor) on closed surfaces. Probably not working.
surfaceCheck surfaceCheck
checks surface for incorrect topology. Checks normals of neighbouring faces. - checks surface for incorrect topology. Checks normals of neighbouring faces.
surfaceCoarsen surfaceCoarsen
Stan Melax coarsening algorithm - Stan Melax coarsening algorithm
surfaceConvert surfaceConvert
Converts surfaces to/from various formats - Converts surfaces to/from various formats
surfaceFind surfaceFind
Finds nearest vertex and face to given point. - Finds nearest vertex and face to given point.
surfaceMeshTriangulate surfaceMeshTriangulate
Triangulate external facses of mesh and write as surface. - Triangulate external facses of mesh and write as surface.
surfacePointMerge surfacePointMerge
Explicit point merge of surface. - Explicit point merge of surface.
surfaceSetOutside surfaceSetOutside
Orient normals on (closed) surface. - Orient normals on (closed) surface.
surfaceSmooth surfaceSmooth
Laplacian smoothing on surface vertices - Laplacian smoothing on surface vertices
surfaceSubset surfaceSubset
Subsets surface - Subsets surface
surfaceToPatch surfaceToPatch
Applies region information of surfaces to mesh. Each external face of mesh - Applies region information of surfaces to mesh.
gets region number of nearest surface triangle. Each external face of mesh gets region number of nearest surface triangle.
-------------------------------------------------------------------------------
surfaceMeshConvert
- Similar to surfaceConvert, but uses surfMesh library

View File

@ -0,0 +1,3 @@
surfaceMeshConvert.C
EXE = $(FOAM_APPBIN)/surfaceMeshConvert

View File

@ -0,0 +1,5 @@
EXE_INC = \
-I$(LIB_SRC)/triSurface/lnInclude \
-I$(LIB_SRC)/surfMesh/lnInclude
EXE_LIBS = -lsurfMesh

View File

@ -0,0 +1,145 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 1991-2008 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
Application
surfaceMeshConvert
Description
Converts from one surface mesh format to another
Usage
- surfaceMeshConvert inputFile outputFile [OPTION]
@param -clean \n
Perform some surface checking/cleanup on the input surface
@param -scale \<scale\> \n
Specify a scaling factor for writing the files
@param -triSurface \n
Use triSurface library for input/output
Note
The filename extensions are used to determine the file format type.
\*---------------------------------------------------------------------------*/
#include "argList.H"
#include "timeSelector.H"
#include "Time.H"
#include "polyMesh.H"
#include "meshedSurface.H"
#include "triSurface.H"
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:
int main(int argc, char *argv[])
{
argList::noParallel();
argList::validArgs.append("inputFile");
argList::validArgs.append("outputFile");
argList::validOptions.insert("scale", "scale");
argList::validOptions.insert("clean", "");
argList::validOptions.insert("triSurface", "");
# include "setRootCase.H"
const stringList& params = args.additionalArgs();
scalar scaleFactor = 0;
if (args.options().found("scale"))
{
IStringStream(args.options()["scale"])() >> scaleFactor;
}
fileName importName(params[0]);
fileName exportName(params[1]);
if
(
!meshedSurface::canRead(importName.ext(), true)
|| !meshedSurface::canWrite(exportName.ext(), true)
)
{
return 1;
}
if (args.options().found("triSurface"))
{
// # include "createTime.H"
// instantList timeDirs = timeSelector::select0(runTime, args);
// # include "createPolyMesh.H"
triSurface surf(importName);
if (args.options().found("clean"))
{
surf.cleanup(true);
surf.checkOrientation(true);
}
Info << "writing " << exportName;
if (scaleFactor <= 0)
{
Info<< " without scaling" << endl;
}
else
{
Info<< " triSurface does not yet support scaling "
<< scaleFactor << endl;
// surf.scalePoints(scaleFactor);
}
surf.write(exportName);
}
else
{
meshedSurface surf(importName);
if (args.options().found("clean"))
{
surf.cleanup(true);
surf.checkOrientation(true);
}
surf.scalePoints(scaleFactor);
Info<< "writing " << exportName;
if (scaleFactor <= 0)
{
Info<< " without scaling" << endl;
}
else
{
Info<< " with scaling " << scaleFactor << endl;
}
surf.write(exportName);
}
Info<< "\nEnd\n" << endl;
return 0;
}
// ************************************************************************* //

View File

@ -13,6 +13,7 @@ wmake libso lagrangian/basic
wmake libso triSurface wmake libso triSurface
wmake libso edgeMesh wmake libso edgeMesh
wmake libso surfMesh
wmake libso meshTools wmake libso meshTools
wmake libso finiteVolume wmake libso finiteVolume

View File

@ -39,6 +39,7 @@ SourceFiles
#define Keyed_H #define Keyed_H
#include "List.H" #include "List.H"
#include "xfer.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -48,6 +49,7 @@ namespace Foam
// Forward declaration of friend functions and operators // Forward declaration of friend functions and operators
template<class T> class Keyed; template<class T> class Keyed;
template<class T> class xfer;
template<class T> Istream& operator>>(Istream&, Keyed<T>&); template<class T> Istream& operator>>(Istream&, Keyed<T>&);
template<class T> Ostream& operator<<(Ostream&, const Keyed<T>&); template<class T> Ostream& operator<<(Ostream&, const Keyed<T>&);
@ -92,6 +94,9 @@ public:
//- Construct as a copy of item, with a key //- Construct as a copy of item, with a key
inline Keyed(const T& item, const label key=0); inline Keyed(const T& item, const label key=0);
//- Construct by transferring the item, with a key
inline Keyed(const xfer<T>& item, const label key=0);
//- Construct from Istream //- Construct from Istream
inline Keyed(Istream&); inline Keyed(Istream&);

View File

@ -30,7 +30,6 @@ License
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
//- Construct null
template<class T> template<class T>
inline Foam::Keyed<T>::Keyed() inline Foam::Keyed<T>::Keyed()
: :
@ -38,7 +37,6 @@ inline Foam::Keyed<T>::Keyed()
{} {}
//- Construct from components
template<class T> template<class T>
inline Foam::Keyed<T>::Keyed(const T& item, const label key) inline Foam::Keyed<T>::Keyed(const T& item, const label key)
: :
@ -47,6 +45,14 @@ inline Foam::Keyed<T>::Keyed(const T& item, const label key)
{} {}
template<class T>
inline Foam::Keyed<T>::Keyed(const xfer<T>& item, const label key)
:
T(item),
key_(key)
{}
template<class T> template<class T>
inline Foam::Keyed<T>::Keyed(Istream& is) inline Foam::Keyed<T>::Keyed(Istream& is)
{ {

23
src/surfMesh/Make/files Normal file
View File

@ -0,0 +1,23 @@
keyedSurface/keyedSurface.C
keyedSurface/keyedSurfaceCleanup.C
keyedSurface/newKeyedSurface.C
meshedSurface/meshedSurface.C
meshedSurface/meshedSurfaceCleanup.C
meshedSurface/newMeshedSurface.C
fileFormats = keyedSurface/fileFormats
$(fileFormats)/ac3d/AC3DfileFormat.C
$(fileFormats)/gts/GTSfileFormat.C
$(fileFormats)/nas/NASfileFormat.C
$(fileFormats)/obj/OBJfileFormat.C
$(fileFormats)/off/OFFfileFormat.C
$(fileFormats)/smesh/SMESHfileFormat.C
$(fileFormats)/starcd/STARCDfileFormat.C
$(fileFormats)/stl/STLfileFormat.C
$(fileFormats)/stl/STLfileFormatASCII.L
$(fileFormats)/tri/TRIfileFormat.C
$(fileFormats)/vtk/VTKfileFormat.C
LIB = $(FOAM_LIBBIN)/libsurfMesh

View File

@ -0,0 +1,5 @@
EXE_INC = \
-I$(LIB_SRC)/triSurface/lnInclude
LIB_LIBS = \
-ltriSurface

View File

@ -0,0 +1,588 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 1991-2008 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 "AC3DfileFormat.H"
#include "clock.H"
#include "IFstream.H"
#include "IStringStream.H"
#include "tensor.H"
#include "primitivePatch.H"
#include "addToRunTimeSelectionTable.H"
#include "addToMemberFunctionSelectionTable.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
namespace fileFormats
{
addNamedToRunTimeSelectionTable
(
keyedSurface,
AC3DfileFormat,
fileExtension,
ac
);
addNamedToMemberFunctionSelectionTable
(
keyedSurface,
AC3DfileFormat,
write,
fileExtension,
ac
);
addNamedToMemberFunctionSelectionTable
(
meshedSurface,
AC3DfileFormat,
write,
fileExtension,
ac
);
}
}
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
template<class Type>
Type Foam::fileFormats::AC3DfileFormat::parse(const string& str)
{
IStringStream ss(str);
Type t;
ss >> t;
return t;
}
bool Foam::fileFormats::AC3DfileFormat::readCmd
(
IFstream& is,
string& cmd,
string& args
)
{
if (is.good())
{
string line;
is.getLine(line);
string::size_type space = line.find(' ');
if (space != string::npos)
{
cmd = line.substr(0, space);
args = line.substr(space+1);
return true;
}
}
return false;
}
// Read up to line starting with cmd. Sets args to rest of line.
// Returns true if found, false if stream is not good anymore.
bool Foam::fileFormats::AC3DfileFormat::cueTo
(
IFstream& is,
const string& cmd,
string& args
)
{
while (is.good())
{
string line;
is.getLine(line);
string::size_type space = line.find(' ');
if (space != string::npos)
{
if (line.substr(0, space) == cmd)
{
args = line.substr(space+1);
return true;
}
}
}
return false;
}
// Similar to cueTo(), but throws error if cmd not found
Foam::string Foam::fileFormats::AC3DfileFormat::cueToOrDie
(
IFstream& is,
const string& cmd,
const string& errorMsg
)
{
string args;
if (!cueTo(is, cmd, args))
{
FatalErrorIn
(
"fileFormats::AC3DfileFormat::AC3DfileFormat"
"(const fileName&)"
)
<< "Cannot find command " << cmd
<< " " << errorMsg
<< exit(FatalError);
}
return args;
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::fileFormats::AC3DfileFormat::AC3DfileFormat()
:
Foam::keyedSurface()
{}
Foam::fileFormats::AC3DfileFormat::AC3DfileFormat
(
const fileName& fName,
const bool triangulate
)
:
Foam::keyedSurface()
{
IFstream is(fName);
if (!is.good())
{
FatalErrorIn
(
"fileFormats::AC3DfileFormat::AC3DfileFormat"
"(const fileName&)"
)
<< "Cannot read file " << fName
<< exit(FatalError);
}
string line, cmd, args;
is.getLine(line);
string version = line.substr(4);
if (version != "b")
{
WarningIn
(
"fileFormats::AC3DfileFormat::AC3DfileFormat"
"(const fileName&)"
)
<< "When reading AC3D file " << fName
<< " read header " << line << " with version "
<< version << endl
<< "Only tested reading with version 'b'."
<< " This might give problems" << endl;
}
if (!cueTo(is, "OBJECT", args) || (args != "world"))
{
FatalErrorIn
(
"fileFormats::AC3DfileFormat::AC3DfileFormat"
"(const fileName&)"
)
<< "Cannot find \"OBJECT world\" in file " << fName
<< exit(FatalError);
}
// # of kids is the # of patches
args = cueToOrDie(is, "kids");
label nPatches = parse<int>(args);
// Start of vertices for object/patch
label patchVertOffset = 0;
DynamicList<point> pointLst;
DynamicList<keyedFace> faceLst;
// patchId => patchName
Map<word> regionNames;
for (label patchI = 0; patchI < nPatches; ++patchI)
{
word patchName = word("patch") + Foam::name(patchI);
args = cueToOrDie(is, "OBJECT", "while reading " + patchName);
// number of vertices for this patch
label nPatchPoints = 0;
vector location(pTraits<vector>::zero);
// tensor rotation(I);
// Read all info for current patch
while (is.good())
{
// Read line and get first word. If end of file break since
// patch should always end with 'kids' command ?not sure.
if (!readCmd(is, cmd, args))
{
FatalErrorIn
(
"fileFormats::AC3DfileFormat::AC3DfileFormat"
"(const fileName&)"
)
<< "Did not read up to \"kids 0\" while reading patch "
<< patchI << " from file " << fName
<< exit(FatalError);
}
if (cmd == "name")
{
// name %s
string str = parse<string>(args);
string::stripInvalid<word>(str);
patchName = str;
}
else if (cmd == "rot")
{
// rot %f %f %f %f %f %f %f %f %f
// IStringStream lineStream(args);
//
// lineStream
// >> rotation.xx() >> rotation.xy() >> rotation.xz()
// >> rotation.yx() >> rotation.yy() >> rotation.yz()
// >> rotation.zx() >> rotation.zy() >> rotation.zz();
WarningIn
(
"fileFormats::AC3DfileFormat::AC3DfileFormat"
"(const fileName&)"
)
<< "rot (rotation tensor) command not implemented"
<< "Line:" << cmd << ' ' << args << endl
<< "while reading patch " << patchI << endl;
}
else if (cmd == "loc")
{
// loc %f %f %f
IStringStream lineStream(args);
lineStream
>> location.x()
>> location.y()
>> location.z();
}
else if (cmd == "numvert")
{
// numvert %d
nPatchPoints = parse<int>(args);
for (label vertI = 0; vertI < nPatchPoints; ++vertI)
{
is.getLine(line);
IStringStream lineStream(line);
point pt;
lineStream
>> pt.x() >> pt.y() >> pt.z();
// Offset with current translation vector
pointLst.append(location + pt);
}
}
else if (cmd == "numsurf")
{
label nFaces = parse<int>(args);
for (label faceI = 0; faceI < nFaces; ++faceI)
{
static string errorMsg =
string(" while reading face ")
+ Foam::name(faceI) + " on patch "
+ Foam::name(patchI)
+ " from file " + fName;
cueToOrDie(is, "SURF", errorMsg);
cueToOrDie(is, "mat", errorMsg);
args = cueToOrDie(is, "refs", errorMsg);
label nVert = parse<int>(args);
List<label> verts(nVert);
forAll(verts, vertI)
{
is.getLine(line);
verts[vertI] = parse<int>(line) + patchVertOffset;
}
if (triangulate && verts.size() > 3)
{
face fTri(3);
// simple face triangulation about f[0].
// cannot use face::triangulation
// since points are incomplete
fTri[0] = verts[0];
for (label fp1 = 1; fp1 < verts.size() - 1; ++fp1)
{
label fp2 = (fp1 + 1) % verts.size();
fTri[1] = verts[fp1];
fTri[2] = verts[fp2];
faceLst.append(keyedFace(fTri, patchI));
}
}
else
{
faceLst.append(keyedFace(face(verts), patchI));
}
}
// Done the current patch.
// Increment the offset vertices are stored at
patchVertOffset += nPatchPoints;
}
else if (cmd == "kids")
{
// 'kids' denotes the end of the current patch.
label nKids = parse<int>(args);
if (nKids != 0)
{
FatalErrorIn
(
"fileFormats::AC3DfileFormat::AC3DfileFormat"
"(const fileName&)"
)
<< "Can only read objects without kids."
<< " Encountered " << nKids << " kids when"
<< " reading patch " << patchI
<< exit(FatalError);
}
// Done reading current patch
regionNames.insert(patchI, patchName);
break;
}
}
}
// transfer to normal lists
points().transfer(pointLst);
faces().transfer(faceLst);
setPatches(regionNames);
stitchFaces(SMALL);
}
// * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::fileFormats::AC3DfileFormat::writeHeader
(
Ostream& os,
const List<surfacePatch>& patchLst
)
{
// Write with patches as separate objects under "world" object.
// Header is taken over from sample file.
// Defines separate materials for all patches. Recycle colours.
// Define 8 standard colours as r,g,b components
static scalar colourMap[] =
{
1, 1, 1,
1, 0, 0,
0, 1, 0,
0, 0, 1,
1, 1, 0,
0, 1, 1,
1, 0, 1,
0.5, 0.5, 1
};
// Write header. Define materials.
os << "AC3Db" << nl;
forAll(patchLst, patchI)
{
const word& pName = patchLst[patchI].name();
label colourI = patchI % 8;
label colourCompI = 3 * colourI;
os << "MATERIAL \"" << pName << "Mat\" rgb "
<< colourMap[colourCompI] << ' ' << colourMap[colourCompI+1]
<< ' ' << colourMap[colourCompI+2]
<< " amb 0.2 0.2 0.2 emis 0 0 0 spec 0.5 0.5 0.5 shi 10"
<< " trans 0"
<< nl;
}
os << "OBJECT world" << nl
<< "kids " << patchLst.size() << endl;
}
void Foam::fileFormats::AC3DfileFormat::write
(
Ostream& os,
const keyedSurface& surf
)
{
labelList faceMap;
List<surfacePatch> patchLst = surf.sortedRegions(faceMap);
writeHeader(os, patchLst);
label faceIndex = 0;
forAll(patchLst, patchI)
{
const surfacePatch& sp = patchLst[patchI];
os << "OBJECT poly" << nl
<< "name \"" << sp.name() << '"' << endl;
// Create patch with only patch faces included for ease of addressing
boolList include(surf.size(), false);
forAll(sp, patchFaceI)
{
const label faceI = faceMap[faceIndex++];
include[faceI] = true;
}
labelList pMap;
labelList fMap;
keyedSurface patch = surf.subsetMesh
(
include, pMap, fMap
);
// Now we have triSurface for this patch alone. Write it.
os << "numvert " << patch.nPoints() << endl;
forAll(patch.localPoints(), ptI)
{
const point& pt = patch.localPoints()[ptI];
os << pt.x() << ' ' << pt.y() << ' ' << pt.z() << endl;
}
os << "numsurf " << patch.localFaces().size() << endl;
forAll(patch.localFaces(), faceI)
{
const keyedFace& f = patch.localFaces()[faceI];
os << "SURF 0x20" << nl // polygon
<< "mat " << patchI << nl
<< "refs " << f.size() << nl;
forAll(f, fp)
{
os << f[fp] << " 0 0" << nl;
}
}
os << "kids 0" << endl;
}
}
void Foam::fileFormats::AC3DfileFormat::write
(
Ostream& os,
const meshedSurface& surf
)
{
const pointField& pointLst = surf.points();
const List<face>& faceLst = surf.faces();
const List<surfacePatch>& patchLst = surf.patches();
writeHeader(os, patchLst);
forAll(patchLst, patchI)
{
const surfacePatch& sp = patchLst[patchI];
os << "OBJECT poly" << nl
<< "name \"" << sp.name() << '"' << endl;
// Temporary primitivePatch to calculate compact points & faces
primitivePatch patch
(
SubList<face>
(
faceLst,
sp.start(),
sp.size()
),
pointLst
);
os << "numvert " << patch.nPoints() << endl;
forAll(patch.localPoints(), ptI)
{
const point& pt = patch.localPoints()[ptI];
os << pt.x() << ' ' << pt.y() << ' ' << pt.z() << endl;
}
os << "numsurf " << patch.localFaces().size() << endl;
forAll(patch.localFaces(), faceI)
{
const keyedFace& f = patch.localFaces()[faceI];
os << "SURF 0x20" << nl // polygon
<< "mat " << patchI << nl
<< "refs " << f.size() << nl;
forAll(f, fp)
{
os << f[fp] << " 0 0" << nl;
}
}
os << "kids 0" << endl;
}
}
// ************************************************************************* //

View File

@ -0,0 +1,167 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 1991-2008 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::AC3DfileFormat
Description
Provide a means of reading/writing AC3D format.
http://www.inivis.com/ac3d/man/ac3dfileformat.html
Note
Since the faces are already organized as patches, the reader could be
optimized for this, but at expense of losing a common reading approach.
SourceFiles
AC3DfileFormat.C
\*---------------------------------------------------------------------------*/
#ifndef AC3DfileFormat_H
#define AC3DfileFormat_H
#include "Ostream.H"
#include "OFstream.H"
#include "keyedSurface.H"
#include "meshedSurface.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace fileFormats
{
class AC3DfileFormat;
/*---------------------------------------------------------------------------*\
Class AC3DfileFormat Declaration
\*---------------------------------------------------------------------------*/
class AC3DfileFormat
:
public keyedSurface
{
// Private Member Functions
//- Read a type via IStringStream
template<class Type>
static Type parse(const string&);
//- Read cmd, args from IFstream
static bool readCmd(IFstream&, string& cmd, string& args);
//- Cue up to cmd, reading args
static bool cueTo(IFstream&, const string& cmd, string& args);
//- Cue up to cmd, reading args or exit with a FatalError
// returns the command args
static string cueToOrDie
(
IFstream&,
const string& cmd,
const string& errorMsg=string::null
);
//- Write header with materials
static void writeHeader(Ostream&, const List<surfacePatch>&);
//- Disallow default bitwise copy construct
AC3DfileFormat(const AC3DfileFormat&);
//- Disallow default bitwise assignment
void operator=(const AC3DfileFormat&);
public:
// Constructors
//- Construct null
AC3DfileFormat();
//- Construct from file name
AC3DfileFormat(const fileName&, const bool triangulate=false);
// Selectors
//- Read file and return keyedSurface
static autoPtr<keyedSurface> New
(
const fileName& fName,
const bool triangulate=false
)
{
return autoPtr<keyedSurface>
(
new AC3DfileFormat(fName, triangulate)
);
}
// Destructor
// Member Functions
// Write
//- Write keyedSurface
static void write(Ostream&, const keyedSurface&);
//- Write keyedSurface
static void write(const fileName& fName, const keyedSurface& surf)
{
write(OFstream(fName)(), surf);
}
//- Write meshedSurface
static void write(Ostream&, const meshedSurface&);
//- Write meshedSurface
static void write(const fileName& fName, const meshedSurface& surf)
{
write(OFstream(fName)(), surf);
}
//- Write object
virtual void write(Ostream& os) const
{
write(os, *this);
}
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace fileFormats
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,440 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 1991-2008 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 "GTSfileFormat.H"
#include "clock.H"
#include "IFstream.H"
#include "IStringStream.H"
#include "tensor.H"
#include "primitivePatch.H"
#include "addToRunTimeSelectionTable.H"
#include "addToMemberFunctionSelectionTable.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
namespace fileFormats
{
addNamedToRunTimeSelectionTable
(
keyedSurface,
GTSfileFormat,
fileExtension,
gts
);
addNamedToMemberFunctionSelectionTable
(
keyedSurface,
GTSfileFormat,
write,
fileExtension,
gts
);
addNamedToMemberFunctionSelectionTable
(
meshedSurface,
GTSfileFormat,
write,
fileExtension,
gts
);
}
}
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::fileFormats::GTSfileFormat::GTSfileFormat()
:
Foam::keyedSurface()
{}
Foam::fileFormats::GTSfileFormat::GTSfileFormat
(
const fileName& fName,
const bool triangulate
)
:
Foam::keyedSurface()
{
IFstream is(fName);
if (!is.good())
{
FatalErrorIn
(
"fileFormats::GTSfileFormat::GTSfileFormat"
"(const fileName&)"
)
<< "Cannot read file " << fName
<< exit(FatalError);
}
// Read header
string line = getLineNoComment(is);
label nPoints, nEdges, nElems;
{
IStringStream lineStream(line);
lineStream
>> nPoints
>> nEdges
>> nElems;
}
pointField pointLst(nPoints);
// Read points
forAll(pointLst, pointI)
{
scalar x, y, z;
line = getLineNoComment(is);
{
IStringStream lineStream(line);
lineStream
>> x >> y >> z;
}
pointLst[pointI] = point(x, y, z);
}
// Read edges (Foam indexing)
edgeList edges(nEdges);
forAll(edges, edgei)
{
label beg, end;
line = getLineNoComment(is);
{
IStringStream lineStream(line);
lineStream
>> beg >> end;
}
edges[edgei] = edge(beg - 1, end - 1);
}
// Read triangles. Convert references to edges into pointlabels
List<keyedFace> faceLst(nElems);
label maxPatch = 0;
forAll(faceLst, faceI)
{
label e0Label, e1Label, e2Label;
label region = 0;
line = getLineNoComment(is);
{
IStringStream lineStream(line);
lineStream
>> e0Label >> e1Label >> e2Label;
// Optional region number: read first, then check state on stream
if (lineStream)
{
label num;
lineStream >> num;
if (!lineStream.bad())
{
region = num;
if (maxPatch < region)
{
maxPatch = region;
}
}
}
}
// Determine ordering of edges e0, e1
// common: common vertex, shared by e0 and e1
// e0Far: vertex on e0 which is not common
// e1Far: vertex on e1 which is not common
const edge& e0 = edges[e0Label - 1];
const edge& e1 = edges[e1Label - 1];
const edge& e2 = edges[e2Label - 1];
label common01 = e0.commonVertex(e1);
if (common01 == -1)
{
FatalErrorIn
(
"fileFormats::GTSfileFormat::GTSfileFormat"
"(const fileName&)"
)
<< "Edges 0 and 1 of triangle " << faceI
<< " do not share a point.\n"
<< " edge0:" << e0 << nl
<< " edge1:" << e1
<< exit(FatalError);
}
label e0Far = e0.otherVertex(common01);
label e1Far = e1.otherVertex(common01);
label common12 = e1.commonVertex(e2);
if (common12 == -1)
{
FatalErrorIn
(
"fileFormats::GTSfileFormat::GTSfileFormat"
"(const fileName&)"
)
<< "Edges 1 and 2 of triangle " << faceI
<< " do not share a point.\n"
<< " edge1:" << e1 << nl
<< " edge2:" << e2
<< exit(FatalError);
}
label e2Far = e2.otherVertex(common12);
// Does edge2 sit between edge1 and 0?
if (common12 != e1Far || e2Far != e0Far)
{
FatalErrorIn
(
"fileFormats::GTSfileFormat::GTSfileFormat"
"(const fileName&)"
)
<< "Edges of triangle " << faceI
<< " reference more than three points.\n"
<< " edge0:" << e0 << nl
<< " edge1:" << e1 << nl
<< " edge2:" << e2 << nl
<< exit(FatalError);
}
keyedFace lface(face(3), region);
lface[0] = e0Far;
lface[1] = common01;
lface[2] = e1Far;
faceLst[faceI] = lface;
}
// transfer to normal lists
points().transfer(pointLst);
faces().transfer(faceLst);
setPatches(maxPatch);
// stitchFaces(SMALL);
}
// * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::fileFormats::GTSfileFormat::write
(
Ostream& os,
const keyedSurface& surf
)
{
const pointField& pointLst = surf.points();
const List<keyedFace>& faceLst = surf.faces();
// It is too annoying to triangulate on-the-fly
// just issue a warning and get out
label nNonTris = 0;
forAll(faceLst, faceI)
{
if (faceLst[faceI].size() > 3)
{
++nNonTris;
}
}
if (nNonTris)
{
FatalErrorIn
(
"fileFormats::GTSfileFormat::write"
"(Ostream&, const keyedSurface&)"
)
<< "Surface has " << nNonTris << "/" << faceLst.size()
<< " non-triangulated faces - not writing!" << endl;
return;
}
labelList faceMap;
List<surfacePatch> patchLst = surf.sortedRegions(faceMap);
// Write header, print patch names as comment
os << "# GTS file" << nl
<< "# Regions:" << nl;
forAll(patchLst, patchI)
{
os << "# " << patchI << " "
<< patchLst[patchI].name() << nl;
}
os << "#" << endl;
os << "# nPoints nEdges nTriangles" << nl
<< pointLst.size() << ' ' << surf.nEdges() << ' '
<< surf.size() << endl;
// Write vertex coords
forAll(pointLst, pointI)
{
os << pointLst[pointI].x() << ' '
<< pointLst[pointI].y() << ' '
<< pointLst[pointI].z() << endl;
}
// Write edges.
// Note: edges are in local point labels so convert
const edgeList& es = surf.edges();
const labelList& meshPts = surf.meshPoints();
forAll(es, edgeI)
{
os << meshPts[es[edgeI].start()] + 1 << ' '
<< meshPts[es[edgeI].end()] + 1 << endl;
}
// Write faces in terms of edges.
const labelListList& faceEs = surf.faceEdges();
label faceIndex = 0;
forAll(patchLst, patchI)
{
forAll(patchLst[patchI], patchFaceI)
{
const labelList& fEdges = faceEs[faceMap[faceIndex++]];
os << fEdges[0] + 1 << ' '
<< fEdges[1] + 1 << ' '
<< fEdges[2] + 1 << ' '
<< patchI << endl;
}
}
}
void Foam::fileFormats::GTSfileFormat::write
(
Ostream& os,
const meshedSurface& surf
)
{
const pointField& pointLst = surf.points();
const List<surfacePatch>& patchLst = surf.patches();
const List<face>& faceLst = surf.faces();
// It is too annoying to triangulate on-the-fly
// just issue a warning and get out
label nNonTris = 0;
forAll(faceLst, faceI)
{
if (faceLst[faceI].size() > 3)
{
++nNonTris;
}
}
if (nNonTris)
{
WarningIn
(
"fileFormats::GTSfileFormat::write"
"(Ostream&, const meshedSurface&)"
)
<< "Surface has " << nNonTris << "/" << faceLst.size()
<< " non-triangulated faces - not writing!" << endl;
return;
}
// Write header, print patch names as comment
os << "# GTS file" << nl
<< "# Regions:" << nl;
forAll(patchLst, patchI)
{
os << "# " << patchI << " "
<< patchLst[patchI].name() << nl;
}
os << "#" << endl;
os << "# nPoints nEdges nTriangles" << nl
<< pointLst.size() << ' ' << surf.nEdges() << ' '
<< surf.size() << endl;
// Write vertex coords
forAll(pointLst, pointI)
{
os << pointLst[pointI].x() << ' '
<< pointLst[pointI].y() << ' '
<< pointLst[pointI].z() << endl;
}
// Write edges.
// Note: edges are in local point labels so convert
const edgeList& es = surf.edges();
const labelList& meshPts = surf.meshPoints();
forAll(es, edgei)
{
os << meshPts[es[edgei].start()] + 1 << ' '
<< meshPts[es[edgei].end()] + 1 << endl;
}
// Write faces in terms of edges.
const labelListList& faceEs = surf.faceEdges();
label faceIndex = 0;
forAll(patchLst, patchI)
{
const surfacePatch& patch = patchLst[patchI];
forAll(patch, patchFaceI)
{
const labelList& fEdges = faceEs[faceIndex++];
os << fEdges[0] + 1 << ' '
<< fEdges[1] + 1 << ' '
<< fEdges[2] + 1 << ' '
<< patchI << endl;
}
}
}
// ************************************************************************* //

View File

@ -0,0 +1,139 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 1991-2008 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::GTSfileFormat
Description
Provide a means of reading/writing GTS format.
SourceFiles
GTSfileFormat.C
\*---------------------------------------------------------------------------*/
#ifndef GTSfileFormat_H
#define GTSfileFormat_H
#include "Ostream.H"
#include "OFstream.H"
#include "keyedSurface.H"
#include "meshedSurface.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace fileFormats
{
class GTSfileFormat;
/*---------------------------------------------------------------------------*\
Class GTSfileFormat Declaration
\*---------------------------------------------------------------------------*/
class GTSfileFormat
:
public keyedSurface
{
// Private Member Functions
//- Disallow default bitwise copy construct
GTSfileFormat(const GTSfileFormat&);
//- Disallow default bitwise assignment
void operator=(const GTSfileFormat&);
public:
// Constructors
//- Construct null
GTSfileFormat();
//- Construct from file name
GTSfileFormat(const fileName&, const bool triangulate=true);
// Selectors
//- Read file and return keyedSurface
static autoPtr<keyedSurface> New
(
const fileName& fName,
const bool triangulate=true
)
{
return autoPtr<keyedSurface>
(
new GTSfileFormat(fName, triangulate)
);
}
// Destructor
// Member Functions
// Write
//- Write keyedSurface
static void write(Ostream&, const keyedSurface&);
//- Write keyedSurface
static void write(const fileName& fName, const keyedSurface& surf)
{
write(OFstream(fName)(), surf);
}
//- Write meshedSurface
static void write(Ostream&, const meshedSurface&);
//- Write meshedSurface
static void write(const fileName& fName, const meshedSurface& surf)
{
write(OFstream(fName)(), surf);
}
//- Write object
virtual void write(Ostream& os) const
{
write(os, *this);
}
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace fileFormats
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,461 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 1991-2008 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 "NASfileFormat.H"
#include "clock.H"
#include "IFstream.H"
#include "IStringStream.H"
#include "addToRunTimeSelectionTable.H"
#include "addToMemberFunctionSelectionTable.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
namespace fileFormats
{
// .bdf (Bulk Data Format)
addNamedToRunTimeSelectionTable
(
keyedSurface,
NASfileFormat,
fileExtension,
bdf
);
// .nas (Nastran)
addNamedToRunTimeSelectionTable
(
keyedSurface,
NASfileFormat,
fileExtension,
nas
);
// addNamedToMemberFunctionSelectionTable
// (
// keyedSurface,
// NASfileFormat,
// write,
// fileExtension,
// nas
// );
//
// addNamedToMemberFunctionSelectionTable
// (
// meshedSurface,
// NASfileFormat,
// write,
// fileExtension,
// nas
// );
}
}
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
// Do weird things to extract number
Foam::scalar Foam::fileFormats::NASfileFormat::parseNASCoord(const string& s)
{
size_t expSign = s.find_last_of("+-");
if (expSign != string::npos && expSign > 0 && !isspace(s[expSign-1]))
{
scalar mantissa = readScalar(IStringStream(s.substr(0, expSign))());
scalar exponent = readScalar(IStringStream(s.substr(expSign+1))());
if (s[expSign] == '-')
{
exponent = -exponent;
}
return mantissa*pow(10, exponent);
}
else
{
return readScalar(IStringStream(s)());
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::fileFormats::NASfileFormat::NASfileFormat()
:
Foam::keyedSurface()
{}
Foam::fileFormats::NASfileFormat::NASfileFormat
(
const fileName& fName,
const bool triangulate
)
:
Foam::keyedSurface()
{
IFstream is(fName);
if (!is.good())
{
FatalErrorIn("fileFormats::NASfileFormat::NASfileFormat(const fileName&)")
<< "Cannot read file " << fName
<< exit(FatalError);
}
DynamicList<point> pointLst;
// Nastran index of points
DynamicList<label> pointId;
DynamicList<keyedFace> faceLst;
HashTable<label> groupToPatch;
// From face groupId to patchId
Map<label> groupIdToPatchId;
label nPatches = 0;
// Name for face group
Map<word> groupIdToName;
// Ansa tags. Denoted by $ANSA_NAME. These will appear just before the
// first use of a type. We read them and store the pshell types which
// are used to name the patches.
label ansaId = -1;
word ansaType;
word ansaName;
// leave faces that didn't have a group in 0
// label groupID = 0;
// label maxGroupID = -1;
// A single warning per unrecognized command
HashSet<word> unhandledCmd;
while (is.good())
{
string line;
is.getLine(line);
// Ansa extension
if (line.substr(0, 10) == "$ANSA_NAME")
{
string::size_type sem0 = line.find (';', 0);
string::size_type sem1 = line.find (';', sem0+1);
string::size_type sem2 = line.find (';', sem1+1);
if
(
sem0 != string::npos
&& sem1 != string::npos
&& sem2 != string::npos
)
{
ansaId = readLabel
(
IStringStream(line.substr(sem0+1, sem1-sem0-1))()
);
ansaType = line.substr(sem1+1, sem2-sem1-1);
string rawName;
is.getLine(rawName);
if (rawName[rawName.size()-1] == '\r')
{
rawName = rawName.substr(1, rawName.size()-2);
}
else
{
rawName = rawName.substr(1, rawName.size()-1);
}
string::stripInvalid<word>(rawName);
ansaName = rawName;
// Info<< "ANSA tag for NastranID:" << ansaID
// << " of type " << ansaType
// << " name " << ansaName << endl;
}
}
// Hypermesh extension
// $HMNAME COMP 1"partName"
if
(
line.substr(0, 12) == "$HMNAME COMP"
&& line.find ('"') != string::npos
)
{
label groupId = readLabel
(
IStringStream(line.substr(16, 16))()
);
IStringStream lineStream(line.substr(32));
string rawName;
lineStream >> rawName;
string::stripInvalid<word>(rawName);
word groupName(rawName);
groupIdToName.insert(groupId, groupName);
Info<< "group " << groupId << " => " << groupName << endl;
}
// Skip empty or comment
if (line.size() == 0 || line[0] == '$')
{
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 == "CTRIA3")
{
face fTri(3);
label groupId = readLabel(IStringStream(line.substr(16,8))());
fTri[0] = readLabel(IStringStream(line.substr(24,8))());
fTri[1] = readLabel(IStringStream(line.substr(32,8))());
fTri[2] = readLabel(IStringStream(line.substr(40,8))());
// Convert groupID into patchID
Map<label>::const_iterator iter = groupIdToPatchId.find(groupId);
label patchI;
if (iter == groupIdToPatchId.end())
{
patchI = nPatches++;
groupIdToPatchId.insert(groupId, patchI);
Info<< "patch " << patchI << " => group " << groupId << endl;
}
else
{
patchI = iter();
}
faceLst.append(keyedFace(fTri, patchI));
}
else if (cmd == "CQUAD4")
{
face fQuad(4);
label groupId = readLabel(IStringStream(line.substr(16,8))());
fQuad[0] = readLabel(IStringStream(line.substr(24,8))());
fQuad[1] = readLabel(IStringStream(line.substr(32,8))());
fQuad[2] = readLabel(IStringStream(line.substr(40,8))());
fQuad[3] = readLabel(IStringStream(line.substr(48,8))());
// Convert group into patch
Map<label>::const_iterator iter = groupIdToPatchId.find(groupId);
label patchI;
if (iter == groupIdToPatchId.end())
{
patchI = nPatches++;
groupIdToPatchId.insert(groupId, patchI);
Info<< "patch " << patchI << " => group " << groupId << endl;
}
else
{
patchI = iter();
}
if (triangulate)
{
face fTri(3);
// simple face triangulation about f[0].
// cannot use face::triangulation since points are incomplete
fTri[0] = fQuad[0];
for (label fp1 = 1; fp1 < fQuad.size() - 1; fp1++)
{
label fp2 = (fp1 + 1) % fQuad.size();
fTri[1] = fQuad[fp1];
fTri[2] = fQuad[fp2];
faceLst.append(keyedFace(fTri, patchI));
}
}
else
{
faceLst.append(keyedFace(fQuad, patchI));
}
}
else if (cmd == "PSHELL")
{
// Read shell type since group gives patchnames.
label groupId = readLabel(IStringStream(line.substr(8,8))());
if (groupId == ansaId && ansaType == "PSHELL")
{
groupIdToName.insert(groupId, ansaName);
Info<< "group " << groupId << " => " << ansaName << endl;
}
}
else if (cmd == "GRID")
{
label index = readLabel(IStringStream(line.substr(8,8))());
scalar x = parseNASCoord(line.substr(24, 8));
scalar y = parseNASCoord(line.substr(32, 8));
scalar z = parseNASCoord(line.substr(40, 8));
pointId.append(index);
pointLst.append(point(x, y, z));
}
else if (cmd == "GRID*")
{
// Long format is on two lines with '*' continuation symbol
// on start of second line.
// Typical line (spaces compacted)
// GRID* 126 0 -5.55999875E+02 -5.68730474E+02
// * 2.14897901E+02
label index = readLabel(IStringStream(line.substr(8,16))());
scalar x = parseNASCoord(line.substr(40, 16));
scalar y = parseNASCoord(line.substr(56, 16));
is.getLine(line);
if (line[0] != '*')
{
FatalErrorIn
(
"fileFormats::NASfileFormat::NASfileFormat"
"(const fileName&)"
)
<< "Expected continuation symbol '*' when reading GRID*"
<< " (double precision coordinate) output" << nl
<< "Read:" << line << nl
<< "File:" << is.name()
<< " line:" << is.lineNumber()
<< exit(FatalError);
}
scalar z = parseNASCoord(line.substr(8, 16));
pointId.append(index);
pointLst.append(point(x, y, z));
}
else if (unhandledCmd.insert(cmd))
{
Info<< "Unhandled Nastran command " << line << nl
<< "File:" << is.name()
<< " line:" << is.lineNumber()
<< endl;
}
}
Info<< "Read faces:" << faceLst.size()
<< " points:" << pointLst.size()
<< endl;
// transfer to normal lists
points().transfer(pointLst);
pointId.shrink();
faceLst.shrink();
{
// Build inverse mapping (index to point)
Map<label> nasToFoamPoint(2*pointId.size());
forAll(pointId, i)
{
nasToFoamPoint.insert(pointId[i], i);
}
pointId.clearStorage();
// Relabel faces
forAll(faceLst, i)
{
keyedFace& f = faceLst[i];
forAll(f, fp)
{
f[fp] = nasToFoamPoint[f[fp]];
}
}
}
// convert Nastran groupId => name to patchId => name
Map<word> regionNames;
forAllConstIter(Map<word>, groupIdToName, iter)
{
Map<label>::const_iterator iter2 = groupIdToPatchId.find(iter.key());
if (iter2 != groupIdToPatchId.end())
{
regionNames.insert(iter2.key(), iter());
}
}
// transfer to normal lists
faces().transfer(faceLst);
setPatches(regionNames);
}
// * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * Friend Functions * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
// ************************************************************************* //
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// ************************************************************************* //

View File

@ -0,0 +1,122 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 1991-2008 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::NASfileFormat
Description
Nastran surface reader.
- Uses the Ansa "$ANSA_NAME" or the Hypermesh "$HMNAME COMP" extensions
to obtain patch names.
- Handles Nastran short and long formats, but not free format.
- Properly handles the Nastran compact floating point notation: \n
@verbatim
GRID 28 10.20269-.030265-2.358-8
@endverbatim
SourceFiles
NASfileFormat.C
\*---------------------------------------------------------------------------*/
#ifndef NASfileFormat_H
#define NASfileFormat_H
#include "Ostream.H"
#include "OFstream.H"
#include "keyedSurface.H"
#include "meshedSurface.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace fileFormats
{
/*---------------------------------------------------------------------------*\
Class NASfileFormat Declaration
\*---------------------------------------------------------------------------*/
class NASfileFormat
:
public keyedSurface
{
// Private Member Functions
//- Do weird things to extract number
static scalar parseNASCoord(const string&);
//- Disallow default bitwise copy construct
NASfileFormat(const NASfileFormat&);
//- Disallow default bitwise assignment
void operator=(const NASfileFormat&);
public:
// Constructors
//- Construct null
NASfileFormat();
//- Construct from file name
NASfileFormat(const fileName&, const bool triangulate=false);
// Selectors
//- Read file and return keyedSurface
static autoPtr<keyedSurface> New
(
const fileName& fName,
const bool triangulate=false
)
{
return autoPtr<keyedSurface>
(
new NASfileFormat(fName,triangulate)
);
}
// Destructor
// Member Functions
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace fileFormats
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,371 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 1991-2008 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 "OBJfileFormat.H"
#include "clock.H"
#include "IFstream.H"
#include "IStringStream.H"
#include "addToRunTimeSelectionTable.H"
#include "addToMemberFunctionSelectionTable.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
namespace fileFormats
{
addNamedToRunTimeSelectionTable
(
keyedSurface,
OBJfileFormat,
fileExtension,
obj
);
addNamedToMemberFunctionSelectionTable
(
keyedSurface,
OBJfileFormat,
write,
fileExtension,
obj
);
addNamedToMemberFunctionSelectionTable
(
meshedSurface,
OBJfileFormat,
write,
fileExtension,
obj
);
}
}
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::fileFormats::OBJfileFormat::OBJfileFormat()
:
Foam::keyedSurface()
{}
Foam::fileFormats::OBJfileFormat::OBJfileFormat
(
const fileName& fName,
const bool triangulate
)
:
Foam::keyedSurface()
{
IFstream is(fName);
if (!is.good())
{
FatalErrorIn("fileFormats::OBJfileFormat::OBJfileFormat(const fileName&)")
<< "Cannot read file " << fName
<< exit(FatalError);
}
DynamicList<point> pointLst;
DynamicList<keyedFace> faceLst;
HashTable<label> groupToPatch;
// leave faces that didn't have a group in 0
label groupID = 0;
label maxGroupID = -1;
while (is.good())
{
string line = getLineNoComment(is);
// handle continuations
if (line[line.size()-1] == '\\')
{
line.substr(0, line.size()-1);
line += getLineNoComment(is);
}
// Read first word
IStringStream lineStream(line);
word cmd;
lineStream >> cmd;
if (cmd == "v")
{
scalar x, y, z;
lineStream >> x >> y >> z;
pointLst.append(point(x, y, z));
}
else if (cmd == "g")
{
word groupName;
lineStream >> groupName;
HashTable<label>::const_iterator findGroup =
groupToPatch.find(groupName);
if (findGroup != groupToPatch.end())
{
groupID = findGroup();
}
else
{
// special treatment if any initial faces were not in a group
if (maxGroupID == -1 && faceLst.size())
{
groupToPatch.insert("patch0", 0);
maxGroupID = 0;
}
groupID = ++maxGroupID;
groupToPatch.insert(groupName, groupID);
}
}
else if (cmd == "f")
{
DynamicList<label> verts;
// Assume 'f' is followed by space.
string::size_type endNum = 1;
while (true)
{
string::size_type startNum = line.find_first_not_of(' ', endNum);
if (startNum == string::size_type(string::npos))
{
break;
}
endNum = line.find(' ', startNum);
string vertexSpec;
if (endNum != string::size_type(string::npos))
{
vertexSpec = line.substr(startNum, endNum-startNum);
}
else
{
vertexSpec = line.substr(startNum, line.size() - startNum);
}
string::size_type slashPos = vertexSpec.find('/');
label vertI = 0;
if (slashPos != string::size_type(string::npos))
{
IStringStream intStream(vertexSpec.substr(0, slashPos));
intStream >> vertI;
}
else
{
IStringStream intStream(vertexSpec);
intStream >> vertI;
}
verts.append(vertI - 1);
}
verts.shrink();
if (triangulate && verts.size() > 3)
{
face fTri(3);
// simple face triangulation about f[0].
// Cannot use face::triangulation since points are incomplete
fTri[0] = verts[0];
for (label fp1 = 1; fp1 < verts.size() - 1; fp1++)
{
label fp2 = (fp1 + 1) % verts.size();
fTri[1] = verts[fp1];
fTri[2] = verts[fp2];
faceLst.append(keyedFace(fTri, groupID));
}
}
else
{
faceLst.append
(
keyedFace
(
face( xferMoveTo<labelList>(verts) ),
groupID
)
);
}
}
}
// transfer to normal lists
points().transfer(pointLst);
faces().transfer(faceLst);
setPatches(groupToPatch);
}
// * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::fileFormats::OBJfileFormat::write
(
Ostream& os,
const keyedSurface& surf
)
{
const pointField& pointLst = surf.points();
const List<keyedFace>& faceLst = surf.faces();
labelList faceMap;
List<surfacePatch> patchLst = surf.sortedRegions(faceMap);
os << "# Wavefront OBJ file written " << clock::dateTime().c_str() << nl
<< "o " << os.name().lessExt().name() << nl
<< nl
<< "# points : " << pointLst.size() << nl
<< "# faces : " << faceLst.size() << nl
<< "# patches: " << patchLst.size() << nl;
// Print patch names as comment
forAll(patchLst, patchI)
{
os << "# " << patchI << " " << patchLst[patchI].name()
<< " (nFaces: " << patchLst[patchI].size() << ")" << nl;
}
os << nl
<< "# <points count=\"" << pointLst.size() << "\">" << endl;
// Write vertex coords
forAll(pointLst, ptI)
{
os << "v " << pointLst[ptI].x()
<< ' ' << pointLst[ptI].y()
<< ' ' << pointLst[ptI].z() << nl;
}
os << "# </points>" << nl
<< nl
<< "# <faces count=\"" << faceLst.size() << "\">" << endl;
label faceIndex = 0;
forAll(patchLst, patchI)
{
// Print all faces belonging to this region
const surfacePatch& patch = patchLst[patchI];
os << "g " << patch.name() << endl;
forAll(patch, patchFaceI)
{
const face& f = faceLst[faceMap[faceIndex++]];
os << 'f';
forAll(f, fp)
{
os << ' ' << f[fp] + 1;
}
os << endl;
}
}
os << "# </faces>" << endl;
}
void Foam::fileFormats::OBJfileFormat::write
(
Ostream& os,
const meshedSurface& surf
)
{
const pointField& pointLst = surf.points();
const List<face>& faceLst = surf.faces();
const List<surfacePatch>& patchLst = surf.patches();
os << "# Wavefront OBJ file written " << clock::dateTime().c_str() << nl
<< "o " << os.name().lessExt().name() << nl
<< nl
<< "# points : " << pointLst.size() << nl
<< "# faces : " << faceLst.size() << nl
<< "# patches: " << patchLst.size() << nl;
// Print patch names as comment
forAll(patchLst, patchI)
{
os << "# " << patchI << " " << patchLst[patchI].name()
<< " (nFaces: " << patchLst[patchI].size() << ")" << nl;
}
os << nl
<< "# <points count=\"" << pointLst.size() << "\">" << endl;
// Write vertex coords
forAll(pointLst, ptI)
{
os << "v " << pointLst[ptI].x()
<< ' ' << pointLst[ptI].y()
<< ' ' << pointLst[ptI].z() << nl;
}
os << "# </points>" << nl
<< nl
<< "# <faces count=\"" << faceLst.size() << "\">" << endl;
label faceIndex = 0;
forAll(patchLst, patchI)
{
const surfacePatch& patch = patchLst[patchI];
os << "g " << patch.name() << endl;
forAll(patch, patchFaceI)
{
const face& f = faceLst[faceIndex++];
os << 'f';
forAll(f, fp)
{
os << ' ' << f[fp] + 1;
}
os << endl;
}
}
os << "# </faces>" << endl;
}
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * Friend Functions * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
// ************************************************************************* //

View File

@ -0,0 +1,139 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 1991-2008 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::OBJfileFormat
Description
Provide a means of reading/writing Alias/Wavefront OBJ format.
Does not handle negative face indices.
SourceFiles
OBJfileFormat.C
\*---------------------------------------------------------------------------*/
#ifndef OBJfileFormat_H
#define OBJfileFormat_H
#include "Ostream.H"
#include "OFstream.H"
#include "keyedSurface.H"
#include "meshedSurface.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace fileFormats
{
/*---------------------------------------------------------------------------*\
Class OBJfileFormat Declaration
\*---------------------------------------------------------------------------*/
class OBJfileFormat
:
public keyedSurface
{
// Private Member Functions
//- Disallow default bitwise copy construct
OBJfileFormat(const OBJfileFormat&);
//- Disallow default bitwise assignment
void operator=(const OBJfileFormat&);
public:
// Constructors
//- Construct null
OBJfileFormat();
//- Construct from file name
OBJfileFormat(const fileName&, const bool triangulate=false);
// Selectors
//- Read file and return keyedSurface
static autoPtr<keyedSurface> New
(
const fileName& fName,
const bool triangulate = false
)
{
return autoPtr<keyedSurface>
(
new OBJfileFormat(fName, triangulate)
);
}
// Destructor
// Member Functions
// Write
//- Write keyedSurface
static void write(Ostream&, const keyedSurface&);
//- Write keyedSurface
static void write(const fileName& fName, const keyedSurface& surf)
{
write(OFstream(fName)(), surf);
}
//- Write meshedSurface
static void write(Ostream&, const meshedSurface&);
//- Write meshedSurface
static void write(const fileName& fName, const meshedSurface& surf)
{
write(OFstream(fName)(), surf);
}
//- Write object
virtual void write(Ostream& os) const
{
write(os, *this);
}
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace fileFormats
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,326 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 1991-2008 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 "OFFfileFormat.H"
#include "clock.H"
#include "IFstream.H"
#include "IStringStream.H"
#include "addToRunTimeSelectionTable.H"
#include "addToMemberFunctionSelectionTable.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
namespace fileFormats
{
addNamedToRunTimeSelectionTable
(
keyedSurface,
OFFfileFormat,
fileExtension,
off
);
addNamedToMemberFunctionSelectionTable
(
keyedSurface,
OFFfileFormat,
write,
fileExtension,
off
);
addNamedToMemberFunctionSelectionTable
(
meshedSurface,
OFFfileFormat,
write,
fileExtension,
off
);
}
}
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::fileFormats::OFFfileFormat::OFFfileFormat()
:
keyedSurface()
{}
Foam::fileFormats::OFFfileFormat::OFFfileFormat
(
const fileName& fName,
const bool triangulate
)
:
keyedSurface()
{
IFstream is(fName);
if (!is.good())
{
FatalErrorIn("fileFormats::OFFfileFormat(const fileName&)")
<< "Cannot read file " << fName
<< exit(FatalError);
}
// Read header
string hdr = getLineNoComment(is);
if (hdr != "OFF")
{
FatalErrorIn("fileFormats::OFFfileFormat(const fileName&)")
<< "OFF file " << fName
<< " does not start with 'OFF'"
<< exit(FatalError);
}
// get dimensions
label nPoints, nEdges, nElems;
string line = getLineNoComment(is);
{
IStringStream lineStream(line);
lineStream >> nPoints >> nElems >> nEdges;
}
// Read points
pointField pointLst(nPoints);
forAll(pointLst, pointI)
{
scalar x, y, z;
line = getLineNoComment(is);
{
IStringStream lineStream(line);
lineStream >> x >> y >> z;
}
pointLst[pointI] = point(x, y, z);
}
// Read faces - ignore optional region information
// use a DynamicList for possible on-the-fly triangulation
DynamicList<keyedFace> faceLst(nElems);
forAll(faceLst, faceI)
{
line = getLineNoComment(is);
{
IStringStream lineStream(line);
label nVerts;
lineStream >> nVerts;
face f(nVerts);
forAll(f, fp)
{
lineStream >> f[fp];
}
if (triangulate && f.size() > 3)
{
face fTri(3);
// simple face triangulation about f[0].
// cannot use face::triangulation since points are incomplete
fTri[0] = f[0];
for (label fp1 = 1; fp1 < f.size() - 1; fp1++)
{
label fp2 = (fp1 + 1) % f.size();
fTri[1] = f[fp1];
fTri[2] = f[fp2];
faceLst.append(keyedFace(fTri, 0));
}
}
else
{
faceLst.append(keyedFace(f, 0));
}
}
}
// no region information
points().transfer(pointLst);
faces().transfer(faceLst);
setPatches(0);
}
// * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::fileFormats::OFFfileFormat::write
(
Ostream& os,
const keyedSurface& surf
)
{
const pointField& pointLst = surf.points();
const List<keyedFace>& faceLst = surf.faces();
labelList faceMap;
List<surfacePatch> patchLst = surf.sortedRegions(faceMap);
// Write header
os << "OFF" << endl
<< "# Geomview OFF file written " << clock::dateTime().c_str() << nl
<< nl
<< "# points : " << pointLst.size() << nl
<< "# faces : " << faceLst.size() << nl
<< "# patches: " << patchLst.size() << nl;
// Print patch names as comment
forAll(patchLst, patchI)
{
os << "# " << patchI << " " << patchLst[patchI].name()
<< " (nFaces: " << patchLst[patchI].size() << ")" << nl;
}
os << nl
<< "# nPoints nFaces nEdges" << nl
<< pointLst.size() << ' ' << faceLst.size() << ' ' << 0 << nl;
os << nl
<< "# <points count=\"" << pointLst.size() << "\">" << endl;
// Write vertex coords
forAll(pointLst, ptI)
{
os << pointLst[ptI].x() << ' '
<< pointLst[ptI].y() << ' '
<< pointLst[ptI].z() << " #" << ptI << endl;
}
os << "# </points>" << nl
<< nl
<< "# <faces count=\"" << faceLst.size() << "\">" << endl;
label faceIndex = 0;
forAll(patchLst, patchI)
{
os << "# <patch name=\"" << patchLst[patchI].name() << "\">" << endl;
forAll(patchLst[patchI], patchFaceI)
{
const face& f = faceLst[faceMap[faceIndex++]];
os << f.size();
forAll(f, fp)
{
os << ' ' << f[fp];
}
// add optional region information
os << ' ' << patchI << endl;
}
os << "# </patch>" << endl;
}
os << "# </faces>" << endl;
}
void Foam::fileFormats::OFFfileFormat::write
(
Ostream& os,
const meshedSurface& surf
)
{
const pointField& pointLst = surf.points();
const List<face>& faceLst = surf.faces();
const List<surfacePatch>& patchLst = surf.patches();
// Write header
os << "OFF" << endl
<< "# Geomview OFF file written " << clock::dateTime().c_str() << nl
<< nl
<< "# points : " << pointLst.size() << nl
<< "# faces : " << faceLst.size() << nl
<< "# patches: " << patchLst.size() << nl;
// Print patch names as comment
forAll(patchLst, patchI)
{
os << "# " << patchI << " " << patchLst[patchI].name()
<< " (nFaces: " << patchLst[patchI].size() << ")" << nl;
}
os << nl
<< "# nPoints nFaces nEdges" << nl
<< pointLst.size() << ' ' << faceLst.size() << ' ' << 0 << nl;
os << nl
<< "# <points count=\"" << pointLst.size() << "\">" << endl;
// Write vertex coords
forAll(pointLst, ptI)
{
os << pointLst[ptI].x() << ' '
<< pointLst[ptI].y() << ' '
<< pointLst[ptI].z() << " #" << ptI << endl;
}
os << "# </points>" << nl
<< nl
<< "# <faces count=\"" << faceLst.size() << "\">" << endl;
label faceIndex = 0;
forAll(patchLst, patchI)
{
os << "# <patch name=\"" << patchLst[patchI].name() << "\">" << endl;
forAll(patchLst[patchI], patchFaceI)
{
const face& f = faceLst[faceIndex++];
os << f.size();
forAll(f, fp)
{
os << ' ' << f[fp];
}
// add optional region information
os << ' ' << patchI << endl;
}
os << "# </patch>" << endl;
}
os << "# </faces>" << endl;
}
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * Friend Functions * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
// ************************************************************************* //

View File

@ -0,0 +1,146 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 1991-2008 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::OFFfileFormat
Description
Provide a means of reading/writing Geomview OFF polyList format.
See Also
The <a href="http://www.geoview.org">Geoview</a>
file format information:
http://www.geomview.org/docs/html/OFF.html#OFF
Note
When reading, the optional @a colorspec is ignored.
When writing, it is set to the region number (integer).
SourceFiles
OFFfileFormat.C
\*---------------------------------------------------------------------------*/
#ifndef OFFfileFormat_H
#define OFFfileFormat_H
#include "Ostream.H"
#include "OFstream.H"
#include "keyedSurface.H"
#include "meshedSurface.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace fileFormats
{
/*---------------------------------------------------------------------------*\
Class OFFfileFormat Declaration
\*---------------------------------------------------------------------------*/
class OFFfileFormat
:
public keyedSurface
{
// Private Member Functions
//- Disallow default bitwise copy construct
OFFfileFormat(const OFFfileFormat&);
//- Disallow default bitwise assignment
void operator=(const OFFfileFormat&);
public:
// Constructors
//- Construct null
OFFfileFormat();
//- Construct from file name
OFFfileFormat(const fileName&, const bool triangulate=false);
// Selectors
//- Read file and return keyedSurface
static autoPtr<keyedSurface> New
(
const fileName& fName,
const bool triangulate=false
)
{
return autoPtr<keyedSurface>
(
new OFFfileFormat(fName,triangulate)
);
}
// Destructor
// Member Functions
// Write
//- Write keyedSurface
static void write(Ostream&, const keyedSurface&);
//- Write keyedSurface
static void write(const fileName& fName, const keyedSurface& surf)
{
write(OFstream(fName)(), surf);
}
//- Write meshedSurface
static void write(Ostream&, const meshedSurface&);
//- Write meshedSurface
static void write(const fileName& fName, const meshedSurface& surf)
{
write(OFstream(fName)(), surf);
}
//- Write object
virtual void write(Ostream& os) const
{
write(os, *this);
}
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace fileFormats
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,185 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 1991-2008 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 "SMESHfileFormat.H"
#include "clock.H"
#include "IStringStream.H"
#include "addToRunTimeSelectionTable.H"
#include "addToMemberFunctionSelectionTable.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
namespace fileFormats
{
addNamedToMemberFunctionSelectionTable
(
keyedSurface,
SMESHfileFormat,
write,
fileExtension,
smesh
);
addNamedToMemberFunctionSelectionTable
(
meshedSurface,
SMESHfileFormat,
write,
fileExtension,
smesh
);
}
}
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::fileFormats::SMESHfileFormat::SMESHfileFormat()
:
keyedSurface()
{}
// * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void
Foam::fileFormats::SMESHfileFormat::write
(
Ostream& os,
const keyedSurface& surf
)
{
const pointField& pointLst= surf.points();
const List<keyedFace>& faceLst = surf.faces();
labelList faceMap;
List<surfacePatch> patchLst = surf.sortedRegions(faceMap);
os << "# tetgen .smesh file written " << clock::dateTime().c_str() << nl;
os << "# <points count=\"" << pointLst.size() << "\">" << endl;
os << pointLst.size() << " 3" << nl; // 3: dimensions
// Write vertex coords
forAll(pointLst, ptI)
{
os << ptI
<< ' ' << pointLst[ptI].x()
<< ' ' << pointLst[ptI].y()
<< ' ' << pointLst[ptI].z() << nl;
}
os << "# </points>" << nl
<< nl
<< "# <faces count=\"" << faceLst.size() << "\">" << endl;
os << faceLst.size() << " 1" << endl; // one attribute: region number
label faceIndex = 0;
forAll(patchLst, patchI)
{
forAll(patchLst[patchI], patchFaceI)
{
const face& f = faceLst[faceMap[faceIndex++]];
os << f.size();
forAll(f, fp)
{
os << ' ' << f[fp];
}
os << ' ' << patchI << endl;
}
}
os << "# </faces>" << nl
<< nl
<< "# no holes or regions:" << nl
<< '0' << nl // holes
<< '0' << endl; // regions
}
void
Foam::fileFormats::SMESHfileFormat::write
(
Ostream& os,
const meshedSurface& surf
)
{
const pointField& pointLst= surf.points();
const List<face>& faceLst = surf.faces();
const List<surfacePatch>& patchLst = surf.patches();
os << "# tetgen .smesh file written " << clock::dateTime().c_str() << nl;
os << "# <points count=\"" << pointLst.size() << "\">" << endl;
os << pointLst.size() << " 3" << nl; // 3: dimensions
// Write vertex coords
forAll(pointLst, ptI)
{
os << ptI
<< ' ' << pointLst[ptI].x()
<< ' ' << pointLst[ptI].y()
<< ' ' << pointLst[ptI].z() << nl;
}
os << "# </points>" << nl
<< nl
<< "# <faces count=\"" << faceLst.size() << "\">" << endl;
os << faceLst.size() << " 1" << endl; // one attribute: region number
label faceIndex = 0;
forAll(patchLst, patchI)
{
forAll(patchLst[patchI], patchFaceI)
{
const face& f = faceLst[faceIndex++];
os << f.size();
forAll(f, fp)
{
os << ' ' << f[fp];
}
os << ' ' << patchI << endl;
}
}
os << "# </faces>" << nl
<< nl
<< "# no holes or regions:" << nl
<< '0' << nl // holes
<< '0' << endl; // regions
}
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * Friend Functions * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
// ************************************************************************* //

View File

@ -0,0 +1,128 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 1991-2008 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::SMESHfileFormat
Description
Provide a means of writing tetgen SMESH format.
Tetgen http://tetgen.berlios.de
See Also
File format information:
http://tetgen.berlios.de/fformats.smesh.html
SourceFiles
SMESHfileFormat.C
\*---------------------------------------------------------------------------*/
#ifndef SMESHfileFormat_H
#define SMESHfileFormat_H
#include "IFstream.H"
#include "OFstream.H"
#include "Ostream.H"
#include "keyedSurface.H"
#include "meshedSurface.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace fileFormats
{
/*---------------------------------------------------------------------------*\
Class SMESHfileFormat Declaration
\*---------------------------------------------------------------------------*/
class SMESHfileFormat
:
public keyedSurface
{
// Private data
// Private Member Functions
//- Disallow default bitwise copy construct
SMESHfileFormat(const SMESHfileFormat&);
//- Disallow default bitwise assignment
void operator=(const SMESHfileFormat&);
public:
// Constructors
//- Construct null
SMESHfileFormat();
// Selectors
// Destructor
// Member Functions
//- Write keyedSurface
static void write(Ostream&, const keyedSurface&);
//- Write meshedSurface
static void write(Ostream&, const meshedSurface&);
//- Write keyedSurface
static void write(const fileName& fName, const keyedSurface& surf)
{
write(OFstream(fName)(), surf);
}
//- Write meshedSurface
static void write(const fileName& fName, const meshedSurface& surf)
{
write(OFstream(fName)(), surf);
}
//- Write object
virtual void write(Ostream& os) const
{
write(os, *this);
}
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace fileFormats
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,478 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 1991-2008 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 "STARCDfileFormat.H"
#include "clock.H"
#include "OSspecific.H"
#include "IStringStream.H"
#include "addToRunTimeSelectionTable.H"
#include "addToMemberFunctionSelectionTable.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
namespace fileFormats
{
addNamedToRunTimeSelectionTable
(
keyedSurface,
STARCDfileFormat,
fileExtension,
inp
);
addNamedToMemberFunctionSelectionTable
(
keyedSurface,
STARCDfileFormat,
write,
fileExtension,
inp
);
addNamedToMemberFunctionSelectionTable
(
meshedSurface,
STARCDfileFormat,
write,
fileExtension,
inp
);
}
}
//! @cond localScope
const int starcdShellShape = 3;
const int starcdShellType = 4;
//! @endcond localScope
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
bool Foam::fileFormats::STARCDfileFormat::readHeader
(
IFstream& is,
const word& signature
)
{
if (!is.good())
{
FatalErrorIn("fileFormats::STARCDfileFormat::readHeader()")
<< "cannot read " << signature << " " << is.name()
<< abort(FatalError);
}
word header;
label majorVersion;
string line;
is.getLine(line);
IStringStream(line)() >> header;
is.getLine(line);
IStringStream(line)() >> majorVersion;
// add other checks ...
if (header != signature)
{
Info<< "header mismatch " << signature << " " << is.name()
<< endl;
}
return true;
}
void Foam::fileFormats::STARCDfileFormat::writeHeader
(
Ostream& os,
const char* filetype
)
{
os << "PROSTAR_" << filetype << nl
<< 4000
<< " " << 0
<< " " << 0
<< " " << 0
<< " " << 0
<< " " << 0
<< " " << 0
<< " " << 0
<< endl;
}
void Foam::fileFormats::STARCDfileFormat::writePoints
(
Ostream& os,
const pointField& pointLst
)
{
writeHeader(os, "VERTEX");
// Set the precision of the points data to 10
os.precision(10);
// force decimal point for Fortran input
os.setf(std::ios::showpoint);
forAll(pointLst, ptI)
{
os
<< ptI + 1 << " "
<< pointLst[ptI].x() << " "
<< pointLst[ptI].y() << " "
<< pointLst[ptI].z() << nl;
}
os.flush();
}
inline void Foam::fileFormats::STARCDfileFormat::writeShell
(
Ostream& os,
const face& f,
const label cellId,
const label cellTableId
)
{
os
<< cellId // includes 1 offset
<< " " << starcdShellShape // 3(shell)
<< " " << f.size()
<< " " << cellTableId
<< " " << starcdShellType; // 4(shell)
// primitives have <= 8 vertices, but prevent overrun anyhow
// indent following lines for ease of reading
label count = 0;
forAll(f, fp)
{
if ((count % 8) == 0)
{
os
<< nl
<< " " << cellId;
}
os << " " << f[fp] + 1;
count++;
}
os << endl;
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::fileFormats::STARCDfileFormat::STARCDfileFormat()
:
Foam::keyedSurface()
{}
// .vrt file format:
/*---------------------------------------------------------------------------*\
Line 1:
PROSTAR_VERTEX [newline]
Line 2:
<version> 0 0 0 0 0 0 0 [newline]
Body:
<vertexId> <x> <y> <z> [newline]
\*---------------------------------------------------------------------------*/
Foam::fileFormats::STARCDfileFormat::STARCDfileFormat
(
const fileName& fName,
const bool triangulation
)
:
Foam::keyedSurface()
{
fileName baseName = fName.lessExt();
autoPtr<IFstream> isPtr;
DynamicList<point> pointLst;
// STAR-CD index of points
DynamicList<label> pointId;
//
// read .vrt file
//
isPtr.reset(new IFstream(baseName + ".vrt"));
if (!isPtr().good())
{
FatalErrorIn
(
"fileFormats::STARCDfileFormat::STARCDfileFormat(const fileName&)"
)
<< "Cannot read file " << (baseName + ".vrt")
<< exit(FatalError);
}
readHeader(isPtr(), "PROSTAR_VERTEX");
label lineLabel;
while ((isPtr() >> lineLabel).good())
{
pointId.append(lineLabel);
scalar x, y, z;
isPtr() >> x >> y >> z;
pointLst.append(point(x, y, z));
}
// transfer to normal lists
points().transfer(pointLst);
// Build inverse mapping (index to point)
pointId.shrink();
Map<label> mapToFoamPointId(2*pointId.size());
forAll(pointId, i)
{
mapToFoamPointId.insert(pointId[i], i);
}
pointId.clear();
DynamicList<keyedFace> faceLst;
// From face cellTableId to patchId
Map<label> cellTableToPatchId;
label nPatches = 0;
//
// read .cel file
//
isPtr.reset(new IFstream(baseName + ".cel"));
if (!isPtr().good())
{
FatalErrorIn
(
"fileFormats::STARCDfileFormat::STARCDfileFormat(const fileName&)"
)
<< "Cannot read file " << (baseName + ".cel")
<< exit(FatalError);
}
readHeader(isPtr(), "PROSTAR_CELL");
label shapeId, nLabels, cellTableId, typeId;
labelList starLabels(64);
while ((isPtr() >> lineLabel).good())
{
isPtr() >> shapeId >> nLabels >> cellTableId >> typeId;
if (nLabels > starLabels.size())
{
starLabels.setSize(nLabels);
}
starLabels = -1;
// read indices - max 8 per line
for (label i = 0; i < nLabels; ++i)
{
if ((i % 8) == 0)
{
isPtr() >> lineLabel;
}
isPtr() >> starLabels[i];
}
if (typeId == starcdShellType)
{
// Convert groupID into patchID
Map<label>::const_iterator iter =
cellTableToPatchId.find(cellTableId);
label patchI;
if (iter == cellTableToPatchId.end())
{
patchI = nPatches++;
cellTableToPatchId.insert(cellTableId, patchI);
}
else
{
patchI = iter();
}
// convert orig vertex id to point label
for (label i=0; i < nLabels; ++i)
{
starLabels[i] = mapToFoamPointId[starLabels[i]];
}
if (triangulation && nLabels > 3)
{
face f
(
SubList<label>(starLabels, nLabels)
);
faceList triFaces(f.nTriangles(points()));
label nTri = 0;
f.triangles(points(), nTri, triFaces);
forAll(triFaces, faceI)
{
faceLst.append
(
keyedFace
(
triFaces[faceI],
patchI
)
);
}
}
else
{
faceLst.append
(
keyedFace
(
face(SubList<label>(starLabels, nLabels)),
patchI
)
);
}
}
}
mapToFoamPointId.clear();
// convert cellTable_N patchId => name
Map<word> regionNames;
forAllConstIter(Map<label>, cellTableToPatchId, iter)
{
regionNames.insert
(
iter(),
"cellTable_" + Foam::name(iter.key())
);
}
// transfer to normal lists
faces().transfer(faceLst);
setPatches(regionNames);
}
// * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::fileFormats::STARCDfileFormat::write
(
const fileName& fName,
const keyedSurface& surf
)
{
const List<keyedFace>& faceLst = surf.faces();
fileName baseName = fName.lessExt();
autoPtr<OFstream> osPtr;
osPtr.reset(new OFstream(baseName + ".vrt"));
writePoints(osPtr(), surf.points());
labelList faceMap;
List<surfacePatch> patchLst = surf.sortedRegions(faceMap);
osPtr.reset(new OFstream(baseName + ".cel"));
writeHeader(osPtr(), "CELL");
label faceIndex = 0;
forAll(patchLst, patchI)
{
const surfacePatch& patch = patchLst[patchI];
forAll(patch, patchFaceI)
{
const face& f = faceLst[faceMap[faceIndex++]];
writeShell(osPtr(), f, faceIndex, patchI + 1);
}
}
}
void Foam::fileFormats::STARCDfileFormat::write
(
const fileName& fName,
const meshedSurface& surf
)
{
const List<face>& faceLst = surf.faces();
const List<surfacePatch>& patchLst = surf.patches();
fileName baseName = fName.lessExt();
autoPtr<OFstream> osPtr;
osPtr.reset(new OFstream(baseName + ".vrt"));
writePoints(osPtr(), surf.points());
osPtr.reset(new OFstream(baseName + ".cel"));
writeHeader(osPtr(), "CELL");
label faceIndex = 0;
forAll(patchLst, patchI)
{
const surfacePatch& patch = patchLst[patchI];
forAll(patch, patchFaceI)
{
const face& f = faceLst[faceIndex++];
writeShell(osPtr(), f, faceIndex, patchI + 1);
}
}
}
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * Friend Functions * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
// ************************************************************************* //

View File

@ -0,0 +1,149 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 1991-2008 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::STARCDfileFormat
Description
Read/write the surface shells from pro-STAR vrt/cel files.
Note
Uses the extension @a .inp (input) to denote the format.
See Also
Foam::meshReaders::STARCD
SourceFiles
STARCDfileFormat.C
\*---------------------------------------------------------------------------*/
#ifndef STARCDfileFormat_H
#define STARCDfileFormat_H
#include "STLtriangle.H"
#include "IFstream.H"
#include "Ostream.H"
#include "OFstream.H"
#include "keyedSurface.H"
#include "meshedSurface.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace fileFormats
{
/*---------------------------------------------------------------------------*\
Class STARCDfileFormat Declaration
\*---------------------------------------------------------------------------*/
class STARCDfileFormat
:
public keyedSurface
{
// Private data
// Private Member Functions
//- Disallow default bitwise copy construct
STARCDfileFormat(const STARCDfileFormat&);
//- Disallow default bitwise assignment
void operator=(const STARCDfileFormat&);
static bool readHeader(IFstream&, const word&);
static void writeHeader(Ostream&, const char* filetype);
static void writePoints(Ostream&, const pointField&);
static inline void writeShell
(
Ostream&,
const face&,
const label cellId,
const label cellTableId
);
public:
// Constructors
//- Construct null
STARCDfileFormat();
//- Construct from file name
STARCDfileFormat(const fileName&, const bool triangulate=true);
// Selectors
//- Read file and return keyedSurface
static autoPtr<keyedSurface> New
(
const fileName& fName,
const bool triangulate=true
)
{
return autoPtr<keyedSurface>
(
new STARCDfileFormat(fName, triangulate)
);
}
// Destructor
// Member Functions
// Write
//- Write keyedSurface
static void write(const fileName&, const keyedSurface&);
//- Write meshedSurface
static void write(const fileName&, const meshedSurface&);
//- Write to Ostream as one large file - not really useful
virtual void write(Ostream&) const
{
notImplemented("fileFormats::STARCDfileFormat::write(Ostream&)");
}
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace fileFormats
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,590 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 1991-2008 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 "STLfileFormat.H"
#include "clock.H"
#include "OSspecific.H"
#include "addToRunTimeSelectionTable.H"
#include "addToMemberFunctionSelectionTable.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
namespace fileFormats
{
addNamedToRunTimeSelectionTable
(
keyedSurface,
STLfileFormat,
fileExtension,
stl
);
addNamedToRunTimeSelectionTable
(
keyedSurface,
STLfileFormat,
fileExtension,
stlb
);
addNamedToMemberFunctionSelectionTable
(
keyedSurface,
STLfileFormat,
write,
fileExtension,
stl
);
addNamedToMemberFunctionSelectionTable
(
keyedSurface,
STLfileFormat,
write,
fileExtension,
stlb
);
addNamedToMemberFunctionSelectionTable
(
meshedSurface,
STLfileFormat,
write,
fileExtension,
stl
);
addNamedToMemberFunctionSelectionTable
(
meshedSurface,
STLfileFormat,
write,
fileExtension,
stlb
);
}
}
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
// check binary by getting the header and number of facets
// this seems to work better than the old token-based method
// - some programs (eg, pro-STAR) have 'solid' as the first word in
// the binary header.
// - using wordToken can cause an abort if non-word (binary) content
// is detected ... this is not exactly what we want.
bool Foam::fileFormats::STLfileFormat::detectBINARY
(
const fileName& fName
)
{
off_t fileSize = Foam::size(fName);
IFstream ifs(fName, IOstream::BINARY);
istream& is = ifs.stdStream();
// Read the STL header
char header[headerSize];
is.read(header, headerSize);
// Check that stream is OK, if not this may be an ASCII file
if (!is.good())
{
return false;
}
// Read the number of triangles in the STl file
// (note: read as int so we can check whether >2^31)
int nTris;
is.read(reinterpret_cast<char*>(&nTris), sizeof(unsigned int));
// Check that stream is OK and number of triangles is positive,
// if not this maybe an ASCII file
//
// Also compare the file size with that expected from the number of tris
// If the comparison is not sensible then it may be an ASCII file
if
(
!is
|| nTris < 0
|| nTris < (fileSize - headerSize)/50
|| nTris > (fileSize - headerSize)/25
)
{
return false;
}
// looks like it might be BINARY
return true;
}
#undef DEBUG_STLBINARY
bool Foam::fileFormats::STLfileFormat::readBINARY
(
IFstream& ifs,
const off_t fileSize
)
{
istream& is = ifs.stdStream();
// Read the STL header
char header[headerSize];
is.read(header, headerSize);
// Check that stream is OK, if not this may be an ASCII file
if (!is.good())
{
FatalErrorIn("fileFormats::STLfileFormat::readBINARY(Istream&)")
<< "problem reading header, perhaps file is not binary "
<< exit(FatalError);
}
// Read the number of triangles in the STl file
// (note: read as int so we can check whether >2^31)
int nTris;
is.read(reinterpret_cast<char*>(&nTris), sizeof(unsigned int));
// Check that stream is OK and number of triangles is positive,
// if not this maybe an ASCII file
//
// Also compare the file size with that expected from the number of tris
// If the comparison is not sensible then it may be an ASCII file
if
(
!is
|| nTris < 0
|| nTris < (fileSize - headerSize)/50
|| nTris > (fileSize - headerSize)/25
)
{
FatalErrorIn("fileFormats::STLfileFormat::readBINARY(Istream&)")
<< "problem reading number of triangles, perhaps file is not binary"
<< exit(FatalError);
}
#ifdef DEBUG_STLBINARY
Info<< "# " << nTris << " facets" << endl;
label prevRegion = -1;
#endif
pointField pointLst(3*nTris);
List<keyedFace> faceLst(nTris);
label maxRegionId = 0;
label pointI = 0;
forAll(faceLst, faceI)
{
// Read an STL triangle
STLtriangle stlTri(is);
// Set the rawPoints to the vertices of the STL triangle
// and set the point labels of the face
face f(3);
pointLst[pointI] = stlTri.a();
f[0] = pointI++;
pointLst[pointI] = stlTri.b();
f[1] = pointI++;
pointLst[pointI] = stlTri.c();
f[2] = pointI++;
if (maxRegionId < stlTri.region())
{
maxRegionId = stlTri.region();
}
// interprete colour as a region
faceLst[faceI] = keyedFace(f, stlTri.region());
#ifdef DEBUG_STLBINARY
if
(
prevRegion != stlTri.region()
)
{
if (prevRegion != -1)
{
Info<< "endsolid region" << prevRegion << nl;
}
prevRegion = stlTri.region();
Info<< "solid region" << prevRegion << nl;
}
Info<< " facet normal " << stlTri.normal() << nl;
Info<< " outer loop" << nl;
Info<< " vertex " << stlTri.a() << nl;
Info<< " vertex " << stlTri.b() << nl;
Info<< " vertex " << stlTri.c() << nl;
Info<< " outer loop" << nl;
Info<< " endfacet" << endl;
#endif
}
#ifdef DEBUG_STLBINARY
Info<< "endsolid region" << prevRegion << nl;
#endif
points().transfer(pointLst);
faces().transfer(faceLst);
setPatches(maxRegionId);
stitchFaces(SMALL);
return true;
}
inline void Foam::fileFormats::STLfileFormat::writeShell
(
Ostream& os,
const pointField& pointLst,
const face& f,
const vector& norm
)
{
// simple triangulation about f[0].
// better triangulation should have been done before
const point& p0 = pointLst[f[0]];
for (label fp1 = 1; fp1 < f.size() - 1; ++fp1)
{
label fp2 = (fp1 + 1) % f.size();
const point& p1 = pointLst[f[fp1]];
const point& p2 = pointLst[f[fp2]];
// write STL triangle
os << " facet normal "
<< norm.x() << ' ' << norm.y() << ' ' << norm.z() << nl
<< " outer loop\n"
<< " vertex "
<< p0.x() << ' ' << p0.y() << ' ' << p0.z() << nl
<< " vertex "
<< p1.x() << ' ' << p1.y() << ' ' << p1.z() << nl
<< " vertex "
<< p2.x() << ' ' << p2.y() << ' ' << p2.z() << nl
<< " endloop\n"
<< " endfacet" << endl;
}
}
inline void Foam::fileFormats::STLfileFormat::writeShell
(
ostream& os,
const pointField& pointLst,
const face& f,
const vector& norm,
const label patchI
)
{
// simple triangulation about f[0].
// better triangulation should have been done before
const point& p0 = pointLst[f[0]];
for (label fp1 = 1; fp1 < f.size() - 1; ++fp1)
{
label fp2 = (fp1 + 1) % f.size();
STLtriangle stlTri
(
norm,
p0,
pointLst[f[fp1]],
pointLst[f[fp2]],
patchI
);
stlTri.write(os);
}
}
// write sorted:
void Foam::fileFormats::STLfileFormat::writeASCII
(
Ostream& os,
const keyedSurface& surf
)
{
const pointField& pointLst = surf.points();
const List<keyedFace>& faceLst = surf.faces();
const vectorField& normLst = surf.faceNormals();
labelList faceMap;
List<surfacePatch> patchLst = surf.sortedRegions(faceMap);
label faceIndex = 0;
forAll(patchLst, patchI)
{
// Print all faces belonging to this region
const surfacePatch& patch = patchLst[patchI];
os << "solid " << patch.name() << endl;
forAll(patch, patchFaceI)
{
const label faceI = faceMap[faceIndex++];
writeShell(os, pointLst, faceLst[faceI], normLst[faceI]);
}
os << "endsolid " << patch.name() << endl;
}
}
// write sorted:
void Foam::fileFormats::STLfileFormat::writeASCII
(
Ostream& os,
const meshedSurface& surf
)
{
const pointField& pointLst = surf.points();
const List<face>& faceLst = surf.faces();
const List<surfacePatch>& patchLst = surf.patches();
const vectorField& normLst = surf.faceNormals();
// force triangulation, but just do the cheapest form possible
label faceIndex = 0;
forAll(patchLst, patchI)
{
// Print all faces belonging to this region
const surfacePatch& patch = patchLst[patchI];
os << "solid " << patch.name() << endl;
forAll(patch, patchFaceI)
{
const label faceI = faceIndex++;
writeShell(os, pointLst, faceLst[faceI], normLst[faceI]);
}
os << "endsolid " << patch.name() << endl;
}
}
// write unsorted:
void Foam::fileFormats::STLfileFormat::writeBINARY
(
ostream& os,
const keyedSurface& surf
)
{
const pointField& pointLst = surf.points();
const List<keyedFace>& faceLst = surf.faces();
const vectorField& normLst = surf.faceNormals();
// Write the STL header
string header("STL binary file", headerSize);
// clear possible trailing junk
for (label i = header.size(); i < headerSize; ++i)
{
header[i] = 0;
}
os.write(header.c_str(), headerSize);
// force triangulation, but just do the cheapest form possible
unsigned int nTris = 0;
forAll(faceLst, faceI)
{
nTris += faceLst[faceI].size() - 2;
}
os.write(reinterpret_cast<char*>(&nTris), sizeof(unsigned int));
forAll(faceLst, faceI)
{
writeShell
(
os,
pointLst,
faceLst[faceI],
normLst[faceI],
faceLst[faceI].key()
);
}
}
void Foam::fileFormats::STLfileFormat::writeBINARY
(
ostream& os,
const meshedSurface& surf
)
{
const pointField& pointLst = surf.points();
const List<face>& faceLst = surf.faces();
const surfacePatchList& patchLst = surf.patches();
const vectorField& normLst = surf.faceNormals();
// Write the STL header
string header("STL binary file", headerSize);
os.write(header.c_str(), headerSize);
// force triangulation, but just do the cheapest form possible
unsigned int nTris = 0;
forAll(faceLst, faceI)
{
nTris += faceLst[faceI].size() - 2;
}
os.write(reinterpret_cast<char*>(&nTris), sizeof(unsigned int));
label faceIndex = 0;
forAll(patchLst, patchI)
{
forAll(patchLst[patchI], patchFaceI)
{
writeShell
(
os,
pointLst,
faceLst[faceIndex],
normLst[faceIndex],
patchI
);
++faceIndex;
}
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::fileFormats::STLfileFormat::STLfileFormat()
:
Foam::keyedSurface()
{}
Foam::fileFormats::STLfileFormat::STLfileFormat
(
const fileName& fName,
const bool
)
:
Foam::keyedSurface()
{
off_t fileSize = Foam::size(fName);
// auto-detect ascii/binary
if (detectBINARY(fName))
{
readBINARY(IFstream(fName, IOstream::BINARY)(), fileSize);
}
else
{
readASCII(IFstream(fName)(), fileSize);
}
}
// * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::fileFormats::STLfileFormat::write
(
Ostream& os,
const keyedSurface& surf
)
{
writeASCII(os, surf);
}
void Foam::fileFormats::STLfileFormat::write
(
Ostream& os,
const meshedSurface& surf
)
{
writeASCII(os, surf);
}
void Foam::fileFormats::STLfileFormat::write
(
const fileName& fName,
const keyedSurface& surf
)
{
const word ext = fName.ext();
// handle 'stlb' as binary directly
if (ext == "stlb")
{
std::ofstream ofs(fName.c_str(), std::ios::binary);
writeBINARY(ofs, surf);
}
else
{
writeASCII(OFstream(fName)(), surf);
}
}
void Foam::fileFormats::STLfileFormat::write
(
const fileName& fName,
const meshedSurface& surf
)
{
const word ext = fName.ext();
// handle 'stlb' as binary directly
if (ext == "stlb")
{
std::ofstream ofs(fName.c_str(), std::ios::binary);
writeBINARY(ofs, surf);
}
else
{
writeASCII(OFstream(fName)(), surf);
}
}
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * Friend Functions * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
// ************************************************************************* //

View File

@ -0,0 +1,177 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 1991-2008 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::STLfileFormat
Description
Provide a means of reading/writing STL files (ASCII and binary).
SourceFiles
STLfileFormat.C
STLfileFormatASCII.L
\*---------------------------------------------------------------------------*/
#ifndef STLfileFormat_H
#define STLfileFormat_H
#include "STLtriangle.H"
#include "IFstream.H"
#include "Ostream.H"
#include "OFstream.H"
#include "keyedSurface.H"
#include "meshedSurface.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace fileFormats
{
/*---------------------------------------------------------------------------*\
Class STLfileFormat Declaration
\*---------------------------------------------------------------------------*/
class STLfileFormat
:
public keyedSurface
{
// Private data
//- The number of bytes in the STL binary header
static const int headerSize=80;
// Private Member Functions
//- Disallow default bitwise copy construct
STLfileFormat(const STLfileFormat&);
//- Disallow default bitwise assignment
void operator=(const STLfileFormat&);
bool detectBINARY(const fileName&);
bool readASCII(IFstream&, const off_t);
bool readBINARY(IFstream&, const off_t);
//- write face in ASCII
static inline void writeShell
(
Ostream&,
const pointField&,
const face&,
const vector& norm
);
//- write face in BINARY
static inline void writeShell
(
ostream&,
const pointField&,
const face&,
const vector&,
const label patchI
);
//- Write keySurface
static void writeASCII(Ostream&, const keyedSurface&);
//- Write keyedSurface
static void writeBINARY(ostream&, const keyedSurface&);
//- Write meshedSurface
static void writeASCII(Ostream&, const meshedSurface&);
//- Write meshedSurface
static void writeBINARY(ostream&, const meshedSurface&);
public:
// Constructors
//- Construct null
STLfileFormat();
//- Construct from file name
STLfileFormat(const fileName&, const bool triangulate=true);
// Selectors
//- Read file and return keyedSurface
static autoPtr<keyedSurface> New
(
const fileName& fName,
const bool triangulate=true
)
{
return autoPtr<keyedSurface>
(
new STLfileFormat(fName,triangulate)
);
}
// Destructor
// Member Functions
// Write
//- Write keyedSurface
// The ASCII output is sorted by patch, the binary output is unsorted
static void write(Ostream&, const keyedSurface&);
//- Write keyedSurface
// The ASCII output is sorted by patch, the binary output is unsorted
static void write(const fileName&, const keyedSurface&);
//- Write meshedSurface
static void write(Ostream&, const meshedSurface&);
//- Write meshedSurface
static void write(const fileName&, const meshedSurface&);
//- Write object
virtual void write(Ostream& os) const
{
write(os, *this);
}
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace fileFormats
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,426 @@
/*--------------------------------*- C++ -*----------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 1991-2008 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
\*---------------------------------------------------------------------------*/
%{
#undef yyFlexLexer
/* ------------------------------------------------------------------------ *\
------ local definitions
\* ------------------------------------------------------------------------ */
#include "STLfileFormat.H"
using namespace Foam;
// Dummy yyFlexLexer::yylex() to keep the linker happy. It is not called
//! @cond dummy
int yyFlexLexer::yylex()
{
FatalErrorIn("yyFlexLexer::yylex()")
<< "Should not have called this function"
<< abort(FatalError);
return 0;
}
//! @endcond dummy
// Dummy yywrap to keep yylex happy at compile time.
// It is called by yylex but is not used as the mechanism to change file.
// See <<EOF>>
//! @cond dummy
#if YY_FLEX_SUBMINOR_VERSION < 34
extern "C" int yywrap()
#else
int yyFlexLexer::yywrap()
#endif
{
return 1;
}
//! @endcond dummy
//- A lexer for parsing STL ASCII files.
// Returns DynamicList(s) of points and facets (regionIds).
// Since the facets appear within a solid/endsolid grouping,
// they are always within a region
class STLASCIILexer
:
public yyFlexLexer
{
// Private data
short groupID_; // current region
short maxGroupID_; // max region
label lineNo_;
word startError_;
DynamicList<point> points_;
DynamicList<label> facets_;
HashTable<label> groupToPatch_;
public:
// Constructors
//- From input stream and the approximate number of vertices in the STL
STLASCIILexer(istream* is, const label approxNpoints);
// Member Functions
//- The lexer function itself
int lex();
// Access
//- A list of points corresponding to a pointField
DynamicList<point>& points()
{
return points_;
}
//- A list of facet IDs (region IDs)
// corresponds to the number of triangles
DynamicList<label>& facets()
{
return facets_;
}
//- region names
const HashTable<label>& groupToPatch() const
{
return groupToPatch_;
}
};
STLASCIILexer::STLASCIILexer(istream* is, const label approxNpoints)
:
yyFlexLexer(is),
groupID_(-1),
maxGroupID_(-1),
lineNo_(1),
points_(approxNpoints),
facets_(approxNpoints)
{}
/* ------------------------------------------------------------------------ *\
------ cppLexer::yylex()
\* ------------------------------------------------------------------------ */
#define YY_DECL int STLASCIILexer::lex()
%}
one_space [ \t\f\r]
space {one_space}*
some_space {one_space}+
cspace ","{space}
alpha [_A-Za-z]
digit [0-9]
dec_digit [0-9]
octal_digit [0-7]
hex_digit [0-9a-fA-F]
identifier {alpha}({alpha}|{digit})*
integer {dec_digit}+
label [1-9]{dec_digit}*
zeroLabel {digit}*
signedInteger [-+]?{integer}
word ([[:alnum:]]|[[:punct:]])*
string {word}({some_space}{word})*
exponent_part [eE][-+]?{digit}+
fractional_constant [-+]?(({digit}*"."{digit}+)|({digit}+"."?))
double (({fractional_constant}{exponent_part}?)|({digit}+{exponent_part}))
float {double}
x {float}
y {float}
z {float}
solid {space}("solid"|"SOLID"){space}
color {space}("color"|"COLOR"){some_space}{float}{some_space}{float}{some_space}{float}{space}
facet {space}("facet"|"FACET"){space}
normal {space}("normal"|"NORMAL"){space}
point {space}{x}{some_space}{y}{some_space}{z}{space}
outerloop {space}("outer"{some_space}"loop")|("OUTER"{some_space}"LOOP"){space}
vertex {space}("vertex"|"VERTEX"){space}
endloop {space}("endloop"|"ENDLOOP"){space}
endfacet {space}("endfacet"|"ENDFACET"){space}
endsolid {space}("endsolid"|"ENDSOLID")({some_space}{word})*
/* ------------------------------------------------------------------------ *\
----- Exclusive start states -----
\* ------------------------------------------------------------------------ */
%option stack
%x readSolidName
%x readFacet
%x readNormal
%x readVertices
%x readVertex
%x stlError
%%
%{
// End of read character pointer returned by strtof
// char* endPtr;
STLpoint normal;
STLpoint vertex;
label cmpt = 0; // component index used for reading vertex
static const char* stateNames[7] =
{
"reading solid",
"reading solid name",
"reading facet",
"reading normal",
"reading vertices",
"reading vertex",
"error"
};
static const char* stateExpects[7] =
{
"'solid', 'color', 'facet' or 'endsolid'",
"<string>",
"'normal', 'outer loop' or 'endfacet'",
"<float> <float> <float>",
"'vertex' or 'endloop'",
"<float> <float> <float>",
""
};
%}
/* ------------------------------------------------------------------------ *\
------ Start Lexing ------
\* ------------------------------------------------------------------------ */
/* ------ Reading control header ------ */
{solid} {
BEGIN(readSolidName);
}
<readSolidName>{string} {
word group(Foam::string::validate<word>(YYText()));
HashTable<label>::const_iterator findGroup =
groupToPatch_.find(group);
if (findGroup != groupToPatch_.end())
{
groupID_ = findGroup();
}
else
{
groupID_ = ++maxGroupID_;
groupToPatch_.insert(group, groupID_);
}
BEGIN(INITIAL);
}
<readSolidName>{space}\n {
word group("solid");
HashTable<label>::const_iterator findGroup =
groupToPatch_.find(group);
if (findGroup != groupToPatch_.end())
{
groupID_ = findGroup();
}
else
{
groupID_ = ++maxGroupID_;
groupToPatch_.insert(group, groupID_);
}
lineNo_++;
BEGIN(INITIAL);
}
{color} {
}
{facet} {
BEGIN(readFacet);
}
<readFacet>{normal} {
BEGIN(readNormal);
}
<readNormal>{point} {
/*
skip reading normals:
normal.x() = strtof(YYText(), &endPtr);
normal.y() = strtof(endPtr, &endPtr);
normal.z() = strtof(endPtr, &endPtr);
normals_.append(normal);
*/
BEGIN(readFacet);
}
<readFacet>{outerloop} {
BEGIN(readVertices);
}
<readVertices>{vertex} {
BEGIN(readVertex);
}
<readVertex>{space}{signedInteger}{space} {
vertex[cmpt++] = atol(YYText());
if (cmpt == 3)
{
cmpt = 0;
points_.append(vertex);
BEGIN(readVertices);
}
}
<readVertex>{space}{float}{space} {
vertex[cmpt++] = atof(YYText());
if (cmpt == 3)
{
cmpt = 0;
points_.append(vertex);
BEGIN(readVertices);
}
}
<readVertices>{endloop} {
BEGIN(readFacet);
}
<readFacet>{endfacet} {
facets_.append(groupID_);
BEGIN(INITIAL);
}
{endsolid} {
}
/* ------------------ Ignore remaining space and \n s. -------------------- */
<*>{space} {}
<*>\n { lineNo_++; }
/* ------------------- Any other characters are errors -------------------- */
<*>. {
startError_ = YYText();
yy_push_state(stlError);
}
/* ---------------------------- Error handler ----------------------------- */
<stlError>.* {
yy_pop_state();
FatalErrorIn
(
"fileFormats::STLfileFormat::readASCII(const fileName& STLfileName)"
) << "while " << stateNames[YY_START] << " on line " << lineNo_ << nl
<< " expected " << stateExpects[YY_START]
<< " but found '" << startError_.c_str() << YYText() << "'"
<< exit(FatalError);
}
/* ------------------------ On EOF terminate ---------------------------- */
<<EOF>> {
yyterminate();
}
%%
//
// member function
//
bool
Foam::fileFormats::STLfileFormat::readASCII
(
IFstream& ifs,
const off_t fileSize
)
{
// Create the lexer with the approximate number of vertices in the STL
// from the file size
STLASCIILexer lexer(&ifs.stdStream(), fileSize/400);
while (lexer.lex() != 0) {}
DynamicList<point>& pointLst = lexer.points();
DynamicList<label>& facetsLst = lexer.facets();
// transfer to normal list
points().transfer(pointLst);
// make our triangles
facetsLst.shrink();
List<keyedFace> faceLst(facetsLst.size());
face fTri(3);
label ptI = 0;
forAll(facetsLst, faceI)
{
fTri[0] = ptI++;
fTri[1] = ptI++;
fTri[2] = ptI++;
faceLst[faceI] = keyedFace(fTri, facetsLst[faceI]);
}
facetsLst.clearStorage();
// transfer to normal list
faces().transfer(faceLst);
setPatches(lexer.groupToPatch());
stitchFaces(SMALL);
return true;
}
/* ------------------------------------------------------------------------ *\
------ End of STLfileFormatASCII.L
\* ------------------------------------------------------------------------ */

View File

@ -0,0 +1,93 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 1991-2008 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::STLpoint
Description
A vertex point representation for STL files.
SourceFiles
STLpointI.H
\*---------------------------------------------------------------------------*/
#ifndef STLpoint_H
#define STLpoint_H
#include "point.H"
#include "Istream.H"
#include "Ostream.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class STLpoint Declaration
\*---------------------------------------------------------------------------*/
class STLpoint
:
public Vector<float>
{
public:
// Constructors
//- Construct null
inline STLpoint();
//- Construct from components
inline STLpoint(float x, float y, float z);
//- Construct from point
inline STLpoint(const point&);
//- Construct from istream
inline STLpoint(Istream&);
// Member Operators
inline operator point() const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#include "STLpointI.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,60 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 1991-2008 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
\*---------------------------------------------------------------------------*/
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
inline Foam::STLpoint::STLpoint()
{}
inline Foam::STLpoint::STLpoint(float x, float y, float z)
:
Vector<float>(x, y, z)
{}
inline Foam::STLpoint::STLpoint(const point& pt)
:
Vector<float>(float(pt.x()), float(pt.y()), float(pt.z()))
{}
inline Foam::STLpoint::STLpoint(Istream& is)
:
Vector<float>(is)
{}
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
inline Foam::STLpoint::operator point() const
{
return point(x(), y(), z());
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// ************************************************************************* //

View File

@ -0,0 +1,122 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 1991-2008 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::STLtriangle
Description
A triangle representation for STL files.
SourceFiles
STLtriangleI.H
\*---------------------------------------------------------------------------*/
#ifndef STLtriangle_H
#define STLtriangle_H
#include "STLpoint.H"
#include "Istream.H"
#include "Ostream.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class STLtriangle Declaration
\*---------------------------------------------------------------------------*/
class STLtriangle
{
// Private data
typedef unsigned short STLregion;
STLpoint normal_, a_, b_, c_;
STLregion region_;
public:
// Constructors
//- Construct null
inline STLtriangle();
//- Construct from components
inline STLtriangle
(
const STLpoint& normal,
const STLpoint& a,
const STLpoint& b,
const STLpoint& c,
unsigned short region
);
//- Construct from istream (read binary)
inline STLtriangle(istream&);
// Member Functions
// Access
inline const STLpoint& normal() const;
inline const STLpoint& a() const;
inline const STLpoint& b() const;
inline const STLpoint& c() const;
inline unsigned short region() const;
// Read
//- Read from istream (binary)
inline void read(istream&);
// Write
//- Write to ostream (binary)
inline void write(ostream&);
// Ostream operator
inline friend Ostream& operator<<(Ostream&, const STLtriangle&);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#include "STLtriangleI.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,115 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 1991-2008 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
\*---------------------------------------------------------------------------*/
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
inline Foam::STLtriangle::STLtriangle()
{}
inline Foam::STLtriangle::STLtriangle
(
const STLpoint& normal,
const STLpoint& a,
const STLpoint& b,
const STLpoint& c,
unsigned short region
)
:
normal_(normal),
a_(a),
b_(b),
c_(c),
region_(region)
{}
inline Foam::STLtriangle::STLtriangle(istream& is)
{
read(is);
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
inline const Foam::STLpoint& Foam::STLtriangle::normal() const
{
return normal_;
}
inline const Foam::STLpoint& Foam::STLtriangle::a() const
{
return a_;
}
inline const Foam::STLpoint& Foam::STLtriangle::b() const
{
return b_;
}
inline const Foam::STLpoint& Foam::STLtriangle::c() const
{
return c_;
}
inline unsigned short Foam::STLtriangle::region() const
{
return region_;
}
inline void Foam::STLtriangle::read(istream& is)
{
is.read(reinterpret_cast<char*>(this), 4*sizeof(STLpoint));
is.read(reinterpret_cast<char*>(&region_), sizeof(STLregion));
}
inline void Foam::STLtriangle::write(ostream& os)
{
os.write(reinterpret_cast<char*>(this), 4*sizeof(STLpoint));
os.write(reinterpret_cast<char*>(&region_), sizeof(STLregion));
}
// * * * * * * * * * * * * * * * Ostream Operator * * * * * * * * * * * * * //
inline Foam::Ostream& Foam::operator<<(Ostream& os, const STLtriangle& t)
{
os << t.normal_ << token::SPACE
<< t.a_ << token::SPACE
<< t.b_ << token::SPACE
<< t.c_ << token::SPACE
<< t.region_;
return os;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// ************************************************************************* //

View File

@ -0,0 +1,287 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 1991-2008 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 "TRIfileFormat.H"
#include "clock.H"
#include "IFstream.H"
#include "IOmanip.H"
#include "IStringStream.H"
#include "addToRunTimeSelectionTable.H"
#include "addToMemberFunctionSelectionTable.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
namespace fileFormats
{
addNamedToRunTimeSelectionTable
(
keyedSurface,
TRIfileFormat,
fileExtension,
tri
);
addNamedToMemberFunctionSelectionTable
(
keyedSurface,
TRIfileFormat,
write,
fileExtension,
tri
);
addNamedToMemberFunctionSelectionTable
(
meshedSurface,
TRIfileFormat,
write,
fileExtension,
tri
);
}
}
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
inline void Foam::fileFormats::TRIfileFormat::writeShell
(
Ostream& os,
const pointField& pointLst,
const face& f,
const label patchI
)
{
// simple triangulation about f[0].
// better triangulation should have been done before
const point& p0 = pointLst[f[0]];
for (label fp1 = 1; fp1 < f.size() - 1; ++fp1)
{
label fp2 = (fp1 + 1) % f.size();
const point& p1 = pointLst[f[fp1]];
const point& p2 = pointLst[f[fp2]];
os << p0.x() << ' ' << p0.y() << ' ' << p0.z() << ' '
<< p1.x() << ' ' << p1.y() << ' ' << p1.z() << ' '
<< p2.x() << ' ' << p2.y() << ' ' << p2.z() << ' '
// region as colour
<< "0x" << hex << patchI << dec << endl;
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::fileFormats::TRIfileFormat::TRIfileFormat()
:
Foam::keyedSurface()
{}
Foam::fileFormats::TRIfileFormat::TRIfileFormat
(
const fileName& fName,
const bool triangulate
)
:
Foam::keyedSurface()
{
IFstream is(fName);
if (!is.good())
{
FatalErrorIn("fileFormats::TRIfileFormat(const fileName&)")
<< "Cannot read file " << fName
<< exit(FatalError);
}
// uses similar structure as STL, just some points
DynamicList<point> pointLst;
DynamicList<label> facetsLst;
HashTable<label> groupToPatch;
// leave faces that didn't have a group in 0
label nUngrouped = 0;
label groupID = 0;
label maxGroupID = -1;
while (is.good())
{
string line = getLineNoComment(is);
// handle continuations ?
// if (line[line.size()-1] == '\\')
// {
// line.substr(0, line.size()-1);
// line += getLineNoComment(is);
// }
IStringStream lineStream(line);
point p
(
readScalar(lineStream),
readScalar(lineStream),
readScalar(lineStream)
);
if (!lineStream) break;
pointLst.append(p);
pointLst.append
(
point
(
readScalar(lineStream),
readScalar(lineStream),
readScalar(lineStream)
)
);
pointLst.append
(
point
(
readScalar(lineStream),
readScalar(lineStream),
readScalar(lineStream)
)
);
// Region/colour in .tri file starts with 0x. Skip.
// ie, instead of having 0xFF, skip 0 and leave xFF to
// get read as a word and name it "patchFF"
char zero;
lineStream >> zero;
word rawName(lineStream);
word groupName("patch" + rawName(1, rawName.size()-1));
HashTable<label>::const_iterator findGroup =
groupToPatch.find(groupName);
if (findGroup != groupToPatch.end())
{
groupID = findGroup();
}
else
{
// special treatment if any initial faces were not in a group
if (maxGroupID == -1 && facetsLst.size())
{
groupToPatch.insert("patch0", 0);
nUngrouped = facetsLst.size();
maxGroupID = 0;
}
groupID = ++maxGroupID;
groupToPatch.insert(groupName, groupID);
}
facetsLst.append(groupID);
}
// transfer to normal list
points().transfer(pointLst);
// make our triangles
facetsLst.shrink();
List<keyedFace> faceLst(facetsLst.size());
face fTri(3);
label ptI = 0;
forAll(facetsLst, faceI)
{
fTri[0] = ptI++;
fTri[1] = ptI++;
fTri[2] = ptI++;
faceLst[faceI] = keyedFace(fTri, facetsLst[faceI]);
}
facetsLst.clearStorage();
faces().transfer(faceLst);
setPatches(groupToPatch);
stitchFaces(SMALL);
}
// * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::fileFormats::TRIfileFormat::write
(
Ostream& os,
const keyedSurface& surf
)
{
const pointField& pointLst = surf.points();
const List<keyedFace>& faceLst = surf.faces();
labelList faceMap;
List<surfacePatch> patchLst = surf.sortedRegions(faceMap);
label faceIndex = 0;
forAll(patchLst, patchI)
{
forAll(patchLst[patchI], patchFaceI)
{
const face& f = faceLst[faceMap[faceIndex++]];
writeShell(os, pointLst, f, patchI);
}
}
}
void Foam::fileFormats::TRIfileFormat::write
(
Ostream& os,
const meshedSurface& surf
)
{
const pointField& pointLst = surf.points();
const List<face>& faceLst = surf.faces();
const List<surfacePatch>& patchLst = surf.patches();
label faceIndex = 0;
forAll(patchLst, patchI)
{
forAll(patchLst[patchI], patchFaceI)
{
const face& f = faceLst[faceIndex++];
writeShell(os, pointLst, f, patchI);
}
}
}
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * Friend Functions * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
// ************************************************************************* //

View File

@ -0,0 +1,145 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 1991-2008 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::TRIfileFormat
Description
Provide a means of reading/writing .tri format.
SourceFiles
TRIfileFormat.C
\*---------------------------------------------------------------------------*/
#ifndef TRIfileFormat_H
#define TRIfileFormat_H
#include "Ostream.H"
#include "OFstream.H"
#include "keyedSurface.H"
#include "meshedSurface.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace fileFormats
{
/*---------------------------------------------------------------------------*\
Class TRIfileFormat Declaration
\*---------------------------------------------------------------------------*/
class TRIfileFormat
:
public keyedSurface
{
// Private Member Functions
//- Disallow default bitwise copy construct
TRIfileFormat(const TRIfileFormat&);
//- Disallow default bitwise assignment
void operator=(const TRIfileFormat&);
static inline void writeShell
(
Ostream&,
const pointField&,
const face&,
const label patchI
);
public:
// Constructors
//- Construct null
TRIfileFormat();
//- Construct from file name
TRIfileFormat(const fileName&, const bool triangulate=true);
// Selectors
//- Read file and return keyedSurface
static autoPtr<keyedSurface> New
(
const fileName& fName,
const bool triangulate=true
)
{
return autoPtr<keyedSurface>
(
new TRIfileFormat(fName, triangulate)
);
}
// Destructor
// Member Functions
// Write
//- Write keyedSurface
static void write(Ostream&, const keyedSurface&);
//- Write keyedSurface
static void write(const fileName& fName, const keyedSurface& surf)
{
write(OFstream(fName)(), surf);
}
//- Write meshedSurface
static void write(Ostream&, const meshedSurface&);
//- Write meshedSurface
static void write(const fileName& fName, const meshedSurface& surf)
{
write(OFstream(fName)(), surf);
}
//- Write object
virtual void write(Ostream& os) const
{
write(os, *this);
}
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace fileFormats
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,233 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 1991-2008 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 "VTKfileFormat.H"
#include "clock.H"
#include "IFstream.H"
#include "IStringStream.H"
#include "addToRunTimeSelectionTable.H"
#include "addToMemberFunctionSelectionTable.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
namespace fileFormats
{
addNamedToMemberFunctionSelectionTable
(
keyedSurface,
VTKfileFormat,
write,
fileExtension,
vtk
);
addNamedToMemberFunctionSelectionTable
(
meshedSurface,
VTKfileFormat,
write,
fileExtension,
vtk
);
}
}
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::fileFormats::VTKfileFormat::writeHead
(
Ostream& os,
const pointField& pointLst
)
{
// Write header
os << "# vtk DataFile Version 2.0" << nl
<< "surface written " << clock::dateTime().c_str() << nl
<< "ASCII" << nl
<< nl
<< "DATASET POLYDATA" << nl;
// Write vertex coords
os << "POINTS " << pointLst.size() << " float" << nl;
forAll(pointLst, ptI)
{
os << pointLst[ptI].x() << ' '
<< pointLst[ptI].y() << ' '
<< pointLst[ptI].z() << nl;
}
}
void Foam::fileFormats::VTKfileFormat::writeTail
(
Ostream& os,
const List<surfacePatch>& patchLst
)
{
label nFaces = 0;
forAll(patchLst, patchI)
{
nFaces += patchLst[patchI].size();
}
// Print region numbers
os << nl
<< "CELL_DATA " << nFaces << nl
<< "FIELD attributes 1" << nl
<< "region 1 " << nFaces << " float" << nl;
forAll(patchLst, patchI)
{
forAll(patchLst[patchI], patchFaceI)
{
if (patchFaceI)
{
if ((patchFaceI % 20) == 0)
{
os << nl;
}
else
{
os << ' ';
}
}
os << patchI + 1;
}
os << nl;
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::fileFormats::VTKfileFormat::VTKfileFormat()
:
Foam::keyedSurface()
{}
// * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::fileFormats::VTKfileFormat::write
(
Ostream& os,
const keyedSurface& surf
)
{
const pointField& pointLst = surf.points();
const List<keyedFace>& faceLst = surf.faces();
labelList faceMap;
List<surfacePatch> patchLst = surf.sortedRegions(faceMap);
writeHead(os, pointLst);
label nNodes = 0;
forAll(faceLst, faceI)
{
nNodes += faceLst[faceI].size();
}
os << nl
<< "POLYGONS " << faceLst.size() << ' '
<< faceLst.size() + nNodes << nl;
label faceIndex = 0;
forAll(patchLst, patchI)
{
forAll(patchLst[patchI], patchFaceI)
{
const face& f = faceLst[faceMap[faceIndex++]];
os << f.size();
forAll(f, fp)
{
os << ' ' << f[fp];
}
os << ' ' << nl;
}
}
// Print region numbers
writeTail(os, patchLst);
}
void Foam::fileFormats::VTKfileFormat::write
(
Ostream& os,
const meshedSurface& surf
)
{
const pointField& pointLst = surf.points();
const List<face>& faceLst = surf.faces();
const List<surfacePatch>& patchLst = surf.patches();
writeHead(os, pointLst);
label nNodes = 0;
forAll(faceLst, faceI)
{
nNodes += faceLst[faceI].size();
}
os << nl
<< "POLYGONS " << faceLst.size() << ' '
<< faceLst.size() + nNodes << nl;
label faceIndex = 0;
forAll(patchLst, patchI)
{
forAll(patchLst[patchI], patchFaceI)
{
const face& f = faceLst[faceIndex++];
os << f.size();
forAll(f, fp)
{
os << ' ' << f[fp];
}
os << ' ' << nl;
}
}
// Print region numbers
writeTail(os, patchLst);
}
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * Friend Functions * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
// ************************************************************************* //

View File

@ -0,0 +1,124 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 1991-2008 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::VTKfileFormat
Description
Provide a means of writing VTK legacy format.
SourceFiles
VTKfileFormat.C
\*---------------------------------------------------------------------------*/
#ifndef VTKfileFormat_H
#define VTKfileFormat_H
#include "Ostream.H"
#include "OFstream.H"
#include "keyedSurface.H"
#include "meshedSurface.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace fileFormats
{
/*---------------------------------------------------------------------------*\
Class VTKfileFormat Declaration
\*---------------------------------------------------------------------------*/
class VTKfileFormat
:
public keyedSurface
{
// Private Member Functions
//- Disallow default bitwise copy construct
VTKfileFormat(const VTKfileFormat&);
//- Disallow default bitwise assignment
void operator=(const VTKfileFormat&);
static void writeHead(Ostream&, const pointField&);
static void writeTail(Ostream&, const List<surfacePatch>&);
public:
// Constructors
//- Construct null
VTKfileFormat();
// Selectors
// Destructor
// Member Functions
// Write
//- Write keyedSurface
static void write(Ostream&, const keyedSurface&);
//- Write keyedSurface
static void write(const fileName& fName, const keyedSurface& surf)
{
write(OFstream(fName)(), surf);
}
//- Write meshedSurface
static void write(Ostream&, const meshedSurface&);
//- Write meshedSurface
static void write(const fileName& fName, const meshedSurface& surf)
{
write(OFstream(fName)(), surf);
}
//- Write object
virtual void write(Ostream& os) const
{
write(os, *this);
}
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace fileFormats
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,461 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 1991-2008 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::keyedSurface
Description
A surface geometry mesh, in which the patch information is conveyed by
the 'key' attached to each face.
This form of surface description is particularly useful for reading in
surface meshes from third-party formats (eg, obj, stl, gts, etc.). It
can also be particularly useful for situations in which the surface
many be adjusted in an arbitrary manner without worrying about needed
to adjust the patch information (eg, surface refinement).
See Also
The Foam::meshedSurface - which is organized as a surface mesh, but
with independent patch information.
SourceFiles
keyedSurface.C
\*---------------------------------------------------------------------------*/
#ifndef keyedSurface_H
#define keyedSurface_H
#include "pointField.H"
#include "PrimitivePatchExtra.H"
#include "boolList.H"
#include "geometricSurfacePatchList.H"
#include "surfacePatchList.H"
#include "face.H"
#include "Keyed.H"
#include "xfer.H"
#include "runTimeSelectionTables.H"
#include "memberFunctionSelectionTables.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
class Time;
class IFstream;
class meshedSurface;
class polyBoundaryMesh;
/*---------------------------------------------------------------------------*\
Class keyedSurface Declaration
\*---------------------------------------------------------------------------*/
class keyedSurface
:
public PrimitivePatchExtra<Keyed<face>, ::Foam::List, pointField, point>
{
friend class meshedSurface;
protected:
// Protected Member Data
//- Typedef if this type has not already been defined
typedef Keyed<face> keyedFace;
//- Typedef for similar code in keyedSurface and meshedSurface
typedef keyedFace FaceType;
private:
// Private Member Data
// Private typedefs
typedef PrimitivePatchExtra
<
FaceType,
::Foam::List,
pointField,
point
>
MeshStorage;
// Private data
//- Patch information (face ordering nFaces/startFace only used
// during reading and writing)
geometricSurfacePatchList geoPatches_;
// Private member functions
//- Read in Foam format
bool read(Istream&);
//- Generic read routine. Chooses reader based on extension.
//? bool read(const fileName&, const word& ext);
protected:
// Static protected functions
//- Read non-comment line
static string getLineNoComment(IFstream&);
// Protected Member functions
//- Sets default patch names based on the maximum patch number
void setPatches(const label maxPatch);
//- Finds maximum patch number and sets default patch names
void setPatches();
//- Sets patch names from hashed values (id -> name)
void setPatches
(
const Map<word>& regionNames,
const label maxPatch = -1
);
//- Sets patch names from hashed values (name -> id)
void setPatches(const HashTable<label>& groupToPatch);
//- Join the faces by removing duplicate points.
// Returns true if any points merged
bool stitchFaces(const scalar tol=SMALL, const bool verbose=false);
//- Return non-const access to global points
pointField& points()
{
return const_cast<pointField&>(MeshStorage::points());
}
//- Return non-const access to the faces
List<FaceType>& faces()
{
return static_cast<List<FaceType> &>(*this);
}
public:
//- Runtime type information
ClassName("keyedSurface");
//- Return the default geometric patch type (usually "empty")
static word defaultGeometricType;
// Static
//- Name of keyedSurface directory to use.
static fileName triSurfInstance(const Time&);
//- Name of keyedSurface directory to use.
static fileName triSurfName(const Time&);
// Constructors
//- Construct null
keyedSurface();
//- Construct from components (points, labelled faces, patches).
keyedSurface
(
const pointField&,
const List<keyedFace>&,
const geometricSurfacePatchList&
);
//- Construct by transferring components
// (points, labelled faces, patches.
keyedSurface
(
const xfer<pointField>&,
const xfer<List<keyedFace> >&,
const xfer<geometricSurfacePatchList>&
);
//- Construct by transferring points and labelled faces
// With region names per map or set to default.
keyedSurface
(
const xfer<pointField>&,
const xfer<List<keyedFace> >&,
const Map<word>& regionNames = Map<word>::null()
);
//- Construct by transferring points and labelled faces
// with patch-names from hash
keyedSurface
(
const xfer<pointField>&,
const xfer<List<keyedFace> >&,
const HashTable<label>& labelToRegion
);
//- Construct by transferring points, copying unlabelled faces.
// Set single default patch.
keyedSurface
(
const xfer<pointField>&,
const List<face>&
);
//- Construct from a boundary mesh with local points/faces
keyedSurface
(
const polyBoundaryMesh&,
const bool globalPoints=false
);
//- Construct from a meshedSurface
keyedSurface(const meshedSurface&);
//- Construct from file name (uses extension to determine type)
keyedSurface
(
const fileName&,
const bool triangulate=false
);
//- Construct from file name (uses extension to determine type)
keyedSurface
(
const fileName&,
const word&,
const bool triangulate=false
);
//- Construct from Istream
keyedSurface(Istream&);
//- Construct from objectRegistry
keyedSurface(const Time&);
//- Construct as copy
keyedSurface(const keyedSurface&);
//- Construct by transferring the contents from a keyedSurface
keyedSurface(const xfer<keyedSurface>&);
//- Construct by transferring the contents from a meshedSurface
keyedSurface(const xfer<meshedSurface>&);
// Declare run-time constructor selection table
declareRunTimeSelectionTable
(
autoPtr,
keyedSurface,
fileExtension,
(
const fileName& fName,
const bool triangulate
),
(fName, triangulate)
);
// Selectors
//- Select constructed from filename (implicit extension)
static autoPtr<keyedSurface> New
(
const fileName& fName,
const bool triangulate=false
);
//- Select constructed from filename (explicit extension)
static autoPtr<keyedSurface> New
(
const fileName& fName,
const word& ext,
const bool triangulate=false
);
// Destructor
~keyedSurface();
// Member Function Selectors
declareMemberFunctionSelectionTable
(
void,
keyedSurface,
write,
fileExtension,
(
const fileName& fName,
const keyedSurface& surf
),
(fName, surf)
);
//- Write to file
static void write(const fileName&, const keyedSurface&);
//- Can we read this file format?
static bool canRead(const word& ext, const bool verbose=false);
//- Can we write this file format?
static bool canWrite(const word& ext, const bool verbose=false);
// Member Functions
// Access
//- Return the number of points
label nPoints() const
{
return points().size();
}
//- Return the number of faces
label nFaces() const
{
return faces().size();
}
//- The surface size is the number of faces
label size() const
{
return nFaces();
}
//- Return const access to global points
const pointField& points() const
{
return MeshStorage::points();
}
//- Return const access to the faces
const List<FaceType>& faces() const
{
return static_cast<const List<FaceType> &>(*this);
}
const geometricSurfacePatchList& geoPatches() const
{
return geoPatches_;
}
geometricSurfacePatchList& geoPatches()
{
return geoPatches_;
}
//- Determine the sort order from the face regions.
// Returns patch list and sets faceMap to index within faceLst
static surfacePatchList sortedRegions
(
const List<keyedFace>& faceLst,
const Map<word>& patchNames,
labelList& faceMap
);
//- Determine the sort order from the region list.
// Returns patch list and sets faceMap to indices within faceLst
static surfacePatchList sortedRegions
(
const List<label>& regionLst,
const Map<word>& patchNames,
labelList& faceMap
);
//- Sort faces according to region.
// Returns patch list and sets faceMap to index within faces()
surfacePatchList sortedRegions(labelList& faceMap) const;
// Edit
//- Move points
virtual void movePoints(const pointField&);
//- Scale points. A non-positive factor is ignored
virtual void scalePoints(const scalar&);
void checkFaces(const bool verbose);
//- Remove invalid faces
void cleanup(const bool verbose);
//- Return new surface. Returns pointMap, faceMap from
// subsetMeshMap
keyedSurface subsetMesh
(
const boolList& include,
labelList& pointMap,
labelList& faceMap
) const;
//- Transfer the contents of the argument and annull the argument
void transfer(keyedSurface&);
//- Transfer the contents of the argument and annull the argument
void transfer(meshedSurface&);
// Write
//- Write to Ostream in simple FOAM format
virtual void write(Ostream&) const;
//- Generic write routine. Chooses writer based on extension.
virtual void write(const fileName& fName) const
{
write(fName, *this);
}
//- Write to database
void write(const Time&) const;
//- Write some statistics
void writeStats(Ostream&) const;
// Friend Functions
// Member operators
void operator=(const keyedSurface&);
// Ostream Operator
friend Ostream& operator<<(Ostream&, const keyedSurface&);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,235 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 1991-2008 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 "keyedSurface.H"
#include "mergePoints.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
// Remove badly degenerate faces, double faces.
void Foam::keyedSurface::cleanup(const bool verbose)
{
// merge points (already done for STL, TRI)
stitchFaces(SMALL, verbose);
checkFaces(verbose);
checkEdges(verbose);
}
bool Foam::keyedSurface::stitchFaces(const scalar tol, const bool verbose)
{
pointField& pointLst = points();
// Merge points
labelList pointMap(pointLst.size());
pointField newPoints(pointLst.size());
bool hasMerged = mergePoints(pointLst, tol, verbose, pointMap, newPoints);
if (!hasMerged)
{
return false;
}
if (verbose)
{
Info<< "keyedSurface::stitchFaces : Renumbering all faces"
<< endl;
}
// Set the coordinates to the merged ones
pointLst.transfer(newPoints);
List<FaceType>& faceLst = faces();
// Reset the point labels to the unique points array
label newFaceI = 0;
forAll (faceLst, faceI)
{
FaceType& f = faceLst[faceI];
forAll (f, fp)
{
f[fp] = pointMap[f[fp]];
}
if (f.collapse() >= 3)
{
if (newFaceI != faceI)
{
faceLst[newFaceI] = f;
}
newFaceI++;
}
else if (verbose)
{
Pout<< "keyedSurface::stitchFaces : "
<< "Removing collapsed face " << faceI << endl
<< " vertices :" << f << endl;
}
}
if (newFaceI != faceLst.size())
{
if (verbose)
{
Pout<< "keyedSurface::stitchFaces : "
<< "Removed " << faceLst.size() - newFaceI
<< " faces" << endl;
}
faceLst.setSize(newFaceI);
}
// Merging points might have changed geometric factors
clearOut();
return true;
}
// Remove badly degenerate faces and double faces.
void Foam::keyedSurface::checkFaces(const bool verbose)
{
// Simple check on indices ok.
const label maxPointI = points().size() - 1;
List<FaceType>& faceLst = faces();
// Phase 0: detect badly labelled faces
forAll (faceLst, faceI)
{
const FaceType& f = faceLst[faceI];
forAll (f, fp)
{
if (f[fp] < 0 || f[fp] > maxPointI)
{
FatalErrorIn("keyedSurface::checkFaces(bool)")
<< "face " << f
<< " uses point indices outside point range 0.."
<< maxPointI
<< exit(FatalError);
}
}
}
// Two phase process
// 1. mark invalid faces
// 2. pack
// Done to keep numbering constant in phase 1
const labelListList& fFaces = faceFaces();
label newFaceI = 0;
forAll (faceLst, faceI)
{
FaceType& f = faceLst[faceI];
// avoid degenerate faces
if (f.collapse() >= 3)
{
// duplicate face check
bool okay = true;
const labelList& neighbours = fFaces[faceI];
// Check if faceNeighbours use same points as this face.
// Note: discards normal information - sides of baffle are merged.
forAll (neighbours, neighI)
{
if (neighbours[neighI] <= faceI)
{
// lower numbered faces already checked
continue;
}
const face& nei = faceLst[neighbours[neighI]];
if (f == nei)
{
okay = false;
if (verbose)
{
WarningIn
(
"keyedSurface::checkFaces(bool verbose)"
) << "faces share the same vertices:\n"
<< " face 1 :" << faceI << endl;
// printFace(Warning, " ", f, points());
Warning
<< endl
<< " face 2 :"
<< neighbours[neighI] << endl;
// printFace(Warning, " ", nei, points());
}
break;
}
}
if (okay)
{
if (newFaceI != faceI)
{
faceLst[newFaceI] = f;
}
newFaceI++;
}
}
else if (verbose)
{
WarningIn
(
"keyedSurface::checkFaces(bool verbose)"
) << "face " << faceI
<< " does not at least three unique vertices:\n";
// printFace(Warning, " ", f, points());
}
}
if (newFaceI < faceLst.size())
{
if (verbose)
{
WarningIn
(
"keyedSurface::checkFaces(bool verbose)"
) << "Removed " << faceLst.size() - newFaceI
<< " illegal faces." << endl;
}
faceLst.setSize(newFaceI);
// Topology can change because of renumbering
clearOut();
}
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// ************************************************************************* //

View File

@ -0,0 +1,95 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 1991-2008 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 "keyedSurface.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::autoPtr<Foam::keyedSurface>
Foam::keyedSurface::New
(
const fileName& fName,
const word& ext,
const bool triangulate
)
{
if (debug)
{
Info<< "keyedSurface::New"
"(const fileName&, const word&, const bool) : "
"constructing keyedSurface"
<< endl;
}
fileExtensionConstructorTable::iterator cstrIter =
fileExtensionConstructorTablePtr_->find(ext);
if (cstrIter == fileExtensionConstructorTablePtr_->end())
{
FatalErrorIn
(
"keyedSurface::New(const fileName&, const word&, const bool) : "
"constructing keyedSurface"
) << "Unknown file extension " << ext << nl << nl
<< "Valid types are :" << nl
<< fileExtensionConstructorTablePtr_->toc()
<< exit(FatalError);
}
return autoPtr<keyedSurface>(cstrIter()(fName, triangulate));
}
Foam::autoPtr<Foam::keyedSurface>
Foam::keyedSurface::New
(
const fileName& fName,
const bool triangulate
)
{
const word ext = fName.ext();
if (debug)
{
Info<< "keyedSurface::New(const fileName&, const bool) : "
"constructing keyedSurface"
<< endl;
}
// TODO:
// if (ext == "gz")
// {
// fileName unzipName = fName.lessExt();
//
// return New(unzipName, unzipName.ext(), ext);
// }
return New(fName, ext, triangulate);
}
// ************************************************************************* //

View File

@ -0,0 +1,988 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 1991-2008 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 "meshedSurface.H"
#include "keyedSurface.H"
#include "demandDrivenData.H"
#include "IFstream.H"
#include "OFstream.H"
#include "Time.H"
#include "boundBox.H"
#include "SortableList.H"
#include "ListOps.H"
#include "polyBoundaryMesh.H"
#include "polyMesh.H"
// #include "surfMesh.H"
#include "primitivePatch.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(meshedSurface, 0);
defineMemberFunctionSelectionTable
(
meshedSurface,
write,
fileExtension
);
}
Foam::word Foam::meshedSurface::defaultGeometricType("empty");
// File extension for 'native' raw format
//! @cond localscope
const char * const nativeExt = "ftr";
//! @endcond localscope
// * * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * //
Foam::fileName Foam::meshedSurface::triSurfInstance(const Time& d)
{
fileName foamName(d.caseName() + "." + nativeExt);
// Search back through the time directories list to find the time
// closest to and lower than current time
instantList ts = d.times();
label i;
for (i=ts.size()-1; i>=0; i--)
{
if (ts[i].value() <= d.timeOutputValue())
{
break;
}
}
// Noting that the current directory has already been searched
// for mesh data, start searching from the previously stored time directory
if (i>=0)
{
for (label j=i; j>=0; j--)
{
if (file(d.path()/ts[j].name()/typeName/foamName))
{
if (debug)
{
Pout<< " meshedSurface::triSurfInstance(const Time& d)"
<< "reading " << foamName
<< " from " << ts[j].name()/typeName
<< endl;
}
return ts[j].name();
}
}
}
if (debug)
{
Pout<< " meshedSurface::triSurfInstance(const Time& d)"
<< "reading " << foamName
<< " from constant/" << endl;
}
return "constant";
}
Foam::fileName Foam::meshedSurface::triSurfName(const Time& d)
{
fileName foamName(d.caseName() + "." + nativeExt);
// Search back through the time directories list to find the time
// closest to and lower than current time
instantList ts = d.times();
label i;
for (i=ts.size()-1; i>=0; i--)
{
if (ts[i].value() <= d.timeOutputValue())
{
break;
}
}
// Noting that the current directory has already been searched
// for mesh data, start searching from the previously stored time directory
if (i>=0)
{
for (label j=i; j>=0; j--)
{
fileName testName(d.path()/ts[j].name()/typeName/foamName);
if (file(testName))
{
if (debug)
{
Pout<< " meshedSurface::triSurfName(const Time& d)"
<< "reading " << foamName
<< " from " << ts[j].name()/typeName
<< endl;
}
return testName;
}
}
}
if (debug)
{
Pout<< " meshedSurface::triSurfName(const Time& d)"
<< "reading " << foamName
<< " from constant/" << endl;
}
return d.path()/"constant"/typeName/foamName;
}
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::meshedSurface::onePatch()
{
// set single default patch
patches_.setSize(1);
patches_[0] = surfacePatch
(
defaultGeometricType,
"patch0",
size(), // patch size
0, // patch start
0 // patch index
);
}
void Foam::meshedSurface::checkPatches()
{
// extra safety, ensure we have at some patches,
// and they cover all the faces
// fix start silently
if (patches_.size() > 1)
{
label count = 0;
forAll(patches_, patchI)
{
patches_[patchI].start() = count;
count += patches_[patchI].size();
}
if (count < size())
{
WarningIn
(
"meshedSurface::checkPatches()\n"
)
<< "more nFaces " << size()
<< " than patches " << count
<< " ... extending final patch"
<< endl;
patches_[patches_.size()-1].size() += count - size();
}
else if (count > size())
{
FatalErrorIn
(
"meshedSurface::checkPatches()\n"
)
<< "more patches " << count
<< " than nFaces " << size()
<< exit(FatalError);
}
}
else if (patches_.size() == 1)
{
// like onePatch, but preserve the name
patches_[0].start() = 0;
patches_[0].size() = size();
if (!patches_[0].name().size())
{
patches_[0].name() = "patch0";
}
}
else
{
onePatch();
}
}
// Read triangles, points from Istream
bool Foam::meshedSurface::read(Istream& is)
{
is >> patches_ >> points() >> faces();
return true;
}
#if 0
// Read from file in given format
bool Foam::meshedSurface::read(const fileName& name, const word& ext)
{
if (ext == "gz")
{
fileName unzipName = name.lessExt();
return read(unzipName, unzipName.ext());
}
}
#endif
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::meshedSurface::meshedSurface()
:
MeshStorage(List<FaceType>(), pointField()),
patches_()
{}
Foam::meshedSurface::meshedSurface
(
const pointField& pointLst,
const List<FaceType>& faceLst,
const surfacePatchList& patchLst
)
:
MeshStorage(faceLst, pointLst),
patches_(patchLst)
{}
Foam::meshedSurface::meshedSurface
(
const xfer<pointField>& pointLst,
const xfer<List<FaceType> >& faceLst,
const xfer<surfacePatchList>& patchLst
)
:
MeshStorage(List<FaceType>(), pointField()),
patches_(patchLst)
{
faces().transfer(faceLst());
points().transfer(pointLst());
}
Foam::meshedSurface::meshedSurface
(
const xfer<pointField>& pointLst,
const xfer<List<FaceType> >& faceLst,
const List<label>& patchSizes,
const List<word>& patchNames,
const List<word>& patchTypes
)
:
MeshStorage(List<FaceType>(), pointField()),
patches_()
{
points().transfer(pointLst());
faces().transfer(faceLst());
surfacePatchList newPatches(patchSizes.size());
label start = 0;
forAll(newPatches, patchI)
{
newPatches[patchI] = surfacePatch
(
defaultGeometricType,
patchNames[patchI],
patchSizes[patchI],
start,
patchI
);
start += patchSizes[patchI];
}
patches_.transfer(newPatches);
}
Foam::meshedSurface::meshedSurface
(
const xfer<pointField>& pointLst,
const xfer<List<FaceType> >& faceLst,
const List<label>& regionLst,
const Map<word>& regionNames
)
:
MeshStorage(List<FaceType>(), pointField()),
patches_()
{
points().transfer(pointLst());
faces().transfer(faceLst());
const List<FaceType>& unsortedFaces = faces();
if (regionLst.size() == 0)
{
onePatch();
}
else if (regionLst.size() != unsortedFaces.size())
{
FatalErrorIn
(
"meshedSurface::meshedSurface(\n"
"(\n"
" const pointField&,\n"
" const List<FaceType>&,\n"
" const List<label>& regionLst,\n"
" const Map<word>& regionNames\n"
" )\n"
)
<< "size mismatch : regionLst.size() != faceLst.size()"
<< exit(FatalError);
}
else
{
labelList faceMap;
surfacePatchList newPatches = keyedSurface::sortedRegions
(
regionLst,
regionNames,
faceMap
);
patches_.transfer(newPatches);
// this is somewhat like ListOps reorder and/or IndirectList
List<FaceType> newFaces(unsortedFaces.size());
forAll(newFaces, faceI)
{
newFaces[faceI] = unsortedFaces[faceMap[faceI]];
}
faceMap.clear();
faces().transfer(newFaces);
}
}
Foam::meshedSurface::meshedSurface
(
const xfer<pointField>& pointLst,
const xfer<List<FaceType> >& faceLst
)
:
MeshStorage(List<FaceType>(), pointField()),
patches_()
{
faces().transfer(faceLst());
points().transfer(pointLst());
onePatch();
}
Foam::meshedSurface::meshedSurface
(
const xfer<pointField>& pointLst,
const List<keyedFace>& faceLst,
const Map<word>& regionNames
)
:
MeshStorage(List<FaceType>(), pointField()),
patches_()
{
points().transfer(pointLst());
labelList faceMap;
surfacePatchList newPatches = keyedSurface::sortedRegions
(
faceLst,
regionNames,
faceMap
);
patches_.transfer(newPatches);
// this is somewhat like ListOps reorder and/or IndirectList
List<FaceType> newFaces(faceLst.size());
forAll(newFaces, faceI)
{
newFaces[faceI] = faceLst[faceMap[faceI]];
}
faces().transfer(newFaces);
}
Foam::meshedSurface::meshedSurface
(
const xfer<pointField>& pointLst,
const List<keyedFace>& faceLst,
const HashTable<label>& nameToRegionMapping
)
:
MeshStorage(List<FaceType>(), pointField()),
patches_()
{
points().transfer(pointLst());
Map<word> regionNames;
forAllConstIter(HashTable<label>, nameToRegionMapping, iter)
{
regionNames.insert(iter(), iter.key());
}
labelList faceMap;
surfacePatchList newPatches = keyedSurface::sortedRegions
(
faceLst,
regionNames,
faceMap
);
patches_.transfer(newPatches);
List<FaceType> newFaces(faceLst.size());
// this is somewhat like ListOps reorder and/or IndirectList
forAll(newFaces, faceI)
{
newFaces[faceI] = faceLst[faceMap[faceI]];
}
faces().transfer(newFaces);
}
Foam::meshedSurface::meshedSurface
(
const polyBoundaryMesh& bMesh,
const bool useGlobalPoints
)
:
MeshStorage(List<FaceType>(), pointField()),
patches_()
{
const polyMesh& mesh = bMesh.mesh();
const polyPatchList& bPatches = bMesh;
const label nIntFaces = mesh.nInternalFaces();
// Get patch for all of outside
primitivePatch allBoundary
(
SubList<FaceType>
(
mesh.faces(),
mesh.nFaces() - nIntFaces,
nIntFaces
),
mesh.points()
);
if (useGlobalPoints)
{
// copy in the global points and the global face addressing
points() = mesh.points();
faces() = allBoundary;
}
else
{
// copy in the local points and the local face addressing
points() = allBoundary.localPoints();
faces() = allBoundary.localFaces();
}
// create patch list
surfacePatchList newPatches(bPatches.size());
label startFaceI = 0;
forAll(bPatches, patchI)
{
const polyPatch& p = bPatches[patchI];
newPatches[patchI] = surfacePatch
(
defaultGeometricType,
p.name(),
p.size(),
startFaceI,
patchI
);
startFaceI += p.size();
}
patches_.transfer(newPatches);
}
#if 0
// in preparation
Foam::meshedSurface::meshedSurface
(
const surfMesh& sMesh
)
:
MeshStorage(List<FaceType>(sMesh.faces()), sMesh.points()),
patches_()
{
const surfPatchList& sPatches = sMesh.boundaryMesh();
// create patch list
surfacePatchList newPatches(sPatches.size());
label startFaceI = 0;
forAll(sPatches, patchI)
{
const surfPatch& p = sPatches[patchI];
newPatches[patchI] = surfacePatch
(
defaultGeometricType,
p.name(),
p.size(),
startFaceI,
patchI
);
startFaceI += p.size();
}
patches_.transfer(newPatches);
}
#endif
Foam::meshedSurface::meshedSurface
(
const keyedSurface& surf
)
:
MeshStorage(List<FaceType>(), surf.points()),
patches_()
{
labelList faceMap;
surfacePatchList newPatches = surf.sortedRegions(faceMap);
patches_.transfer(newPatches);
const List<keyedFace>& origFaces = surf.faces();
List<FaceType> newFaces(origFaces.size());
// this is somewhat like ListOps reorder and/or IndirectList
forAll(newFaces, faceI)
{
newFaces[faceI] = origFaces[faceMap[faceI]];
}
faces().transfer(newFaces);
}
Foam::meshedSurface::meshedSurface
(
const fileName& fName,
const word& ext,
const bool triangulate
)
:
MeshStorage(List<FaceType>(), pointField()),
patches_()
{
// use selector mechanism
autoPtr<meshedSurface> surfPtr = New(fName, ext, triangulate);
transfer(surfPtr());
}
Foam::meshedSurface::meshedSurface
(
const fileName& fName,
const bool triangulate
)
:
MeshStorage(List<FaceType>(), pointField()),
patches_()
{
// use selector mechanism
autoPtr<meshedSurface> surfPtr = New(fName, triangulate);
transfer(surfPtr());
}
Foam::meshedSurface::meshedSurface(Istream& is)
:
MeshStorage(List<FaceType>(), pointField()),
patches_()
{
read(is);
// setDefaultPatches();
}
Foam::meshedSurface::meshedSurface(const Time& d)
:
MeshStorage(List<FaceType>(), pointField()),
patches_()
{
read(IFstream(triSurfName(d))());
// setDefaultPatches();
}
Foam::meshedSurface::meshedSurface(const meshedSurface& surf)
:
MeshStorage(surf.faces(), surf.points()),
patches_(surf.patches_)
{}
Foam::meshedSurface::meshedSurface(const xfer<keyedSurface>& surf)
:
MeshStorage(List<FaceType>(), pointField()),
patches_()
{
transfer(surf());
}
Foam::meshedSurface::meshedSurface(const xfer<meshedSurface>& surf)
:
MeshStorage(List<FaceType>(), pointField()),
patches_()
{
transfer(surf());
}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::meshedSurface::~meshedSurface()
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
//- Move points
void Foam::meshedSurface::movePoints(const pointField& newPoints)
{
// Remove all geometry dependent data
clearTopology();
// Adapt for new point position
MeshStorage::movePoints(newPoints);
// Copy new points
points() = newPoints;
}
//- scale points
void Foam::meshedSurface::scalePoints(const scalar& scaleFactor)
{
// avoid bad scaling
if (scaleFactor > 0 && scaleFactor != 1.0)
{
// Remove all geometry dependent data
clearTopology();
// Adapt for new point position
MeshStorage::movePoints(pointField());
points() *= scaleFactor;
}
}
Foam::meshedSurface Foam::meshedSurface::subsetMesh
(
const boolList& include,
labelList& pointMap,
labelList& faceMap
) const
{
const pointField& locPoints = localPoints();
const List<FaceType>& locFaces = localFaces();
// Fill pointMap, faceMap
subsetMap(include, pointMap, faceMap);
// Create compact coordinate list and forward mapping array
pointField newPoints(pointMap.size());
labelList oldToNew(locPoints.size());
forAll(pointMap, pointI)
{
newPoints[pointI] = locPoints[pointMap[pointI]];
oldToNew[pointMap[pointI]] = pointI;
}
// create a new patch list
surfacePatchList newPatches(patches_);
forAll(newPatches, patchI)
{
newPatches[patchI].size() = 0;
}
// Renumber face node labels and compact
List<FaceType> newFaces(faceMap.size());
forAll(faceMap, faceI)
{
// Get old vertex labels
label origFaceI = faceMap[faceI];
const FaceType& oldFace = locFaces[origFaceI];
newFaces[faceI] = FaceType(oldFace);
// Renumber labels for face
FaceType& f = newFaces[faceI];
forAll(f, fp)
{
f[fp] = oldToNew[oldFace[fp]];
}
// adjust patch sizes
forAllReverse (newPatches, patchI)
{
if
(
origFaceI >= patches_[patchI].start()
&& patches_[patchI].size()
)
{
newPatches[patchI].size()++;
break;
}
}
}
// adjust patch start
label startFaceI = 0;
forAll(newPatches, patchI)
{
newPatches[patchI].start() = startFaceI;
startFaceI += newPatches[patchI].size();
}
// Construct an empty subsurface and fill
meshedSurface subSurf;
subSurf.patches_.transfer(newPatches);
subSurf.points().transfer(newPoints);
subSurf.faces().transfer(newFaces);
return subSurf;
}
void Foam::meshedSurface::transfer(meshedSurface& surf)
{
clearOut();
faces().transfer(surf.faces());
points().transfer(surf.points());
patches_.transfer(surf.patches_);
surf.clearOut();
}
void Foam::meshedSurface::transfer(keyedSurface& surf)
{
clearOut();
points().transfer(surf.points());
labelList faceMap;
surfacePatchList newPatches = surf.sortedRegions(faceMap);
patches_.transfer(newPatches);
const List<keyedFace>& origFaces = surf.faces();
List<FaceType> newFaces(origFaces.size());
// this is somewhat like ListOps reorder and/or IndirectList
forAll(newFaces, faceI)
{
newFaces[faceI] = origFaces[faceMap[faceI]];
}
faces().transfer(newFaces);
surf.faces().clear();
surf.clearOut();
}
bool Foam::meshedSurface::canRead(const word& ext, const bool verbose)
{
return keyedSurface::canRead(ext, verbose);
}
bool Foam::meshedSurface::canWrite(const word& ext, const bool verbose)
{
// perhaps we got sent an entire name
word fExt(ext);
// FIXME: this looks horrible, but I don't have STL docs here
string::size_type dot = ext.find_last_of(".");
if (dot != string::npos)
{
fExt = ext.substr(dot+1);
}
// handle 'native' format directly
if (fExt == nativeExt)
{
return true;
}
writefileExtensionMemberFunctionTable::iterator mfIter =
writefileExtensionMemberFunctionTablePtr_->find(fExt);
if (mfIter == writefileExtensionMemberFunctionTablePtr_->end())
{
if (verbose)
{
const wordList& known =
writefileExtensionMemberFunctionTablePtr_->toc();
Info<<"Unknown file extension for writing: " << fExt << nl;
// compact output:
Info<<"Valid types: ( " << nativeExt;
forAll(known, i)
{
Info<<" " << known[i];
}
Info<<" )" << endl;
}
return false;
}
return true;
}
void Foam::meshedSurface::write
(
const fileName& fName,
const meshedSurface& surf
)
{
if (debug)
{
Info<< "meshedSurface::write(const fileName&, const meshedSurface&) : "
"writing meshedSurface to " << fName
<< endl;
}
const word ext = fName.ext();
// handle 'native' format directly
if (ext == nativeExt)
{
surf.write(OFstream(fName)());
}
else
{
writefileExtensionMemberFunctionTable::iterator mfIter =
writefileExtensionMemberFunctionTablePtr_->find(ext);
if (mfIter == writefileExtensionMemberFunctionTablePtr_->end())
{
FatalErrorIn
(
"meshedSurface::write(const fileName&)"
) << "Unknown file extension " << ext << nl << nl
<< "Valid types are :" << endl
<< writefileExtensionMemberFunctionTablePtr_->toc()
<< exit(FatalError);
}
mfIter()(fName, surf);
}
}
void Foam::meshedSurface::write(Ostream& os) const
{
// quick-hack
os << patches_.size() << nl << token::BEGIN_LIST;
forAll(patches_, patchI)
{
patches_[patchI].writeDict(os);
}
os << token::END_LIST;
// Note: Write with global point numbering
os << points() << nl << faces() << endl;
// Check state of Ostream
os.check("meshedSurface::write(Ostream&)");
}
void Foam::meshedSurface::write(const Time& d) const
{
write(OFstream(triSurfName(d))());
}
void Foam::meshedSurface::writeStats(Ostream& os) const
{
os << "Faces : " << size() << endl
<< "Edges : " << nEdges() << endl
<< "Vertices : " << nPoints() << endl
<< "Bounding Box : " << boundBox(localPoints(), false) << endl;
}
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
void Foam::meshedSurface::operator=(const meshedSurface& surf)
{
clearOut();
faces() = surf.faces();
points() = surf.points();
patches_ = surf.patches_;
}
// * * * * * * * * * * * * * * * Friend Functions * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
Foam::Ostream& Foam::operator<<(Ostream& os, const meshedSurface& surf)
{
surf.write(os);
return os;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// ************************************************************************* //

View File

@ -0,0 +1,437 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 1991-2008 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::meshedSurface
Description
A surface geometry mesh with patch information, not to be confused
with a similarily named surfaceMesh, which actually refers to
the cell faces of a volume mesh!
The meshedSurface is intended to surfaces from a variety of sources.
- A set of points and faces without any patch information.
- A set of points and faces with randomly sorted patch information.
This could arise, for example, from reading external file formats
such as STL, etc.
SourceFiles
meshedSurface.C
\*---------------------------------------------------------------------------*/
#ifndef meshedSurface_H
#define meshedSurface_H
#include "pointField.H"
#include "PrimitivePatchExtra.H"
#include "boolList.H"
#include "geometricSurfacePatchList.H"
#include "surfacePatchList.H"
#include "face.H"
#include "Keyed.H"
#include "xfer.H"
#include "runTimeSelectionTables.H"
#include "memberFunctionSelectionTables.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
class Time;
class keyedSurface;
class polyBoundaryMesh;
class surfMesh;
/*---------------------------------------------------------------------------*\
Class meshedSurface Declaration
\*---------------------------------------------------------------------------*/
class meshedSurface
:
public PrimitivePatchExtra<face, ::Foam::List, pointField, point>
{
friend class keyedSurface;
protected:
// Protected Member Data
//- Typedef if this type has not already been defined
typedef Keyed<face> keyedFace;
//- Typedef for similar code in keyedSurface and meshedSurface
typedef face FaceType;
private:
// Private Member Data
// Private typedefs
typedef PrimitivePatchExtra
<
FaceType,
::Foam::List,
pointField,
point
>
MeshStorage;
// Private data
//- Patch information (face ordering nFaces/startFace only used
// during reading and writing)
surfacePatchList patches_;
// Private member functions
//- set a single patch
void onePatch();
//- basic sanity check on patches
void checkPatches();
//- Read in Foam format
bool read(Istream&);
// Static private functions
public:
// Protected Member Data
// Protected Member functions
//- Return non-const access to global points
pointField& points()
{
return const_cast<pointField&>(MeshStorage::points());
}
//- Return non-const access to the faces
List<FaceType>& faces()
{
return static_cast<List<FaceType> &>(*this);
}
public:
//- Runtime type information
ClassName("meshedSurface");
//- Return the default geometric patch type (usually "empty")
static word defaultGeometricType;
// Static
//- Name of meshedSurface directory to use.
static fileName triSurfInstance(const Time&);
//- Name of meshedSurface directory to use.
static fileName triSurfName(const Time&);
// Constructors
//- Construct null
meshedSurface();
//- Construct from components (points, faces and patches).
meshedSurface
(
const pointField&,
const List<face>&,
const surfacePatchList&
);
//- Construct by transferring components
//- (points, faces and patches).
meshedSurface
(
const xfer<pointField>&,
const xfer<List<face> >&,
const xfer<surfacePatchList>&
);
//- Construct from points, faces, and patch information
meshedSurface
(
const xfer<pointField>&,
const xfer<List<face> >&,
const List<label>& patchSizes,
const List<word>& patchNames,
const List<word>& patchTypes
);
//- Construct from points, faces, a list of (unsorted) region Ids
// and with the names of the regions.
meshedSurface
(
const xfer<pointField>&,
const xfer<List<face> >&,
const List<label>& regionIds,
const Map<word>& regionNames
);
//- Construct by transferring points, faces
// with a single default patch
meshedSurface
(
const xfer<pointField>&,
const xfer<List<face> >&
);
//- Construct by transferring points and copying labelled faces
// With region names per map or set to default.
meshedSurface
(
const xfer<pointField>&,
const List<keyedFace>&,
const Map<word>& regionNames
);
//- Construct by transferring points and labelled faces
//- with patch-names from hash
meshedSurface
(
const xfer<pointField>&,
const List<keyedFace>&,
const HashTable<label>& nameToRegionMapping
);
//- Construct from a boundary mesh with local points/faces
meshedSurface
(
const polyBoundaryMesh&,
const bool globalPoints=false
);
//- Construct from a keyedSurface
meshedSurface(const keyedSurface&);
//- Construct from a surfMesh
meshedSurface(const surfMesh&);
//- Construct by transferring the contents from a keyedSurface
meshedSurface(const xfer<keyedSurface>&);
//- Construct by transferring the contents from a meshedSurface
meshedSurface(const xfer<meshedSurface>&);
//- Construct from file name (uses extension to determine type)
meshedSurface
(
const fileName&,
const bool triangulate=false
);
//- Construct from file name (uses extension to determine type)
meshedSurface
(
const fileName&,
const word&,
const bool triangulate=false
);
//- Construct from Istream
meshedSurface(Istream&);
//- Construct from objectRegistry
meshedSurface(const Time&);
//- Construct as copy
meshedSurface(const meshedSurface&);
// Selectors
//- Select constructed from filename (implicit extension)
static autoPtr<meshedSurface> New
(
const fileName&,
const bool triangulate=false
);
//- Select constructed from filename (explicit extension)
static autoPtr<meshedSurface> New
(
const fileName&,
const word&,
const bool triangulate=false
);
// Destructor
~meshedSurface();
// Member Function Selectors
declareMemberFunctionSelectionTable
(
void,
meshedSurface,
write,
fileExtension,
(
const fileName& fName,
const meshedSurface& surf
),
(fName, surf)
);
//- Write to file
static void write(const fileName&, const meshedSurface&);
//- Can we read this file format?
static bool canRead(const word& ext, const bool verbose=false);
//- Can we write this file format?
static bool canWrite(const word& ext, const bool verbose=false);
// Member Functions
// Access
//- Return the number of points
label nPoints() const
{
return points().size();
}
//- Return the number of faces
label nFaces() const
{
return faces().size();
}
//- The surface size is the number of faces
label size() const
{
return nFaces();
}
//- Return const access to global points
const pointField& points() const
{
return MeshStorage::points();
}
//- Return const access to the faces
const List<FaceType>& faces() const
{
return static_cast<const List<FaceType> &>(*this);
}
const surfacePatchList& patches() const
{
return patches_;
}
surfacePatchList& patches()
{
return patches_;
}
// Edit
//- Move points
virtual void movePoints(const pointField&);
//- Scale points. A non-positive factor is ignored
virtual void scalePoints(const scalar&);
//- Triangulate the surface, return the number of added faces.
// The patch list will be adjusted accordingly.
label triangulate();
//- Join the faces by removing duplicate points.
// Returns true if any points merged
bool stitchFaces(const scalar tol=SMALL, const bool verbose=false);
//- Check/fix duplicate/degenerate faces
void checkFaces(const bool verbose);
//- Remove invalid faces
void cleanup(const bool verbose);
//- Return new surface.
// Returns pointMap, faceMap from subsetMeshMap
meshedSurface subsetMesh
(
const boolList& include,
labelList& pointMap,
labelList& faceMap
) const;
//- Transfer the contents of the argument and annull the argument
void transfer(meshedSurface&);
//- Transfer the contents of the argument and annull the argument
void transfer(keyedSurface&);
// Write
//- Write to Ostream in simple FOAM format
virtual void write(Ostream&) const;
//- Generic write routine. Chooses writer based on extension.
virtual void write(const fileName& fName) const
{
write(fName, *this);
}
//- Write to database
void write(const Time&) const;
//- Write some statistics
void writeStats(Ostream&) const;
// Member operators
void operator=(const meshedSurface&);
// Ostream Operator
friend Ostream& operator<<(Ostream&, const meshedSurface&);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,330 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 1991-2008 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 "meshedSurface.H"
#include "mergePoints.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
// Remove badly degenerate faces, double faces.
void Foam::meshedSurface::cleanup(const bool verbose)
{
// merge points (already done for STL, TRI)
stitchFaces(SMALL, verbose);
checkFaces(verbose);
checkEdges(verbose);
}
bool Foam::meshedSurface::stitchFaces(const scalar tol, const bool verbose)
{
pointField& pointLst = points();
// Merge points
labelList pointMap(pointLst.size());
pointField newPoints(pointLst.size());
bool hasMerged = mergePoints(pointLst, tol, verbose, pointMap, newPoints);
if (!hasMerged)
{
return false;
}
if (verbose)
{
Info<< "meshedSurface::stitchFaces : Renumbering all faces"
<< endl;
}
// Set the coordinates to the merged ones
pointLst.transfer(newPoints);
List<FaceType>& faceLst = faces();
// ensure we have at some patches, and they cover all the faces
checkPatches();
// Reset the point labels to the unique points array
label oldFaceI = 0;
label newFaceI = 0;
forAll (patches_, patchI)
{
surfacePatch& surfPatch = patches_[patchI];
// adjust patch start
surfPatch.start() = newFaceI;
label patchEnd = oldFaceI + surfPatch.size();
for (; oldFaceI < patchEnd; ++oldFaceI)
{
FaceType& f = faceLst[oldFaceI];
forAll (f, fp)
{
f[fp] = pointMap[f[fp]];
}
if (f.collapse() >= 3)
{
if (newFaceI != oldFaceI)
{
faceLst[newFaceI] = f;
}
newFaceI++;
}
else if (verbose)
{
Pout<< "meshedSurface::stitchFaces : "
<< "Removing collapsed face " << oldFaceI << endl
<< " vertices :" << f << endl;
}
}
// adjust patch size
surfPatch.size() = newFaceI - surfPatch.size();
}
if (newFaceI != faceLst.size())
{
if (verbose)
{
Pout<< "meshedSurface::stitchFaces : "
<< "Removed " << faceLst.size() - newFaceI
<< " faces" << endl;
}
faceLst.setSize(newFaceI);
}
// Merging points might have changed geometric factors
clearOut();
return true;
}
// Remove badly degenerate faces and double faces.
void Foam::meshedSurface::checkFaces(const bool verbose)
{
// Simple check on indices ok.
const label maxPointI = points().size() - 1;
List<FaceType>& faceLst = faces();
// Phase 0: detect badly labelled faces
forAll (faceLst, faceI)
{
const FaceType& f = faceLst[faceI];
forAll (f, fp)
{
if (f[fp] < 0 || f[fp] > maxPointI)
{
FatalErrorIn("meshedSurface::checkFaces(bool)")
<< "face " << f
<< " uses point indices outside point range 0.."
<< maxPointI
<< exit(FatalError);
}
}
}
// ensure we have patches, and they cover all the faces
checkPatches();
// Phase 1: find and skip over invalid faces
// Phase 2: pack
const labelListList& fFaces = faceFaces();
label oldFaceI = 0;
label newFaceI = 0;
forAll (patches_, patchI)
{
surfacePatch& surfPatch = patches_[patchI];
// correct the patch start
surfPatch.start() = newFaceI;
label patchEnd = oldFaceI + surfPatch.size();
for (; oldFaceI < patchEnd; ++oldFaceI)
{
FaceType& f = faceLst[oldFaceI];
// 'degenerate' face check
if (f.collapse() >= 3)
{
// duplicate face check
bool okay = true;
const labelList& neighbours = fFaces[oldFaceI];
// Check if faceNeighbours use same points as this face.
// Note: discards normal information - sides of baffle are merged.
forAll (neighbours, neighI)
{
if (neighbours[neighI] <= oldFaceI)
{
// lower numbered faces already checked
continue;
}
const face& nei = faceLst[neighbours[neighI]];
if (f == nei)
{
okay = false;
if (verbose)
{
WarningIn
(
"meshedSurface::checkFaces(bool verbose)"
) << "faces share the same vertices:\n"
<< " face 1 :" << oldFaceI << endl;
// printFace(Warning, " ", f, points());
Warning
<< endl
<< " face 2 :"
<< neighbours[neighI] << endl;
// printFace(Warning, " ", nei, points());
}
break;
}
}
if (okay)
{
if (newFaceI != oldFaceI)
{
faceLst[newFaceI] = f;
}
newFaceI++;
}
}
else if (verbose)
{
WarningIn
(
"meshedSurface::checkFaces(bool verbose)"
) << "face " << oldFaceI
<< " has fewer than three unique vertices:\n";
// printTriangle(Warning, " ", f, points());
}
}
// adjust patch size
surfPatch.size() = newFaceI - surfPatch.start();
}
if (newFaceI < faceLst.size())
{
if (verbose)
{
WarningIn
(
"meshedSurface::checkFaces(bool verbose)"
) << "Removed " << faceLst.size() - newFaceI
<< " illegal faces." << endl;
}
faceLst.setSize(newFaceI);
// Topology can change because of renumbering
clearOut();
}
}
Foam::label Foam::meshedSurface::triangulate()
{
label nTri = 0;
List<FaceType>& faceLst = faces();
// estimate how may triangles are needed
forAll (faceLst, faceI)
{
nTri += faceLst[faceI].size() - 2;
}
// nothing to do
if (nTri <= faceLst.size())
{
return 0;
}
List<FaceType> newFaces(nTri);
// note the number of *additional* faces
nTri -= faceLst.size();
// Reset the point labels to the unique points array
label oldFaceI = 0;
label newFaceI = 0;
forAll (patches_, patchI)
{
surfacePatch& surfPatch = patches_[patchI];
// adjust patch start
surfPatch.start() = newFaceI;
label patchEnd = oldFaceI + surfPatch.size();
for (; oldFaceI < patchEnd; ++oldFaceI)
{
const FaceType& f = faceLst[oldFaceI];
FaceType fTri(3);
// Do simple face triangulation around f[0].
// we could also use face::triangulation
fTri[0] = f[0];
for (label fp = 1; fp < f.size() - 1; ++fp)
{
label fp1 = (fp + 1) % f.size();
fTri[1] = f[fp];
fTri[2] = f[fp1];
newFaces[newFaceI++] = fTri;
}
}
// adjust patch size
surfPatch.size() = newFaceI - surfPatch.start();
}
faceLst.transfer(newFaces);
return nTri;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// ************************************************************************* //

View File

@ -0,0 +1,73 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 1991-2008 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 "keyedSurface.H"
#include "meshedSurface.H"
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
// all input is indirect via keyedSurface
Foam::autoPtr<Foam::meshedSurface>
Foam::meshedSurface::New
(
const fileName& fName,
const word& ext,
const bool triangulate
)
{
if (debug)
{
Info<< "meshedSurface::New(const fileName&, const word&, const bool) : "
"constructing meshedSurface"
<< endl;
}
// created indirectly via keyedSurface
autoPtr<meshedSurface> surf(new meshedSurface);
surf().transfer( keyedSurface::New(fName,ext,triangulate)() );
return surf;
}
Foam::autoPtr<Foam::meshedSurface>
Foam::meshedSurface::New
(
const fileName& fName,
const bool triangulate
)
{
if (debug)
{
Info<< "meshedSurface::New(const fileName&, const bool) : "
"constructing meshedSurface"
<< endl;
}
return New(fName, fName.ext(), triangulate);
}
// ************************************************************************* //