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/STLsurfaceFormatCore.C
$(surfaceFormats)/stl/STLsurfaceFormatRunTime.C $(surfaceFormats)/stl/STLsurfaceFormatRunTime.C
$(surfaceFormats)/stl/STLsurfaceFormatASCII.L $(surfaceFormats)/stl/STLsurfaceFormatASCII.L
$(surfaceFormats)/tri/TRIsurfaceFormatCore.C
$(surfaceFormats)/tri/TRIsurfaceFormatRunTime.C $(surfaceFormats)/tri/TRIsurfaceFormatRunTime.C
$(surfaceFormats)/vtk/VTKsurfaceFormatCore.C $(surfaceFormats)/vtk/VTKsurfaceFormatCore.C
$(surfaceFormats)/vtk/VTKsurfaceFormatRunTime.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> template<class Face>
void Foam::MeshedSurface<Face>::transfer void Foam::MeshedSurface<Face>::transfer
( (

View File

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

View File

@ -106,12 +106,9 @@ bool Foam::fileFormats::AC3DsurfaceFormat<Face>::read
// Start of vertices for object/patch // Start of vertices for object/patch
label patchVertOffset = 0; label patchVertOffset = 0;
DynamicList<point> pointLst; DynamicList<point> dynPoints;
DynamicList<Face> faceLst; DynamicList<Face> dynFaces;
DynamicList<label> regionLst; List<label> sizes(nPatches, 0);
// patchId => patchName
Map<word> regionNames;
for (label patchI = 0; patchI < nPatches; ++patchI) for (label patchI = 0; patchI < nPatches; ++patchI)
{ {
@ -193,7 +190,7 @@ bool Foam::fileFormats::AC3DsurfaceFormat<Face>::read
>> pt.x() >> pt.y() >> pt.z(); >> pt.x() >> pt.y() >> pt.z();
// Offset with current translation vector // Offset with current translation vector
pointLst.append(location + pt); dynPoints.append(location + pt);
} }
} }
else if (cmd == "numsurf") else if (cmd == "numsurf")
@ -238,14 +235,14 @@ bool Foam::fileFormats::AC3DsurfaceFormat<Face>::read
fTri[1] = verts[fp1]; fTri[1] = verts[fp1];
fTri[2] = verts[fp2]; fTri[2] = verts[fp2];
faceLst.append(fTri); dynFaces.append(fTri);
regionLst.append(patchI); sizes[patchI]++;
} }
} }
else else
{ {
faceLst.append(Face(f)); dynFaces.append(Face(f));
regionLst.append(patchI); sizes[patchI]++;
} }
} }
@ -271,23 +268,79 @@ bool Foam::fileFormats::AC3DsurfaceFormat<Face>::read
} }
// Done reading current patch // Done reading current patch
regionNames.insert(patchI, patchName);
break; break;
} }
} }
} }
// transfer to normal lists // transfer to normal lists
this->storedPoints().transfer(pointLst); this->storedPoints().transfer(dynPoints);
this->storedFaces().transfer(faceLst); this->storedFaces().transfer(dynFaces);
this->storedRegions().transfer(regionLst);
this->setPatches(regionNames); this->addPatches(sizes);
this->stitchFaces(SMALL); this->stitchFaces(SMALL);
return true; 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> template<class Face>
void Foam::fileFormats::AC3DsurfaceFormat<Face>::write 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 http://www.inivis.com/ac3d/man/ac3dfileformat.html
Note Note
Since the faces are already organized as patches, the reader could be The faces are already organized as patches.
optimized for this, but at expense of losing a common reading approach.
The output is always sorted by regions. The output is always sorted by regions.
SourceFiles SourceFiles
@ -64,7 +62,7 @@ namespace fileFormats
template<class Face> template<class Face>
class AC3DsurfaceFormat class AC3DsurfaceFormat
: :
public UnsortedMeshedSurface<Face>, public MeshedSurface<Face>,
public AC3DsurfaceFormatCore public AC3DsurfaceFormatCore
{ {
// Private Member Functions // Private Member Functions
@ -85,12 +83,12 @@ public:
// Selectors // Selectors
//- Read file and return surface //- Read file and return surface
static autoPtr<UnsortedMeshedSurface<Face> > New static autoPtr<MeshedSurface<Face> > New
( (
const fileName& fName const fileName& fName
) )
{ {
return autoPtr<UnsortedMeshedSurface<Face> > return autoPtr<MeshedSurface<Face> >
( (
new AC3DsurfaceFormat<Face>(fName) new AC3DsurfaceFormat<Face>(fName)
); );

View File

@ -38,7 +38,7 @@ namespace fileFormats
addNamedTemplatedToRunTimeSelectionTable addNamedTemplatedToRunTimeSelectionTable
( (
UnsortedMeshedSurface, MeshedSurface,
AC3DsurfaceFormat, AC3DsurfaceFormat,
face, face,
fileExtension, fileExtension,
@ -46,7 +46,7 @@ addNamedTemplatedToRunTimeSelectionTable
); );
addNamedTemplatedToRunTimeSelectionTable addNamedTemplatedToRunTimeSelectionTable
( (
UnsortedMeshedSurface, MeshedSurface,
AC3DsurfaceFormat, AC3DsurfaceFormat,
triFace, triFace,
fileExtension, 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: // write sorted:
template<class Face> template<class Face>
void Foam::fileFormats::STLsurfaceFormat<Face>::writeASCII void Foam::fileFormats::STLsurfaceFormat<Face>::writeASCII
@ -136,86 +166,10 @@ void Foam::fileFormats::STLsurfaceFormat<Face>::writeASCII
os << "endsolid " << patch.name() << endl; 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> template<class Face>
void Foam::fileFormats::STLsurfaceFormat<Face>::writeBINARY 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 * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
template<class Face> template<class Face>
@ -293,67 +292,51 @@ bool Foam::fileFormats::STLsurfaceFormat<Face>::read
// transfer points // transfer points
this->storedPoints().transfer(reader.points()); this->storedPoints().transfer(reader.points());
// get the original region information // retrieve the original region information
List<word> names(xferMove(reader.names())); 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: // generate the (sorted) faces
// avoid SortableList since we discard the main list anyhow List<Face> faceLst(regions.size());
List<label> faceMap;
sortedOrder(unsortedRegions, faceMap);
// generate the sorted faces and sorted regions: if (reader.sorted())
List<Face> faceLst(faceMap.size());
DynamicList<label> dynPatchSizes;
label prevRegion = -1;
label regionSize = 0;
forAll(faceMap, faceI)
{ {
const label startPt = 3*faceMap[faceI]; // already sorted - generate directly
const label regionI = unsortedRegions[faceMap[faceI]]; forAll(faceLst, faceI)
faceLst[faceI] = triFace(startPt, startPt+1, startPt+2);
if (prevRegion != regionI)
{ {
if (regionSize) const label startPt = 3*faceI;
{ faceLst[faceI] = triFace(startPt, startPt+1, startPt+2);
dynPatchSizes.append(regionSize);
}
prevRegion = regionI;
regionSize = 0;
} }
regionSize++;
} }
else
if (regionSize)
{ {
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: // transfer:
this->storedFaces().transfer(faceLst); this->storedFaces().transfer(faceLst);
unsortedRegions.clear();
faceMap.clear();
label start = 0; if (names.size())
surfGroupList newPatches(dynPatchSizes.size());
forAll(newPatches, patchI)
{ {
newPatches[patchI] = surfGroup this->addPatches(names, sizes);
( }
names[patchI], else
dynPatchSizes[patchI], {
start, this->addPatches(names, sizes);
patchI
);
start += dynPatchSizes[patchI];
} }
this->addPatches(newPatches);
this->stitchFaces(SMALL); this->stitchFaces(SMALL);
return true; return true;
} }

View File

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

View File

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

View File

@ -59,7 +59,7 @@ class STLsurfaceFormatCore
{ {
// Private Data // Private Data
bool binary_; bool sorted_;
//- The points supporting the facets //- The points supporting the facets
pointField points_; pointField points_;
@ -70,6 +70,9 @@ class STLsurfaceFormatCore
//- The solid names, in the order of their first appearance //- The solid names, in the order of their first appearance
List<word> names_; List<word> names_;
//- The solid count, in the order of their first appearance
List<label> sizes_;
// Private Member Functions // Private Member Functions
//- Disallow default bitwise copy construct //- Disallow default bitwise copy construct
@ -81,10 +84,10 @@ class STLsurfaceFormatCore
//- Determine the file type //- Determine the file type
static int detectBINARY(const fileName&); static int detectBINARY(const fileName&);
//- Read ASCII, set groupToPatch //- Read ASCII
bool readASCII(IFstream&, const off_t); bool readASCII(IFstream&, const off_t);
//- Read BINARY, set maxRegionId //- Read BINARY
bool readBINARY(IFstream&, const off_t); bool readBINARY(IFstream&, const off_t);
public: public:
@ -110,27 +113,23 @@ public:
// Member Functions // Member Functions
//- File was detected to be STL binary //- File read was already sorted
bool binary() const bool sorted() const
{ {
return binary_; return sorted_;
}
//- The number of facets is the number of regions
label size() const
{
return regions_.size();
} }
//- Flush all values //- Flush all values
void clear() void clear()
{ {
sorted_ = true;
points_.clear(); points_.clear();
regions_.clear(); regions_.clear();
names_.clear(); names_.clear();
sizes_.clear();
} }
//- Return full access to the faces //- Return full access to the points
pointField& points() pointField& points()
{ {
return points_; return points_;
@ -148,6 +147,12 @@ public:
return names_; 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 "TRIsurfaceFormat.H"
#include "IFstream.H" #include "ListOps.H"
#include "IOmanip.H"
#include "IStringStream.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
@ -83,121 +81,76 @@ bool Foam::fileFormats::TRIsurfaceFormat<Face>::read
{ {
this->clear(); this->clear();
IFstream is(fName); // read in the values
if (!is.good()) 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 // already sorted - generate directly
( forAll(faceLst, faceI)
"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())
{ {
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);
} }
else
// 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)
{ {
const label startPt = 3 * faceI; // unsorted - determine the sorted order:
faceLst[faceI] = triFace(startPt, startPt+1, startPt+2); // 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); this->stitchFaces(SMALL);
return true; 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> template<class Face>
void Foam::fileFormats::TRIsurfaceFormat<Face>::write 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 Description
Provide a means of reading/writing .tri format. 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 SourceFiles
TRIsurfaceFormat.C TRIsurfaceFormat.C
@ -36,6 +40,7 @@ SourceFiles
#ifndef TRIsurfaceFormat_H #ifndef TRIsurfaceFormat_H
#define TRIsurfaceFormat_H #define TRIsurfaceFormat_H
#include "TRIsurfaceFormatCore.H"
#include "Ostream.H" #include "Ostream.H"
#include "OFstream.H" #include "OFstream.H"
#include "MeshedSurface.H" #include "MeshedSurface.H"
@ -49,13 +54,13 @@ namespace fileFormats
{ {
/*---------------------------------------------------------------------------*\ /*---------------------------------------------------------------------------*\
Class TRIsurfaceFormat Declaration Class TRIsurfaceFormat Declaration
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
template<class Face> template<class Face>
class TRIsurfaceFormat class TRIsurfaceFormat
: :
public UnsortedMeshedSurface<Face> public MeshedSurface<Face>
{ {
// Private Member Functions // Private Member Functions
@ -83,12 +88,12 @@ public:
// Selectors // Selectors
//- Read file and return surface //- Read file and return surface
static autoPtr<UnsortedMeshedSurface<Face> > New static autoPtr<MeshedSurface<Face> > New
( (
const fileName& fName const fileName& fName
) )
{ {
return autoPtr<UnsortedMeshedSurface<Face> > return autoPtr<MeshedSurface<Face> >
( (
new TRIsurfaceFormat<Face>(fName) new TRIsurfaceFormat<Face>(fName)
); );
@ -140,7 +145,6 @@ public:
} }
//- Write object //- Write object
// By default, the output is not sorted by regions
virtual void write(Ostream& os) const virtual void write(Ostream& os) const
{ {
write(os, *this); 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 addNamedTemplatedToRunTimeSelectionTable
( (
UnsortedMeshedSurface, MeshedSurface,
TRIsurfaceFormat, TRIsurfaceFormat,
face, face,
fileExtension, fileExtension,
@ -46,7 +46,7 @@ addNamedTemplatedToRunTimeSelectionTable
); );
addNamedTemplatedToRunTimeSelectionTable addNamedTemplatedToRunTimeSelectionTable
( (
UnsortedMeshedSurface, MeshedSurface,
TRIsurfaceFormat, TRIsurfaceFormat,
triFace, triFace,
fileExtension, fileExtension,