surfMesh - ac3d, tri read into MeshedSurface

- optimized stl reading to skip sort if possible
This commit is contained in:
Mark Olesen
2008-11-20 16:28:38 +01:00
parent 74cb43af0b
commit a11386e6ba
15 changed files with 705 additions and 375 deletions

View File

@ -25,6 +25,7 @@ $(surfaceFormats)/starcd/STARCDsurfaceFormatRunTime.C
$(surfaceFormats)/stl/STLsurfaceFormatCore.C
$(surfaceFormats)/stl/STLsurfaceFormatRunTime.C
$(surfaceFormats)/stl/STLsurfaceFormatASCII.L
$(surfaceFormats)/tri/TRIsurfaceFormatCore.C
$(surfaceFormats)/tri/TRIsurfaceFormatRunTime.C
$(surfaceFormats)/vtk/VTKsurfaceFormatCore.C
$(surfaceFormats)/vtk/VTKsurfaceFormatRunTime.C

View File

@ -758,6 +758,54 @@ void Foam::MeshedSurface<Face>::addPatches
}
template<class Face>
void Foam::MeshedSurface<Face>::addPatches
(
const UList<word>& names,
const UList<label>& sizes
)
{
patches_.setSize(sizes.size());
label start = 0;
forAll(patches_, patchI)
{
patches_[patchI] = surfGroup
(
names[patchI],
sizes[patchI],
start,
patchI
);
start += sizes[patchI];
}
}
template<class Face>
void Foam::MeshedSurface<Face>::addPatches
(
const UList<label>& sizes
)
{
patches_.setSize(sizes.size());
label start = 0;
forAll(patches_, patchI)
{
patches_[patchI] = surfGroup
(
word("patch") + ::Foam::name(patchI),
sizes[patchI],
start,
patchI
);
start += sizes[patchI];
}
}
template<class Face>
void Foam::MeshedSurface<Face>::transfer
(

View File

@ -276,6 +276,9 @@ public:
}
void addPatches(const UList<surfGroup>&);
void addPatches(const UList<word>& names, const UList<label>& sizes);
void addPatches(const UList<label>& sizes);
// Edit

View File

@ -106,12 +106,9 @@ bool Foam::fileFormats::AC3DsurfaceFormat<Face>::read
// Start of vertices for object/patch
label patchVertOffset = 0;
DynamicList<point> pointLst;
DynamicList<Face> faceLst;
DynamicList<label> regionLst;
// patchId => patchName
Map<word> regionNames;
DynamicList<point> dynPoints;
DynamicList<Face> dynFaces;
List<label> sizes(nPatches, 0);
for (label patchI = 0; patchI < nPatches; ++patchI)
{
@ -193,7 +190,7 @@ bool Foam::fileFormats::AC3DsurfaceFormat<Face>::read
>> pt.x() >> pt.y() >> pt.z();
// Offset with current translation vector
pointLst.append(location + pt);
dynPoints.append(location + pt);
}
}
else if (cmd == "numsurf")
@ -238,14 +235,14 @@ bool Foam::fileFormats::AC3DsurfaceFormat<Face>::read
fTri[1] = verts[fp1];
fTri[2] = verts[fp2];
faceLst.append(fTri);
regionLst.append(patchI);
dynFaces.append(fTri);
sizes[patchI]++;
}
}
else
{
faceLst.append(Face(f));
regionLst.append(patchI);
dynFaces.append(Face(f));
sizes[patchI]++;
}
}
@ -271,23 +268,79 @@ bool Foam::fileFormats::AC3DsurfaceFormat<Face>::read
}
// Done reading current patch
regionNames.insert(patchI, patchName);
break;
}
}
}
// transfer to normal lists
this->storedPoints().transfer(pointLst);
this->storedFaces().transfer(faceLst);
this->storedRegions().transfer(regionLst);
this->storedPoints().transfer(dynPoints);
this->storedFaces().transfer(dynFaces);
this->setPatches(regionNames);
this->addPatches(sizes);
this->stitchFaces(SMALL);
return true;
}
template<class Face>
void Foam::fileFormats::AC3DsurfaceFormat<Face>::write
(
Ostream& os,
const MeshedSurface<Face>& surf
)
{
const pointField& pointLst = surf.points();
const List<Face>& faceLst = surf.faces();
const List<surfGroup>& patchLst = surf.patches();
writeHeader(os, patchLst);
forAll(patchLst, patchI)
{
const surfGroup& p = patchLst[patchI];
os << "OBJECT poly" << nl
<< "name \"" << p.name() << '"' << endl;
// Temporary PrimitivePatch to calculate compact points & faces
// use 'UList' to avoid allocations!
PrimitivePatch<Face, UList, const pointField&> patch
(
faceLst,
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 Face& 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;
}
}
template<class Face>
void Foam::fileFormats::AC3DsurfaceFormat<Face>::write
(
@ -350,61 +403,4 @@ void Foam::fileFormats::AC3DsurfaceFormat<Face>::write
}
template<class Face>
void Foam::fileFormats::AC3DsurfaceFormat<Face>::write
(
Ostream& os,
const MeshedSurface<Face>& surf
)
{
const pointField& pointLst = surf.points();
const List<Face>& faceLst = surf.faces();
const List<surfGroup>& patchLst = surf.patches();
writeHeader(os, patchLst);
forAll(patchLst, patchI)
{
const surfGroup& p = patchLst[patchI];
os << "OBJECT poly" << nl
<< "name \"" << p.name() << '"' << endl;
// Temporary PrimitivePatch to calculate compact points & faces
// use 'UList' to avoid allocations!
PrimitivePatch<Face, UList, const pointField&> patch
(
faceLst,
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 Face& 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

@ -31,9 +31,7 @@ Description
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.
The faces are already organized as patches.
The output is always sorted by regions.
SourceFiles
@ -64,7 +62,7 @@ namespace fileFormats
template<class Face>
class AC3DsurfaceFormat
:
public UnsortedMeshedSurface<Face>,
public MeshedSurface<Face>,
public AC3DsurfaceFormatCore
{
// Private Member Functions
@ -85,12 +83,12 @@ public:
// Selectors
//- Read file and return surface
static autoPtr<UnsortedMeshedSurface<Face> > New
static autoPtr<MeshedSurface<Face> > New
(
const fileName& fName
)
{
return autoPtr<UnsortedMeshedSurface<Face> >
return autoPtr<MeshedSurface<Face> >
(
new AC3DsurfaceFormat<Face>(fName)
);

View File

@ -38,7 +38,7 @@ namespace fileFormats
addNamedTemplatedToRunTimeSelectionTable
(
UnsortedMeshedSurface,
MeshedSurface,
AC3DsurfaceFormat,
face,
fileExtension,
@ -46,7 +46,7 @@ addNamedTemplatedToRunTimeSelectionTable
);
addNamedTemplatedToRunTimeSelectionTable
(
UnsortedMeshedSurface,
MeshedSurface,
AC3DsurfaceFormat,
triFace,
fileExtension,

View File

@ -94,6 +94,36 @@ inline void Foam::fileFormats::STLsurfaceFormat<Face>::writeShell
}
// write sorted:
template<class Face>
void Foam::fileFormats::STLsurfaceFormat<Face>::writeASCII
(
Ostream& os,
const MeshedSurface<Face>& surf
)
{
const pointField& pointLst = surf.points();
const List<Face>& faceLst = surf.faces();
const List<surfGroup>& patchLst = surf.patches();
const vectorField& normLst = surf.faceNormals();
label faceIndex = 0;
forAll(patchLst, patchI)
{
// Print all faces belonging to this region
const surfGroup& 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 sorted:
template<class Face>
void Foam::fileFormats::STLsurfaceFormat<Face>::writeASCII
@ -136,86 +166,10 @@ void Foam::fileFormats::STLsurfaceFormat<Face>::writeASCII
os << "endsolid " << patch.name() << endl;
}
}
}
// write sorted:
template<class Face>
void Foam::fileFormats::STLsurfaceFormat<Face>::writeASCII
(
Ostream& os,
const MeshedSurface<Face>& surf
)
{
const pointField& pointLst = surf.points();
const List<Face>& faceLst = surf.faces();
const List<surfGroup>& patchLst = surf.patches();
const vectorField& normLst = surf.faceNormals();
label faceIndex = 0;
forAll(patchLst, patchI)
{
// Print all faces belonging to this region
const surfGroup& 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:
template<class Face>
void Foam::fileFormats::STLsurfaceFormat<Face>::writeBINARY
(
ostream& os,
const UnsortedMeshedSurface<Face>& surf
)
{
const pointField& pointLst = surf.points();
const List<Face>& faceLst = surf.faces();
const List<label>& regionLst = surf.regions();
const vectorField& normLst = surf.faceNormals();
unsigned int nTris = 0;
if (surf.isTri())
{
nTris = faceLst.size();
}
else
{
// count triangles for on-the-fly triangulation
forAll(faceLst, faceI)
{
nTris += faceLst[faceI].size() - 2;
}
}
// Write the STL header
STLsurfaceFormatCore::writeHeaderBINARY(os, nTris);
// always write unsorted
forAll(faceLst, faceI)
{
writeShell
(
os,
pointLst,
faceLst[faceI],
normLst[faceI],
regionLst[faceI]
);
}
}
template<class Face>
void Foam::fileFormats::STLsurfaceFormat<Face>::writeBINARY
(
@ -265,6 +219,51 @@ void Foam::fileFormats::STLsurfaceFormat<Face>::writeBINARY
}
// write unsorted:
template<class Face>
void Foam::fileFormats::STLsurfaceFormat<Face>::writeBINARY
(
ostream& os,
const UnsortedMeshedSurface<Face>& surf
)
{
const pointField& pointLst = surf.points();
const List<Face>& faceLst = surf.faces();
const List<label>& regionLst = surf.regions();
const vectorField& normLst = surf.faceNormals();
unsigned int nTris = 0;
if (surf.isTri())
{
nTris = faceLst.size();
}
else
{
// count triangles for on-the-fly triangulation
forAll(faceLst, faceI)
{
nTris += faceLst[faceI].size() - 2;
}
}
// Write the STL header
STLsurfaceFormatCore::writeHeaderBINARY(os, nTris);
// always write unsorted
forAll(faceLst, faceI)
{
writeShell
(
os,
pointLst,
faceLst[faceI],
normLst[faceI],
regionLst[faceI]
);
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
template<class Face>
@ -293,67 +292,51 @@ bool Foam::fileFormats::STLsurfaceFormat<Face>::read
// transfer points
this->storedPoints().transfer(reader.points());
// get the original region information
// retrieve the original region information
List<word> names(xferMove(reader.names()));
List<label> unsortedRegions(xferMove(reader.regions()));
List<label> sizes(xferMove(reader.sizes()));
List<label> regions(xferMove(reader.regions()));
// and determine the sorted order:
// avoid SortableList since we discard the main list anyhow
List<label> faceMap;
sortedOrder(unsortedRegions, faceMap);
// generate the (sorted) faces
List<Face> faceLst(regions.size());
// generate the sorted faces and sorted regions:
List<Face> faceLst(faceMap.size());
DynamicList<label> dynPatchSizes;
label prevRegion = -1;
label regionSize = 0;
forAll(faceMap, faceI)
if (reader.sorted())
{
const label startPt = 3*faceMap[faceI];
const label regionI = unsortedRegions[faceMap[faceI]];
faceLst[faceI] = triFace(startPt, startPt+1, startPt+2);
if (prevRegion != regionI)
// already sorted - generate directly
forAll(faceLst, faceI)
{
if (regionSize)
{
dynPatchSizes.append(regionSize);
}
prevRegion = regionI;
regionSize = 0;
const label startPt = 3*faceI;
faceLst[faceI] = triFace(startPt, startPt+1, startPt+2);
}
regionSize++;
}
if (regionSize)
else
{
dynPatchSizes.append(regionSize);
// unsorted - determine the sorted order:
// avoid SortableList since we discard the main list anyhow
List<label> faceMap;
sortedOrder(regions, faceMap);
// generate sorted faces
forAll(faceMap, faceI)
{
const label startPt = 3*faceMap[faceI];
faceLst[faceI] = triFace(startPt, startPt+1, startPt+2);
}
}
regions.clear();
// transfer:
this->storedFaces().transfer(faceLst);
unsortedRegions.clear();
faceMap.clear();
label start = 0;
surfGroupList newPatches(dynPatchSizes.size());
forAll(newPatches, patchI)
if (names.size())
{
newPatches[patchI] = surfGroup
(
names[patchI],
dynPatchSizes[patchI],
start,
patchI
);
start += dynPatchSizes[patchI];
this->addPatches(names, sizes);
}
else
{
this->addPatches(names, sizes);
}
this->addPatches(newPatches);
this->stitchFaces(SMALL);
return true;
}

View File

@ -72,6 +72,7 @@ class STLASCIILexer
{
// Private data
bool sorted_;
label groupID_; // current region
label lineNo_;
word startError_;
@ -79,7 +80,8 @@ class STLASCIILexer
DynamicList<point> points_;
DynamicList<label> facets_;
DynamicList<word> names_;
HashTable<label> nameIndex_;
DynamicList<label> sizes_;
HashTable<label> lookup_;
public:
@ -96,6 +98,12 @@ public:
// Access
//- Do all the solid groups appear in order
bool sorted() const
{
return sorted_;
}
//- A list of points corresponding to a pointField
DynamicList<point>& points()
{
@ -114,12 +122,19 @@ public:
{
return names_;
}
//- region sizes
DynamicList<label>& sizes()
{
return sizes_;
}
};
STLASCIILexer::STLASCIILexer(istream* is, const label approxNpoints)
:
yyFlexLexer(is),
sorted_(true),
groupID_(-1),
lineNo_(1),
points_(approxNpoints),
@ -237,16 +252,22 @@ endsolid {space}("endsolid"|"ENDSOLID")({some_space}{word})*
<readSolidName>{string} {
word name(Foam::string::validate<word>(YYText()));
HashTable<label>::const_iterator fnd = nameIndex_.find(name);
if (fnd != nameIndex_.end())
HashTable<label>::const_iterator fnd = lookup_.find(name);
if (fnd != lookup_.end())
{
if (groupID_ != fnd())
{
// group appeared out of order
sorted_ = false;
}
groupID_ = fnd();
}
else
{
groupID_ = names_.size();
groupID_ = sizes_.size();
lookup_.insert(name, groupID_);
names_.append(name);
nameIndex_.insert(name, groupID_);
sizes_.append(0);
}
BEGIN(INITIAL);
}
@ -254,16 +275,22 @@ endsolid {space}("endsolid"|"ENDSOLID")({some_space}{word})*
<readSolidName>{space}\n {
word name("solid");
HashTable<label>::const_iterator fnd = nameIndex_.find(name);
if (fnd != nameIndex_.end())
HashTable<label>::const_iterator fnd = lookup_.find(name);
if (fnd != lookup_.end())
{
if (groupID_ != fnd())
{
// group appeared out of order
sorted_ = false;
}
groupID_ = fnd();
}
else
{
groupID_ = names_.size();
groupID_ = sizes_.size();
lookup_.insert(name, groupID_);
names_.append(name);
nameIndex_.insert(name, groupID_);
sizes_.append(0);
}
lineNo_++;
@ -328,6 +355,7 @@ endsolid {space}("endsolid"|"ENDSOLID")({some_space}{word})*
<readFacet>{endfacet} {
facets_.append(groupID_);
sizes_[groupID_]++;
BEGIN(INITIAL);
}
@ -380,17 +408,18 @@ bool Foam::fileFormats::STLsurfaceFormatCore::readASCII
const off_t fileSize
)
{
binary_ = false;
// 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) {}
sorted_ = lexer.sorted();
// transfer to normal lists
points_.transfer(lexer.points());
regions_.transfer(lexer.facets());
names_.transfer(lexer.names());
sizes_.transfer(lexer.sizes());
return true;
}

View File

@ -92,7 +92,7 @@ bool Foam::fileFormats::STLsurfaceFormatCore::readBINARY
const off_t fileSize
)
{
binary_ = true;
sorted_ = true;
istream& is = ifs.stdStream();
// Read the STL header
@ -144,10 +144,11 @@ bool Foam::fileFormats::STLsurfaceFormatCore::readBINARY
points_.setSize(3*nTris);
regions_.setSize(nTris);
Map<label> regionToPatch;
DynamicList<word> dynNames;
Map<label> lookup;
DynamicList<label> dynSizes;
label ptI = 0;
label regionI = -1;
forAll(regions_, faceI)
{
// Read an STL triangle
@ -161,20 +162,25 @@ bool Foam::fileFormats::STLsurfaceFormatCore::readBINARY
// interprete colour as a region
const label stlRegion = stlTri.region();
Map<label>::const_iterator fnd = regionToPatch.find(stlRegion);
label regionI;
if (fnd != regionToPatch.end())
Map<label>::const_iterator fnd = lookup.find(stlRegion);
if (fnd != lookup.end())
{
if (regionI != fnd())
{
// group appeared out of order
sorted_ = false;
}
regionI = fnd();
}
else
{
regionI = dynNames.size();
dynNames.append(word("patch") + ::Foam::name(regionI));
regionToPatch.insert(stlRegion, regionI);
regionI = dynSizes.size();
lookup.insert(stlRegion, regionI);
dynSizes.append(0);
}
regions_[faceI] = regionI;
dynSizes[regionI]++;
#ifdef DEBUG_STLBINARY
if (prevRegion != regionI)
@ -198,7 +204,8 @@ bool Foam::fileFormats::STLsurfaceFormatCore::readBINARY
#endif
}
names_.transfer(dynNames);
names_.clear();
sizes_.transfer(dynSizes);
return true;
}
@ -211,10 +218,11 @@ Foam::fileFormats::STLsurfaceFormatCore::STLsurfaceFormatCore
const fileName& fName
)
:
binary_(false),
sorted_(true),
points_(0),
regions_(0),
names_(0)
names_(0),
sizes_(0)
{
off_t fileSize = Foam::size(fName);

View File

@ -59,7 +59,7 @@ class STLsurfaceFormatCore
{
// Private Data
bool binary_;
bool sorted_;
//- The points supporting the facets
pointField points_;
@ -70,6 +70,9 @@ class STLsurfaceFormatCore
//- The solid names, in the order of their first appearance
List<word> names_;
//- The solid count, in the order of their first appearance
List<label> sizes_;
// Private Member Functions
//- Disallow default bitwise copy construct
@ -81,10 +84,10 @@ class STLsurfaceFormatCore
//- Determine the file type
static int detectBINARY(const fileName&);
//- Read ASCII, set groupToPatch
//- Read ASCII
bool readASCII(IFstream&, const off_t);
//- Read BINARY, set maxRegionId
//- Read BINARY
bool readBINARY(IFstream&, const off_t);
public:
@ -110,27 +113,23 @@ public:
// Member Functions
//- File was detected to be STL binary
bool binary() const
//- File read was already sorted
bool sorted() const
{
return binary_;
}
//- The number of facets is the number of regions
label size() const
{
return regions_.size();
return sorted_;
}
//- Flush all values
void clear()
{
sorted_ = true;
points_.clear();
regions_.clear();
names_.clear();
sizes_.clear();
}
//- Return full access to the faces
//- Return full access to the points
pointField& points()
{
return points_;
@ -148,6 +147,12 @@ public:
return names_;
}
//- The list of solid sizes in the order of their first appearance
List<label>& sizes()
{
return sizes_;
}
};

View File

@ -25,9 +25,7 @@ License
\*---------------------------------------------------------------------------*/
#include "TRIsurfaceFormat.H"
#include "IFstream.H"
#include "IOmanip.H"
#include "IStringStream.H"
#include "ListOps.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
@ -83,121 +81,76 @@ bool Foam::fileFormats::TRIsurfaceFormat<Face>::read
{
this->clear();
IFstream is(fName);
if (!is.good())
// read in the values
TRIsurfaceFormatCore reader(fName);
// transfer points
this->storedPoints().transfer(reader.points());
// retrieve the original region information
List<label> sizes(xferMove(reader.sizes()));
List<label> regions(xferMove(reader.regions()));
// generate the (sorted) faces
List<Face> faceLst(regions.size());
if (reader.sorted())
{
FatalErrorIn
(
"fileFormats::TRIsurfaceFormat::read(const fileName&)"
)
<< "Cannot read file " << fName
<< exit(FatalError);
}
// uses similar structure as STL, just some points
DynamicList<point> pointLst;
DynamicList<label> regionLst;
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 = this->getLineNoComment(is);
// handle continuations ?
// if (line[line.size()-1] == '\\')
// {
// line.substr(0, line.size()-1);
// line += this->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 fnd = groupToPatch.find(groupName);
if (fnd != groupToPatch.end())
// already sorted - generate directly
forAll(faceLst, faceI)
{
groupID = fnd();
const label startPt = 3*faceI;
faceLst[faceI] = triFace(startPt, startPt+1, startPt+2);
}
else
{
// special treatment if any initial faces were not in a group
if (maxGroupID == -1 && regionLst.size())
{
groupToPatch.insert("patch0", 0);
nUngrouped = regionLst.size();
maxGroupID = 0;
}
groupID = ++maxGroupID;
groupToPatch.insert(groupName, groupID);
}
regionLst.append(groupID);
}
// make our triangles directly
List<Face>& faceLst = this->storedFaces();
faceLst.setSize(regionLst.size());
// transfer to normal list
this->storedPoints().transfer(pointLst);
this->storedRegions().transfer(regionLst);
forAll(faceLst, faceI)
else
{
const label startPt = 3 * faceI;
faceLst[faceI] = triFace(startPt, startPt+1, startPt+2);
}
// unsorted - determine the sorted order:
// avoid SortableList since we discard the main list anyhow
List<label> faceMap;
sortedOrder(regions, faceMap);
this->setPatches(groupToPatch);
// generate sorted faces
forAll(faceMap, faceI)
{
const label startPt = 3*faceMap[faceI];
faceLst[faceI] = triFace(startPt, startPt+1, startPt+2);
}
}
regions.clear();
// transfer:
this->storedFaces().transfer(faceLst);
this->addPatches(sizes);
this->stitchFaces(SMALL);
return true;
}
template<class Face>
void Foam::fileFormats::TRIsurfaceFormat<Face>::write
(
Ostream& os,
const MeshedSurface<Face>& surf
)
{
const pointField& pointLst = surf.points();
const List<Face>& faceLst = surf.faces();
const List<surfGroup>& patchLst = surf.patches();
label faceIndex = 0;
forAll(patchLst, patchI)
{
forAll(patchLst[patchI], patchFaceI)
{
const Face& f = faceLst[faceIndex++];
writeShell(os, pointLst, f, patchI);
}
}
}
template<class Face>
void Foam::fileFormats::TRIsurfaceFormat<Face>::write
(
@ -241,27 +194,4 @@ void Foam::fileFormats::TRIsurfaceFormat<Face>::write
}
}
template<class Face>
void Foam::fileFormats::TRIsurfaceFormat<Face>::write
(
Ostream& os,
const MeshedSurface<Face>& surf
)
{
const pointField& pointLst = surf.points();
const List<Face>& faceLst = surf.faces();
const List<surfGroup>& patchLst = surf.patches();
label faceIndex = 0;
forAll(patchLst, patchI)
{
forAll(patchLst[patchI], patchFaceI)
{
const Face& f = faceLst[faceIndex++];
writeShell(os, pointLst, f, patchI);
}
}
}
// ************************************************************************* //

View File

@ -28,6 +28,10 @@ Class
Description
Provide a means of reading/writing .tri format.
Note
For efficiency, the regions are sorted before creating the faces.
The class is thus derived from MeshedSurface.
SourceFiles
TRIsurfaceFormat.C
@ -36,6 +40,7 @@ SourceFiles
#ifndef TRIsurfaceFormat_H
#define TRIsurfaceFormat_H
#include "TRIsurfaceFormatCore.H"
#include "Ostream.H"
#include "OFstream.H"
#include "MeshedSurface.H"
@ -49,13 +54,13 @@ namespace fileFormats
{
/*---------------------------------------------------------------------------*\
Class TRIsurfaceFormat Declaration
Class TRIsurfaceFormat Declaration
\*---------------------------------------------------------------------------*/
template<class Face>
class TRIsurfaceFormat
:
public UnsortedMeshedSurface<Face>
public MeshedSurface<Face>
{
// Private Member Functions
@ -83,12 +88,12 @@ public:
// Selectors
//- Read file and return surface
static autoPtr<UnsortedMeshedSurface<Face> > New
static autoPtr<MeshedSurface<Face> > New
(
const fileName& fName
)
{
return autoPtr<UnsortedMeshedSurface<Face> >
return autoPtr<MeshedSurface<Face> >
(
new TRIsurfaceFormat<Face>(fName)
);
@ -140,7 +145,6 @@ public:
}
//- Write object
// By default, the output is not sorted by regions
virtual void write(Ostream& os) const
{
write(os, *this);

View File

@ -0,0 +1,182 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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 "TRIsurfaceFormat.H"
#include "IFstream.H"
#include "IOmanip.H"
#include "IStringStream.H"
#include "Map.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::fileFormats::TRIsurfaceFormatCore::TRIsurfaceFormatCore
(
const fileName& fName
)
:
sorted_(true),
points_(0),
regions_(0),
sizes_(0)
{
read(fName);
}
// * * * * * * * * * * * * * * * * Destructors * * * * * * * * * * * * * * * //
Foam::fileFormats::TRIsurfaceFormatCore::~TRIsurfaceFormatCore()
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
bool Foam::fileFormats::TRIsurfaceFormatCore::read
(
const fileName& fName
)
{
this->clear();
sorted_ = true;
IFstream is(fName);
if (!is.good())
{
FatalErrorIn
(
"fileFormats::TRIsurfaceFormatCore::read(const fileName&)"
)
<< "Cannot read file " << fName
<< exit(FatalError);
}
// uses similar structure as STL, just some points
// the rest of the reader resembles the STL binary reader
DynamicList<point> dynPoints;
DynamicList<label> dynRegions;
DynamicList<label> dynSizes;
HashTable<label> lookup;
// place faces without a group in patch0
label regionI = 0;
dynSizes.append(regionI);
lookup.insert("patch0", regionI);
while (is.good())
{
string line = this->getLineNoComment(is);
// handle continuations ?
// if (line[line.size()-1] == '\\')
// {
// line.substr(0, line.size()-1);
// line += this->getLineNoComment(is);
// }
IStringStream lineStream(line);
point p
(
readScalar(lineStream),
readScalar(lineStream),
readScalar(lineStream)
);
if (!lineStream) break;
dynPoints.append(p);
dynPoints.append
(
point
(
readScalar(lineStream),
readScalar(lineStream),
readScalar(lineStream)
)
);
dynPoints.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 name("patch" + rawName(1, rawName.size()-1));
HashTable<label>::const_iterator fnd = lookup.find(name);
if (fnd != lookup.end())
{
if (regionI != fnd())
{
// group appeared out of order
sorted_ = false;
}
regionI = fnd();
}
else
{
regionI = dynSizes.size();
lookup.insert(name, regionI);
dynSizes.append(0);
}
dynRegions.append(regionI);
dynSizes[regionI]++;
}
// transfer to normal lists
points_.transfer(dynPoints);
regions_.transfer(dynRegions);
if (dynSizes[0] == 0)
{
// no ungrouped patches, copy sub-list
sizes_ = SubList<label>(dynSizes, dynSizes.size()-1, 1);
}
else
{
sizes_.transfer(dynSizes);
}
return true;
}
// ************************************************************************* //

View File

@ -0,0 +1,143 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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::TRIsurfaceFormatCore
Description
Internal class used by the TRIsurfaceFormat
SourceFiles
TRIsurfaceFormatCore.C
\*---------------------------------------------------------------------------*/
#ifndef TRIsurfaceFormatCore_H
#define TRIsurfaceFormatCore_H
#include "surfaceFormatsCore.H"
#include "triFace.H"
#include "IFstream.H"
#include "Ostream.H"
#include "OFstream.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace fileFormats
{
/*---------------------------------------------------------------------------*\
Class TRIsurfaceFormatCore Declaration
\*---------------------------------------------------------------------------*/
class TRIsurfaceFormatCore
:
public surfaceFormatsCore
{
// Private Data
bool sorted_;
//- The points supporting the facets
pointField points_;
//- The regions associated with the faces
List<label> regions_;
//- The solid count, in the order of their first appearance
List<label> sizes_;
// Private Member Functions
//- Disallow default bitwise copy construct
TRIsurfaceFormatCore(const TRIsurfaceFormatCore&);
//- Disallow default bitwise assignment
void operator=(const TRIsurfaceFormatCore&);
bool read(const fileName&);
public:
// Constructors
//- Read from file, filling in the information
TRIsurfaceFormatCore(const fileName&);
// Destructor
~TRIsurfaceFormatCore();
// Member Functions
//- File read was already sorted
bool sorted() const
{
return sorted_;
}
//- Flush all values
void clear()
{
sorted_ = true;
points_.clear();
regions_.clear();
sizes_.clear();
}
//- Return full access to the points
pointField& points()
{
return points_;
}
//- Return full access to the regions
List<label>& regions()
{
return regions_;
}
//- The list of region sizes in the order of their first appearance
List<label>& sizes()
{
return sizes_;
}
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace fileFormats
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -38,7 +38,7 @@ namespace fileFormats
addNamedTemplatedToRunTimeSelectionTable
(
UnsortedMeshedSurface,
MeshedSurface,
TRIsurfaceFormat,
face,
fileExtension,
@ -46,7 +46,7 @@ addNamedTemplatedToRunTimeSelectionTable
);
addNamedTemplatedToRunTimeSelectionTable
(
UnsortedMeshedSurface,
MeshedSurface,
TRIsurfaceFormat,
triFace,
fileExtension,