1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM is free software: you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by
13 the Free Software Foundation, either version 3 of the License, or
14 (at your option) any later version.
16 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
24 \*---------------------------------------------------------------------------*/
26 #include "STLsurfaceFormatCore.H"
28 #include "OSspecific.H"
33 #undef DEBUG_STLBINARY
35 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
37 // check binary by getting the header and number of facets
38 // this seems to work better than the old token-based method
39 // - some programs (eg, pro-STAR) have 'solid' as the first word in
41 // - using wordToken can cause an abort if non-word (binary) content
42 // is detected ... this is not exactly what we want.
43 int Foam::fileFormats::STLsurfaceFormatCore::detectBINARY
45 const fileName& filename
48 off_t dataFileSize = Foam::fileSize(filename);
50 IFstream str(filename, IOstream::BINARY);
51 istream& is = str().stdStream();
53 // Read the STL header
54 char header[headerSize];
55 is.read(header, headerSize);
57 // Check that stream is OK, if not this may be an ASCII file
63 // Read the number of triangles in the STl file
64 // (note: read as int so we can check whether >2^31)
66 is.read(reinterpret_cast<char*>(&nTris), sizeof(unsigned int));
68 // Check that stream is OK and number of triangles is positive,
69 // if not this may be an ASCII file
71 // Also compare the file size with that expected from the number of tris
72 // If the comparison is not sensible then it may be an ASCII file
77 || nTris < (dataFileSize - headerSize)/50
78 || nTris > (dataFileSize - headerSize)/25
84 // looks like it might be BINARY, return number of triangles
89 bool Foam::fileFormats::STLsurfaceFormatCore::readBINARY
92 const off_t dataFileSize
97 // Read the STL header
98 char header[headerSize];
99 is.read(header, headerSize);
101 // Check that stream is OK, if not this may be an ASCII file
106 "fileFormats::STLsurfaceFormatCore::readBINARY(IFstream&)"
108 << "problem reading header, perhaps file is not binary "
112 // Read the number of triangles in the STl file
113 // (note: read as int so we can check whether >2^31)
115 is.read(reinterpret_cast<char*>(&nTris), sizeof(unsigned int));
117 // Check that stream is OK and number of triangles is positive,
118 // if not this maybe an ASCII file
120 // Also compare the file size with that expected from the number of tris
121 // If the comparison is not sensible then it may be an ASCII file
126 || nTris < int(dataFileSize - headerSize)/50
127 || nTris > int(dataFileSize - headerSize)/25
132 "fileFormats::STLsurfaceFormatCore::readBINARY(istream&)"
134 << "problem reading number of triangles, perhaps file is not binary"
138 #ifdef DEBUG_STLBINARY
139 Info<< "# " << nTris << " facets" << endl;
143 points_.setSize(3*nTris);
144 zoneIds_.setSize(nTris);
147 DynamicList<label> dynSizes;
151 forAll(zoneIds_, faceI)
153 // Read an STL triangle
154 STLtriangle stlTri(is);
156 // transcribe the vertices of the STL triangle -> points
157 points_[ptI++] = stlTri.a();
158 points_[ptI++] = stlTri.b();
159 points_[ptI++] = stlTri.c();
161 // interprete stl attribute as a zone
162 const label origId = stlTri.attrib();
164 Map<label>::const_iterator fnd = lookup.find(origId);
165 if (fnd != lookup.end())
169 // group appeared out of order
176 zoneI = dynSizes.size();
177 lookup.insert(origId, zoneI);
181 zoneIds_[faceI] = zoneI;
184 #ifdef DEBUG_STLBINARY
185 if (prevZone != zoneI)
189 Info<< "endsolid zone" << prevZone << nl;
193 Info<< "solid zone" << prevZone << nl;
196 Info<< " facet normal " << stlTri.normal() << nl
197 << " outer loop" << nl
198 << " vertex " << stlTri.a() << nl
199 << " vertex " << stlTri.b() << nl
200 << " vertex " << stlTri.c() << nl
201 << " outer loop" << nl
202 << " endfacet" << endl;
207 sizes_.transfer(dynSizes);
213 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
215 Foam::fileFormats::STLsurfaceFormatCore::STLsurfaceFormatCore
217 const fileName& filename
226 off_t dataFileSize = Foam::fileSize(filename);
228 // auto-detect ascii/binary
229 if (detectBINARY(filename))
233 IFstream(filename, IOstream::BINARY)().stdStream(),
241 IFstream(filename)().stdStream(),
248 // * * * * * * * * * * * * * * * * Destructors * * * * * * * * * * * * * * * //
250 Foam::fileFormats::STLsurfaceFormatCore::~STLsurfaceFormatCore()
254 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
256 void Foam::fileFormats::STLsurfaceFormatCore::writeHeaderBINARY
262 // STL header with extra information about nTris
263 char header[headerSize];
264 sprintf(header, "STL binary file %u facets", nTris);
266 // avoid trailing junk
267 for (size_t i = strlen(header); i < headerSize; ++i)
272 os.write(header, headerSize);
273 os.write(reinterpret_cast<char*>(&nTris), sizeof(unsigned int));
278 // ************************************************************************* //