Initial commit for version 2.0.x patch release
[OpenFOAM-2.0.x.git] / src / surfMesh / surfaceFormats / stl / STLsurfaceFormatCore.C
blob6e03d66bd36d5989ca740f12f4610185f572a9f9
1 /*---------------------------------------------------------------------------*\
2   =========                 |
3   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
4    \\    /   O peration     |
5     \\  /    A nd           | Copyright (C) 2004-2010 OpenCFD Ltd.
6      \\/     M anipulation  |
7 -------------------------------------------------------------------------------
8 License
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
19     for more details.
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"
27 #include "gzstream.h"
28 #include "OSspecific.H"
29 #include "Map.H"
30 #include "IFstream.H"
31 #include "Ostream.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
40 //   the binary header.
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
58     if (!is.good())
59     {
60         return 0;
61     }
63     // Read the number of triangles in the STl file
64     // (note: read as int so we can check whether >2^31)
65     int nTris;
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
70     //
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
73     if
74     (
75         !is
76      || nTris < 0
77      || nTris < (dataFileSize - headerSize)/50
78      || nTris > (dataFileSize - headerSize)/25
79     )
80     {
81         return 0;
82     }
84     // looks like it might be BINARY, return number of triangles
85     return nTris;
89 bool Foam::fileFormats::STLsurfaceFormatCore::readBINARY
91     istream& is,
92     const off_t dataFileSize
95     sorted_ = true;
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
102     if (!is.good())
103     {
104         FatalErrorIn
105         (
106             "fileFormats::STLsurfaceFormatCore::readBINARY(IFstream&)"
107         )
108             << "problem reading header, perhaps file is not binary "
109             << exit(FatalError);
110     }
112     // Read the number of triangles in the STl file
113     // (note: read as int so we can check whether >2^31)
114     int nTris;
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
119     //
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
122     if
123     (
124         !is
125      || nTris < 0
126      || nTris < int(dataFileSize - headerSize)/50
127      || nTris > int(dataFileSize - headerSize)/25
128     )
129     {
130         FatalErrorIn
131         (
132             "fileFormats::STLsurfaceFormatCore::readBINARY(istream&)"
133         )
134             << "problem reading number of triangles, perhaps file is not binary"
135             << exit(FatalError);
136     }
138 #ifdef DEBUG_STLBINARY
139     Info<< "# " << nTris << " facets" << endl;
140     label prevZone = -1;
141 #endif
143     points_.setSize(3*nTris);
144     zoneIds_.setSize(nTris);
146     Map<label> lookup;
147     DynamicList<label> dynSizes;
149     label ptI = 0;
150     label zoneI = -1;
151     forAll(zoneIds_, faceI)
152     {
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())
166         {
167             if (zoneI != fnd())
168             {
169                 // group appeared out of order
170                 sorted_ = false;
171             }
172             zoneI = fnd();
173         }
174         else
175         {
176             zoneI = dynSizes.size();
177             lookup.insert(origId, zoneI);
178             dynSizes.append(0);
179         }
181         zoneIds_[faceI] = zoneI;
182         dynSizes[zoneI]++;
184 #ifdef DEBUG_STLBINARY
185         if (prevZone != zoneI)
186         {
187             if (prevZone != -1)
188             {
189                 Info<< "endsolid zone" << prevZone << nl;
190             }
191             prevZone = zoneI;
193             Info<< "solid zone" << prevZone << nl;
194         }
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;
203 #endif
204     }
206     names_.clear();
207     sizes_.transfer(dynSizes);
209     return true;
213 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
215 Foam::fileFormats::STLsurfaceFormatCore::STLsurfaceFormatCore
217     const fileName& filename
220     sorted_(true),
221     points_(0),
222     zoneIds_(0),
223     names_(0),
224     sizes_(0)
226     off_t dataFileSize = Foam::fileSize(filename);
228     // auto-detect ascii/binary
229     if (detectBINARY(filename))
230     {
231         readBINARY
232         (
233             IFstream(filename, IOstream::BINARY)().stdStream(),
234             dataFileSize
235         );
236     }
237     else
238     {
239         readASCII
240         (
241             IFstream(filename)().stdStream(),
242             dataFileSize
243         );
244     }
248 // * * * * * * * * * * * * * * * * Destructors * * * * * * * * * * * * * * * //
250 Foam::fileFormats::STLsurfaceFormatCore::~STLsurfaceFormatCore()
254 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
256 void Foam::fileFormats::STLsurfaceFormatCore::writeHeaderBINARY
258     ostream& os,
259     unsigned int nTris
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)
268     {
269         header[i] = 0;
270     }
272     os.write(header, headerSize);
273     os.write(reinterpret_cast<char*>(&nTris), sizeof(unsigned int));
278 // ************************************************************************* //