FreeFOAM The Cross-Platform CFD Toolkit
Hosted by SourceForge:
Get FreeFOAM at SourceForge.net.
            Fast, secure and Free Open Source software downloads

STLsurfaceFormatCore.C

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002   =========                 |
00003   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
00004    \\    /   O peration     |
00005     \\  /    A nd           | Copyright (C) 1991-2010 OpenCFD Ltd.
00006      \\/     M anipulation  |
00007 -------------------------------------------------------------------------------
00008 License
00009     This file is part of OpenFOAM.
00010 
00011     OpenFOAM is free software: you can redistribute it and/or modify it
00012     under the terms of the GNU General Public License as published by
00013     the Free Software Foundation, either version 3 of the License, or
00014     (at your option) any later version.
00015 
00016     OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
00017     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00019     for more details.
00020 
00021     You should have received a copy of the GNU General Public License
00022     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
00023 
00024 \*---------------------------------------------------------------------------*/
00025 
00026 #include "STLsurfaceFormatCore.H"
00027 #include <OpenFOAM/gzstream.h>
00028 #include <OpenFOAM/OSspecific.H>
00029 #include <OpenFOAM/Map.H>
00030 #include <OpenFOAM/IFstream.H>
00031 #include <OpenFOAM/Ostream.H>
00032 
00033 #undef DEBUG_STLBINARY
00034 
00035 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
00036 
00037 // check binary by getting the header and number of facets
00038 // this seems to work better than the old token-based method
00039 // - some programs (eg, pro-STAR) have 'solid' as the first word in
00040 //   the binary header.
00041 // - using wordToken can cause an abort if non-word (binary) content
00042 //   is detected ... this is not exactly what we want.
00043 int Foam::fileFormats::STLsurfaceFormatCore::detectBINARY
00044 (
00045     const fileName& filename
00046 )
00047 {
00048     off_t dataFileSize = Foam::fileSize(filename);
00049 
00050     IFstream str(filename, IOstream::BINARY);
00051     istream& is = str().stdStream();
00052 
00053     // Read the STL header
00054     char header[headerSize];
00055     is.read(header, headerSize);
00056 
00057     // Check that stream is OK, if not this may be an ASCII file
00058     if (!is.good())
00059     {
00060         return 0;
00061     }
00062 
00063     // Read the number of triangles in the STl file
00064     // (note: read as int so we can check whether >2^31)
00065     int nTris;
00066     is.read(reinterpret_cast<char*>(&nTris), sizeof(unsigned int));
00067 
00068     // Check that stream is OK and number of triangles is positive,
00069     // if not this may be an ASCII file
00070     //
00071     // Also compare the file size with that expected from the number of tris
00072     // If the comparison is not sensible then it may be an ASCII file
00073     if
00074     (
00075         !is
00076      || nTris < 0
00077      || nTris < (dataFileSize - headerSize)/50
00078      || nTris > (dataFileSize - headerSize)/25
00079     )
00080     {
00081         return 0;
00082     }
00083 
00084     // looks like it might be BINARY, return number of triangles
00085     return nTris;
00086 }
00087 
00088 
00089 bool Foam::fileFormats::STLsurfaceFormatCore::readBINARY
00090 (
00091     istream& is,
00092     const off_t dataFileSize
00093 )
00094 {
00095     sorted_ = true;
00096 
00097     // Read the STL header
00098     char header[headerSize];
00099     is.read(header, headerSize);
00100 
00101     // Check that stream is OK, if not this may be an ASCII file
00102     if (!is.good())
00103     {
00104         FatalErrorIn
00105         (
00106             "fileFormats::STLsurfaceFormatCore::readBINARY(IFstream&)"
00107         )
00108             << "problem reading header, perhaps file is not binary "
00109             << exit(FatalError);
00110     }
00111 
00112     // Read the number of triangles in the STl file
00113     // (note: read as int so we can check whether >2^31)
00114     int nTris;
00115     is.read(reinterpret_cast<char*>(&nTris), sizeof(unsigned int));
00116 
00117     // Check that stream is OK and number of triangles is positive,
00118     // if not this maybe an ASCII file
00119     //
00120     // Also compare the file size with that expected from the number of tris
00121     // If the comparison is not sensible then it may be an ASCII file
00122     if
00123     (
00124         !is
00125      || nTris < 0
00126      || nTris < int(dataFileSize - headerSize)/50
00127      || nTris > int(dataFileSize - headerSize)/25
00128     )
00129     {
00130         FatalErrorIn
00131         (
00132             "fileFormats::STLsurfaceFormatCore::readBINARY(istream&)"
00133         )
00134             << "problem reading number of triangles, perhaps file is not binary"
00135             << exit(FatalError);
00136     }
00137 
00138 #ifdef DEBUG_STLBINARY
00139     Info<< "# " << nTris << " facets" << endl;
00140     label prevZone = -1;
00141 #endif
00142 
00143     points_.setSize(3*nTris);
00144     zoneIds_.setSize(nTris);
00145 
00146     Map<label> lookup;
00147     DynamicList<label> dynSizes;
00148 
00149     label ptI = 0;
00150     label zoneI = -1;
00151     forAll(zoneIds_, faceI)
00152     {
00153         // Read an STL triangle
00154         STLtriangle stlTri(is);
00155 
00156         // transcribe the vertices of the STL triangle -> points
00157         points_[ptI++] = stlTri.a();
00158         points_[ptI++] = stlTri.b();
00159         points_[ptI++] = stlTri.c();
00160 
00161         // interprete stl attribute as a zone
00162         const label origId = stlTri.attrib();
00163 
00164         Map<label>::const_iterator fnd = lookup.find(origId);
00165         if (fnd != lookup.end())
00166         {
00167             if (zoneI != fnd())
00168             {
00169                 // group appeared out of order
00170                 sorted_ = false;
00171             }
00172             zoneI = fnd();
00173         }
00174         else
00175         {
00176             zoneI = dynSizes.size();
00177             lookup.insert(origId, zoneI);
00178             dynSizes.append(0);
00179         }
00180 
00181         zoneIds_[faceI] = zoneI;
00182         dynSizes[zoneI]++;
00183 
00184 #ifdef DEBUG_STLBINARY
00185         if (prevZone != zoneI)
00186         {
00187             if (prevZone != -1)
00188             {
00189                 Info<< "endsolid zone" << prevZone << nl;
00190             }
00191             prevZone = zoneI;
00192 
00193             Info<< "solid zone" << prevZone << nl;
00194         }
00195 
00196         Info<< " facet normal " << stlTri.normal() << nl
00197             << "  outer loop" << nl
00198             << "   vertex " << stlTri.a() << nl
00199             << "   vertex " << stlTri.b() << nl
00200             << "   vertex " << stlTri.c() << nl
00201             << "  outer loop" << nl
00202             << " endfacet" << endl;
00203 #endif
00204     }
00205 
00206     names_.clear();
00207     sizes_.transfer(dynSizes);
00208 
00209     return true;
00210 }
00211 
00212 
00213 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
00214 
00215 Foam::fileFormats::STLsurfaceFormatCore::STLsurfaceFormatCore
00216 (
00217     const fileName& filename
00218 )
00219 :
00220     sorted_(true),
00221     points_(0),
00222     zoneIds_(0),
00223     names_(0),
00224     sizes_(0)
00225 {
00226     off_t dataFileSize = Foam::fileSize(filename);
00227 
00228     // auto-detect ascii/binary
00229     if (detectBINARY(filename))
00230     {
00231         readBINARY
00232         (
00233             IFstream(filename, IOstream::BINARY)().stdStream(),
00234             dataFileSize
00235         );
00236     }
00237     else
00238     {
00239         readASCII
00240         (
00241             IFstream(filename)().stdStream(),
00242             dataFileSize
00243         );
00244     }
00245 }
00246 
00247 
00248 // * * * * * * * * * * * * * * * * Destructors * * * * * * * * * * * * * * * //
00249 
00250 Foam::fileFormats::STLsurfaceFormatCore::~STLsurfaceFormatCore()
00251 {}
00252 
00253 
00254 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
00255 
00256 void Foam::fileFormats::STLsurfaceFormatCore::writeHeaderBINARY
00257 (
00258     ostream& os,
00259     unsigned int nTris
00260 )
00261 {
00262     // STL header with extra information about nTris
00263     char header[headerSize];
00264     sprintf(header, "STL binary file %u facets", nTris);
00265 
00266     // avoid trailing junk
00267     for (size_t i = strlen(header); i < headerSize; ++i)
00268     {
00269         header[i] = 0;
00270     }
00271 
00272     os.write(header, headerSize);
00273     os.write(reinterpret_cast<char*>(&nTris), sizeof(unsigned int));
00274 
00275 }
00276 
00277 
00278 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines