diff --git a/src/fileFormats/Make/files b/src/fileFormats/Make/files index 8919e3392d620678737974d272ee3dd44f807754..87fd35ee22b3c227489cbc79bad227c58ebc1051 100644 --- a/src/fileFormats/Make/files +++ b/src/fileFormats/Make/files @@ -10,6 +10,9 @@ ensight/type/ensightPTraits.C nas/NASCore.C fire/FIRECore.C starcd/STARCDCore.C +stl/STLCore.C +stl/STLReader.C +stl/STLReaderASCII.L vtk/foamVtkCore.C vtk/format/foamVtkAppendBase64Formatter.C diff --git a/src/surfMesh/surfaceFormats/stl/STLsurfaceFormatCore.C b/src/fileFormats/stl/STLCore.C similarity index 51% rename from src/surfMesh/surfaceFormats/stl/STLsurfaceFormatCore.C rename to src/fileFormats/stl/STLCore.C index 022b6df5a9e802abde0ea4bbf2a6cf797647df1f..a38d3a3cdf919407e8570e3b35204994e2959ab2 100644 --- a/src/surfMesh/surfaceFormats/stl/STLsurfaceFormatCore.C +++ b/src/fileFormats/stl/STLCore.C @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -23,36 +23,75 @@ License \*---------------------------------------------------------------------------*/ -#include "STLsurfaceFormatCore.H" +#include "STLCore.H" #include "gzstream.h" #include "OSspecific.H" -#include "Map.H" #include "IFstream.H" -#include "Ostream.H" -#undef DEBUG_STLBINARY +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // -// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // +//! \cond fileScope -// check binary by getting the header and number of facets +// The number of bytes in the STL binary header +static const unsigned STLHeaderSize = 80; + +//! \endcond + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::fileFormats::STLCore::STLCore() +{} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +bool Foam::fileFormats::STLCore::isBinaryName +( + const fileName& filename, + const STLFormat& format +) +{ + return (format == DETECT ? (filename.ext() == "stlb") : format == BINARY); +} + + +// Check binary by getting the header and number of facets // this seems to work better than the old token-based method // - some programs (eg, pro-STAR) have 'solid' as the first word in // the binary header. // - using wordToken can cause an abort if non-word (binary) content // is detected ... this is not exactly what we want. -int Foam::fileFormats::STLsurfaceFormatCore::detectBINARY +int Foam::fileFormats::STLCore::detectBinaryHeader ( const fileName& filename ) { - off_t dataFileSize = Foam::fileSize(filename); + bool compressed = false; + autoPtr<istream> streamPtr + ( + new ifstream(filename.c_str(), std::ios::binary) + ); + + // If the file is compressed, decompress it before further checking. + if (!streamPtr->good() && isFile(filename + ".gz", false)) + { + compressed = true; + streamPtr.reset(new igzstream((filename + ".gz").c_str())); + } + istream& is = streamPtr(); - IFstream str(filename, IOstream::BINARY); - istream& is = str().stdStream(); + if (!is.good()) + { + FatalErrorInFunction + << "Cannot read file " << filename + << " or file " << filename + ".gz" + << exit(FatalError); + } // Read the STL header - char header[headerSize]; - is.read(header, headerSize); + char header[STLHeaderSize]; + is.read(header, STLHeaderSize); // Check that stream is OK, if not this may be an ASCII file if (!is.good()) @@ -60,7 +99,7 @@ int Foam::fileFormats::STLsurfaceFormatCore::detectBINARY return 0; } - // Read the number of triangles in the STl file + // Read the number of triangles in the STL file // (note: read as int so we can check whether >2^31) int nTris; is.read(reinterpret_cast<char*>(&nTris), sizeof(unsigned int)); @@ -74,33 +113,73 @@ int Foam::fileFormats::STLsurfaceFormatCore::detectBINARY ( !is || nTris < 0 - || nTris < (dataFileSize - headerSize)/50 - || nTris > (dataFileSize - headerSize)/25 ) { return 0; } + else if (!compressed) + { + const off_t dataFileSize = Foam::fileSize(filename); + + if + ( + nTris < int(dataFileSize - STLHeaderSize)/50 + || nTris > int(dataFileSize - STLHeaderSize)/25 + ) + { + return 0; + } + } // looks like it might be BINARY, return number of triangles return nTris; } -bool Foam::fileFormats::STLsurfaceFormatCore::readBINARY +Foam::autoPtr<std::istream> +Foam::fileFormats::STLCore::readBinaryHeader ( - istream& is, - const off_t dataFileSize + const fileName& filename, + label& nTrisEstimated ) { - sorted_ = true; + bool bad = false; + bool compressed = false; + nTrisEstimated = 0; + + autoPtr<istream> streamPtr + ( + new ifstream(filename.c_str(), std::ios::binary) + ); + + // If the file is compressed, decompress it before reading. + if (!streamPtr->good() && isFile(filename + ".gz", false)) + { + compressed = true; + streamPtr.reset(new igzstream((filename + ".gz").c_str())); + } + istream& is = streamPtr(); + + if (!is.good()) + { + streamPtr.clear(); + + FatalErrorInFunction + << "Cannot read file " << filename + << " or file " << filename + ".gz" + << exit(FatalError); + } + // Read the STL header - char header[headerSize]; - is.read(header, headerSize); + char header[STLHeaderSize]; + is.read(header, STLHeaderSize); // Check that stream is OK, if not this may be an ASCII file if (!is.good()) { + streamPtr.clear(); + FatalErrorInFunction << "problem reading header, perhaps file is not binary " << exit(FatalError); @@ -116,156 +195,56 @@ bool Foam::fileFormats::STLsurfaceFormatCore::readBINARY // // Also compare the file size with that expected from the number of tris // If the comparison is not sensible then it may be an ASCII file - if - ( - !is - || nTris < 0 - || nTris < int(dataFileSize - headerSize)/50 - || nTris > int(dataFileSize - headerSize)/25 - ) + if (!is || nTris < 0) { - FatalErrorInFunction - << "problem reading number of triangles, perhaps file is not binary" - << exit(FatalError); + bad = true; } - -#ifdef DEBUG_STLBINARY - Info<< "# " << nTris << " facets" << endl; - label prevZone = -1; -#endif - - points_.setSize(3*nTris); - zoneIds_.setSize(nTris); - - Map<label> lookup; - DynamicList<label> dynSizes; - - label ptI = 0; - label zoneI = -1; - forAll(zoneIds_, facei) + else if (!compressed) { - // Read an STL triangle - STLtriangle stlTri(is); - - // transcribe the vertices of the STL triangle -> points - points_[ptI++] = stlTri.a(); - points_[ptI++] = stlTri.b(); - points_[ptI++] = stlTri.c(); - - // interprete stl attribute as a zone - const label origId = stlTri.attrib(); + const off_t dataFileSize = Foam::fileSize(filename); - Map<label>::const_iterator fnd = lookup.find(origId); - if (fnd != lookup.end()) - { - if (zoneI != fnd()) - { - // group appeared out of order - sorted_ = false; - } - zoneI = fnd(); - } - else - { - zoneI = dynSizes.size(); - lookup.insert(origId, zoneI); - dynSizes.append(0); - } - - zoneIds_[facei] = zoneI; - dynSizes[zoneI]++; - -#ifdef DEBUG_STLBINARY - if (prevZone != zoneI) + if + ( + nTris < int(dataFileSize - STLHeaderSize)/50 + || nTris > int(dataFileSize - STLHeaderSize)/25 + ) { - if (prevZone != -1) - { - Info<< "endsolid zone" << prevZone << nl; - } - prevZone = zoneI; - - Info<< "solid zone" << prevZone << nl; + bad = true; } - - Info<< " facet normal " << stlTri.normal() << nl - << " outer loop" << nl - << " vertex " << stlTri.a() << nl - << " vertex " << stlTri.b() << nl - << " vertex " << stlTri.c() << nl - << " outer loop" << nl - << " endfacet" << endl; -#endif } - names_.clear(); - sizes_.transfer(dynSizes); - - return true; -} - - -// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // - -Foam::fileFormats::STLsurfaceFormatCore::STLsurfaceFormatCore -( - const fileName& filename -) -: - sorted_(true), - points_(0), - zoneIds_(0), - names_(0), - sizes_(0) -{ - off_t dataFileSize = Foam::fileSize(filename); - - // auto-detect ascii/binary - if (detectBINARY(filename)) - { - readBINARY - ( - IFstream(filename, IOstream::BINARY)().stdStream(), - dataFileSize - ); - } - else + if (bad) { - readASCII - ( - IFstream(filename)().stdStream(), - dataFileSize - ); - } -} - + streamPtr.clear(); -// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // - -Foam::fileFormats::STLsurfaceFormatCore::~STLsurfaceFormatCore() -{} + FatalErrorInFunction + << "problem reading number of triangles, perhaps file is not binary" + << exit(FatalError); + } + nTrisEstimated = nTris; + return streamPtr; +} -// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // -void Foam::fileFormats::STLsurfaceFormatCore::writeHeaderBINARY +void Foam::fileFormats::STLCore::writeBinaryHeader ( ostream& os, unsigned int nTris ) { // STL header with extra information about nTris - char header[headerSize]; + char header[STLHeaderSize]; sprintf(header, "STL binary file %u facets", nTris); // avoid trailing junk - for (size_t i = strlen(header); i < headerSize; ++i) + for (size_t i = strlen(header); i < STLHeaderSize; ++i) { header[i] = 0; } - os.write(header, headerSize); + os.write(header, STLHeaderSize); os.write(reinterpret_cast<char*>(&nTris), sizeof(unsigned int)); - } diff --git a/src/fileFormats/stl/STLCore.H b/src/fileFormats/stl/STLCore.H new file mode 100644 index 0000000000000000000000000000000000000000..548cfabde206b862f5c3ee433ca5c0e45ba5e703 --- /dev/null +++ b/src/fileFormats/stl/STLCore.H @@ -0,0 +1,115 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 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 3 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, see <http://www.gnu.org/licenses/>. + +Class + Foam::fileFormats::STLCore + +Description + Core routines used when reading/writing STL files. + +SourceFiles + STLCore.C + +\*---------------------------------------------------------------------------*/ + +#ifndef STLCore_H +#define STLCore_H + +#include "STLpoint.H" +#include "STLtriangle.H" +#include "autoPtr.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ +namespace fileFormats +{ + +/*---------------------------------------------------------------------------*\ + Class fileFormats::STLCore Declaration +\*---------------------------------------------------------------------------*/ + +class STLCore +{ +public: + + // Public data types + + //- Enumeration for the format of data in the stream + enum STLFormat + { + ASCII, //!< ASCII + BINARY, //!< BINARY + DETECT //!< Detect based on (input) content or (output) extension + }; + + +protected: + + // Protected Member Functions + + //- Detect 'stlb' extension as binary + static bool isBinaryName + ( + const fileName& filename, + const STLFormat& format + ); + + + //- Check contents to detect if the file is a binary STL. + // Return the estimated number of triangles or 0 on error. + static int detectBinaryHeader(const fileName&); + + + //- Read STL binary file header. + // Return the opened file stream and estimated number of triangles. + // The stream is invalid and number of triangles is 0 on error. + static autoPtr<std::istream> readBinaryHeader + ( + const fileName& filename, + label& nTrisEstimated + ); + + //- Write STL binary file and number of triangles to stream + static void writeBinaryHeader(ostream&, unsigned int); + + + // Constructors + + //- Construct null + STLCore(); + +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace fileFormats +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/fileFormats/stl/STLReader.C b/src/fileFormats/stl/STLReader.C new file mode 100644 index 0000000000000000000000000000000000000000..c507b026735658d30e25ccd14375cc4083d9f8e4 --- /dev/null +++ b/src/fileFormats/stl/STLReader.C @@ -0,0 +1,188 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation + \\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd. +------------------------------------------------------------------------------- +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 3 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, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "STLReader.H" +#include "Map.H" +#include "IFstream.H" + +#undef DEBUG_STLBINARY + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +bool Foam::fileFormats::STLReader::readBINARY +( + const fileName& filename +) +{ + sorted_ = true; + + label nTris = 0; + autoPtr<istream> streamPtr = readBinaryHeader(filename, nTris); + + if (!streamPtr.valid()) + { + FatalErrorInFunction + << "Error reading file " << filename + << " or file " << filename + ".gz" + << exit(FatalError); + } + + istream& is = streamPtr(); + +#ifdef DEBUG_STLBINARY + Info<< "# " << nTris << " facets" << endl; + label prevZone = -1; +#endif + + points_.setSize(3*nTris); + zoneIds_.setSize(nTris); + + Map<label> lookup; + DynamicList<label> dynSizes; + + label ptI = 0; + label zoneI = -1; + forAll(zoneIds_, facei) + { + // Read STL triangle + STLtriangle stlTri(is); + + // transcribe the vertices of the STL triangle -> points + points_[ptI++] = stlTri.a(); + points_[ptI++] = stlTri.b(); + points_[ptI++] = stlTri.c(); + + // interpret STL attribute as a zone + const label origId = stlTri.attrib(); + + Map<label>::const_iterator fnd = lookup.find(origId); + if (fnd != lookup.end()) + { + if (zoneI != fnd()) + { + // group appeared out of order + sorted_ = false; + } + zoneI = fnd(); + } + else + { + zoneI = dynSizes.size(); + lookup.insert(origId, zoneI); + dynSizes.append(0); + } + + zoneIds_[facei] = zoneI; + dynSizes[zoneI]++; + +#ifdef DEBUG_STLBINARY + if (prevZone != zoneI) + { + if (prevZone != -1) + { + Info<< "endsolid zone" << prevZone << nl; + } + prevZone = zoneI; + + Info<< "solid zone" << prevZone << nl; + } + + stlTri.print(Info); +#endif + } + +#ifdef DEBUG_STLBINARY + if (prevZone != -1) + { + Info<< "endsolid zone" << prevZone << nl; + } +#endif + + names_.clear(); + sizes_.transfer(dynSizes); + + return true; +} + + +bool Foam::fileFormats::STLReader::readFile +( + const fileName& filename, + const STLFormat& format +) +{ + if (format == DETECT ? detectBinaryHeader(filename) : format == BINARY) + { + return readBINARY(filename); + } + else + { + return readASCII(filename); + } +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::fileFormats::STLReader::STLReader +( + const fileName& filename +) +: + sorted_(true), + points_(), + zoneIds_(), + names_(), + sizes_() +{ + // Auto-detect ASCII/BINARY format + readFile(filename, STLCore::DETECT); +} + + +Foam::fileFormats::STLReader::STLReader +( + const fileName& filename, + const STLFormat& format +) +: + sorted_(true), + points_(), + zoneIds_(), + names_(), + sizes_() +{ + // Manually specified ASCII/BINARY format + readFile(filename, format); +} + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +Foam::fileFormats::STLReader::~STLReader() +{} + + +// ************************************************************************* // diff --git a/src/surfMesh/surfaceFormats/stl/STLsurfaceFormatCore.H b/src/fileFormats/stl/STLReader.H similarity index 78% rename from src/surfMesh/surfaceFormats/stl/STLsurfaceFormatCore.H rename to src/fileFormats/stl/STLReader.H index a5aba97cfd930664cc7f15d2cf4a82a896127fc9..db985181d0b2384c935c3944da9279ebd7a79f32 100644 --- a/src/surfMesh/surfaceFormats/stl/STLsurfaceFormatCore.H +++ b/src/fileFormats/stl/STLReader.H @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -22,22 +22,22 @@ License along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. Class - Foam::fileFormats::STLsurfaceFormatCore + Foam::fileFormats::STLReader Description Internal class used by the STLsurfaceFormat SourceFiles - STLsurfaceFormatCore.C + STLReader.C STLsurfaceFormatASCII.L \*---------------------------------------------------------------------------*/ -#ifndef STLsurfaceFormatCore_H -#define STLsurfaceFormatCore_H +#ifndef STLReader_H +#define STLReader_H -#include "STLtriangle.H" -#include "triFace.H" +#include "STLCore.H" +#include "labelledTri.H" #include "IFstream.H" #include "Ostream.H" @@ -49,10 +49,12 @@ namespace fileFormats { /*---------------------------------------------------------------------------*\ - Class STLsurfaceFormatCore Declaration + Class fileFormats::STLReader Declaration \*---------------------------------------------------------------------------*/ -class STLsurfaceFormatCore +class STLReader +: + public STLCore { // Private Data @@ -73,44 +75,37 @@ class STLsurfaceFormatCore // Private Member Functions - //- Disallow default bitwise copy construct - STLsurfaceFormatCore(const STLsurfaceFormatCore&); - - //- Disallow default bitwise assignment - void operator=(const STLsurfaceFormatCore&); - - //- Determine the file type - static int detectBINARY(const fileName&); - //- Read ASCII - bool readASCII(istream&, const off_t); + bool readASCII(const fileName&); //- Read BINARY - bool readBINARY(istream&, const off_t); - + bool readBINARY(const fileName&); -public: - - // Static Data + //- Read ASCII or BINARY + bool readFile(const fileName&, const STLFormat&); - //- The number of bytes in the STL binary header - static const unsigned int headerSize = 80; + //- Disallow default bitwise copy construct + STLReader(const STLReader&) = delete; - // Static Member Functions + //- Disallow default bitwise assignment + void operator=(const STLReader&) = delete; - //- Write "STL binary file" and number of triangles to stream - static void writeHeaderBINARY(ostream&, unsigned int); +public: // Constructors //- Read from file, filling in the information - STLsurfaceFormatCore(const fileName&); + STLReader(const fileName&); + + //- Read from file, filling in the information. + // Manually selected choice of ascii/binary/detect. + STLReader(const fileName&, const STLFormat&); //- Destructor - ~STLsurfaceFormatCore(); + ~STLReader(); // Member Functions diff --git a/src/surfMesh/surfaceFormats/stl/STLsurfaceFormatASCII.L b/src/fileFormats/stl/STLReaderASCII.L similarity index 93% rename from src/surfMesh/surfaceFormats/stl/STLsurfaceFormatASCII.L rename to src/fileFormats/stl/STLReaderASCII.L index a3f9e47a6ce06cfb629bf7b78c2ab5fe01b9791e..515a1be90d8f3b5c2ec69c7d9cb1698f7486256b 100644 --- a/src/surfMesh/surfaceFormats/stl/STLsurfaceFormatASCII.L +++ b/src/fileFormats/stl/STLReaderASCII.L @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -31,7 +31,8 @@ License ------ local definitions \* ------------------------------------------------------------------------ */ -#include "STLsurfaceFormatCore.H" +#include "STLReader.H" +#include "OSspecific.H" using namespace Foam; @@ -97,32 +98,32 @@ public: // Access //- Do all the solid groups appear in order - bool sorted() const + inline bool sorted() const { return sorted_; } //- A list of points corresponding to a pointField - DynamicList<point>& points() + inline DynamicList<point>& points() { return points_; } //- A list of facet IDs (group IDs) // corresponds to the number of triangles - DynamicList<label>& facets() + inline DynamicList<label>& facets() { return facets_; } //- Names - DynamicList<word>& names() + inline DynamicList<word>& names() { return names_; } //- Sizes - DynamicList<label>& sizes() + inline DynamicList<label>& sizes() { return sizes_; } @@ -390,20 +391,27 @@ endsolid {space}("endsolid"|"ENDSOLID")({some_space}{word})* // // member function // -bool Foam::fileFormats::STLsurfaceFormatCore::readASCII +bool Foam::fileFormats::STLReader::readASCII ( - istream& is, - const off_t dataFileSize + const fileName& filename ) { + IFstream is(filename); + if (!is) + { + FatalErrorInFunction + << "file " << filename << " not found" + << exit(FatalError); + } + // Create the lexer with the approximate number of vertices in the STL // from the file size - STLASCIILexer lexer(&is, dataFileSize/400); + STLASCIILexer lexer(&(is.stdStream()), Foam::fileSize(filename)/400); while (lexer.lex() != 0) {} sorted_ = lexer.sorted(); - // transfer to normal lists + // Transfer to normal lists points_.transfer(lexer.points()); zoneIds_.transfer(lexer.facets()); names_.transfer(lexer.names()); @@ -413,5 +421,5 @@ bool Foam::fileFormats::STLsurfaceFormatCore::readASCII } /* ------------------------------------------------------------------------ *\ - ------ End of STLfileFormatASCII.L + ------ End of STLReaderASCII.L \* ------------------------------------------------------------------------ */ diff --git a/src/surfMesh/surfaceFormats/stl/STLpoint.H b/src/fileFormats/stl/STLpoint.H similarity index 91% rename from src/surfMesh/surfaceFormats/stl/STLpoint.H rename to src/fileFormats/stl/STLpoint.H index 157e832ba5a66581799ac4049f1b30ef792929f3..c9862eaf9442d8a9755206616f1a9aa99ef630ec 100644 --- a/src/surfMesh/surfaceFormats/stl/STLpoint.H +++ b/src/fileFormats/stl/STLpoint.H @@ -2,8 +2,8 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2011-2013 OpenFOAM Foundation - \\/ M anipulation | + \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation + \\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -27,14 +27,13 @@ Class Description A vertex point representation for STL files. -SourceFiles - \*---------------------------------------------------------------------------*/ #ifndef STLpoint_H #define STLpoint_H #include "point.H" +#include "floatVector.H" #include "Istream.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -80,11 +79,13 @@ public: // Member Operators - //- Conversion to point + #ifdef WM_DP + //- Conversion to double-precision point inline operator point() const { return point(x(), y(), z()); } + #endif }; diff --git a/src/surfMesh/surfaceFormats/stl/STLtriangle.H b/src/fileFormats/stl/STLtriangle.H similarity index 80% rename from src/surfMesh/surfaceFormats/stl/STLtriangle.H rename to src/fileFormats/stl/STLtriangle.H index 17783047f2107ad507a01d7d16b4dae6efbd3749..a80f5498c53f3e90cd4acb474b266d5f92d57881 100644 --- a/src/surfMesh/surfaceFormats/stl/STLtriangle.H +++ b/src/fileFormats/stl/STLtriangle.H @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -45,12 +45,9 @@ namespace Foam { // Forward declaration of friend functions and operators - class STLtriangle; - Ostream& operator<<(Ostream&, const STLtriangle&); - /*---------------------------------------------------------------------------*\ Class STLtriangle Declaration \*---------------------------------------------------------------------------*/ @@ -62,7 +59,7 @@ class STLtriangle //- Attribute is 16-bit typedef unsigned short STLattrib; - //- The face normal, many programs write zore or other junk + //- The face normal, many programs write zero or other junk STLpoint normal_; //- The three points defining the triangle @@ -113,7 +110,30 @@ public: // Write //- Write to ostream (binary) - inline void write(ostream&); + inline void write(ostream&) const; + + //- Write to Ostream (ASCII) + inline Ostream& print(Ostream& os) const; + + + //- Write components to Ostream (ASCII) + inline static void write + ( + Ostream& os, + const vector& norm, + const point& pt0, + const point& pt1, + const point& pt2 + ); + + //- Write components to Ostream (ASCII), calculating the normal + inline static void write + ( + Ostream& os, + const point& pt0, + const point& pt1, + const point& pt2 + ); // Ostream operator diff --git a/src/surfMesh/surfaceFormats/stl/STLtriangleI.H b/src/fileFormats/stl/STLtriangleI.H similarity index 61% rename from src/surfMesh/surfaceFormats/stl/STLtriangleI.H rename to src/fileFormats/stl/STLtriangleI.H index c6d17f4a832473b13041394a54d1d441d4cf8abf..85e02be3d483602e41944832275eb9c60b6812ac 100644 --- a/src/surfMesh/surfaceFormats/stl/STLtriangleI.H +++ b/src/fileFormats/stl/STLtriangleI.H @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -23,6 +23,8 @@ License \*---------------------------------------------------------------------------*/ +#include "triPointRef.H" + // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // inline Foam::STLtriangle::STLtriangle() @@ -91,10 +93,61 @@ inline void Foam::STLtriangle::read(istream& is) } -inline void Foam::STLtriangle::write(ostream& os) +inline void Foam::STLtriangle::write(ostream& os) const +{ + os.write(reinterpret_cast<const char*>(this), 4*sizeof(STLpoint)); + os.write(reinterpret_cast<const char*>(&attrib_), sizeof(STLattrib)); +} + + +inline Foam::Ostream& Foam::STLtriangle::print(Ostream& os) const +{ + os << " facet normal " + << normal_.x() << ' ' << normal_.y() << ' ' << normal_.z() << nl + << " outer loop" << nl + << " vertex " << a_.x() << ' ' << a_.y() << ' ' << a_.z() << nl + << " vertex " << b_.x() << ' ' << b_.y() << ' ' << b_.z() << nl + << " vertex " << c_.x() << ' ' << c_.y() << ' ' << c_.z() << nl + << " endloop" << nl + << " endfacet" << nl; + + return os; +} + + +inline void Foam::STLtriangle::write +( + Ostream& os, + const vector& norm, + const point& pt0, + const point& pt1, + const point& pt2 +) +{ + os << " facet normal " + << norm.x() << ' ' << norm.y() << ' ' << norm.z() << nl + << " outer loop" << nl + << " vertex " << pt0.x() << ' ' << pt0.y() << ' ' << pt0.z() << nl + << " vertex " << pt1.x() << ' ' << pt1.y() << ' ' << pt1.z() << nl + << " vertex " << pt2.x() << ' ' << pt2.y() << ' ' << pt2.z() << nl + << " endloop" << nl + << " endfacet" << nl; +} + + +inline void Foam::STLtriangle::write +( + Ostream& os, + const point& pt0, + const point& pt1, + const point& pt2 +) { - os.write(reinterpret_cast<char*>(this), 4*sizeof(STLpoint)); - os.write(reinterpret_cast<char*>(&attrib_), sizeof(STLattrib)); + // calculate the normal ourselves + vector norm = triPointRef(pt0, pt1, pt2).normal(); + norm /= mag(norm) + VSMALL; + + write(os, norm, pt0, pt1, pt2); } diff --git a/src/surfMesh/Make/files b/src/surfMesh/Make/files index b03fdc7e77c4c7321aed0970c52b11f73c549f95..e0a2b486e47e03a30422031786fc12372a61fd10 100644 --- a/src/surfMesh/Make/files +++ b/src/surfMesh/Make/files @@ -32,9 +32,7 @@ $(surfaceFormats)/off/OFFsurfaceFormatRunTime.C $(surfaceFormats)/smesh/SMESHsurfaceFormatRunTime.C $(surfaceFormats)/starcd/STARCDsurfaceFormatCore.C $(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 diff --git a/src/surfMesh/surfaceFormats/stl/STLsurfaceFormat.C b/src/surfMesh/surfaceFormats/stl/STLsurfaceFormat.C index ce53aed44bcaf8e9da312d24cb87c8101a8f06e0..0529da9941d8fb954e21729541371be6d22187ac 100644 --- a/src/surfMesh/surfaceFormats/stl/STLsurfaceFormat.C +++ b/src/surfMesh/surfaceFormats/stl/STLsurfaceFormat.C @@ -51,20 +51,17 @@ inline void Foam::fileFormats::STLsurfaceFormat<Face>::writeShell const point& p0 = pointLst[f[0]]; for (label fp1 = 1; fp1 < f.size() - 1; ++fp1) { - label fp2 = f.fcIndex(fp1); - - const point& p1 = pointLst[f[fp1]]; - const point& p2 = pointLst[f[fp2]]; - - // write STL triangle - os << " facet normal " - << norm.x() << ' ' << norm.y() << ' ' << norm.z() << nl - << " outer loop\n" - << " vertex " << p0.x() << ' ' << p0.y() << ' ' << p0.z() << nl - << " vertex " << p1.x() << ' ' << p1.y() << ' ' << p1.z() << nl - << " vertex " << p2.x() << ' ' << p2.y() << ' ' << p2.z() << nl - << " endloop\n" - << " endfacet" << endl; + const label fp2 = f.fcIndex(fp1); + + // Write ASCII + STLtriangle::write + ( + os, + norm, + p0, + pointLst[f[fp1]], + pointLst[f[fp2]] + ); } } @@ -92,18 +89,17 @@ inline void Foam::fileFormats::STLsurfaceFormat<Face>::writeShell const point& p0 = pointLst[f[0]]; for (label fp1 = 1; fp1 < f.size() - 1; ++fp1) { - label fp2 = f.fcIndex(fp1); + const label fp2 = f.fcIndex(fp1); - STLtriangle stlTri + // Write BINARY + STLtriangle ( norm, p0, pointLst[f[fp1]], pointLst[f[fp2]], zoneI - ); - - stlTri.write(os); + ).write(os); } } @@ -131,7 +127,7 @@ bool Foam::fileFormats::STLsurfaceFormat<Face>::read this->clear(); // read in the values - STLsurfaceFormatCore reader(filename); + STLReader reader(filename); // transfer points this->storedPoints().transfer(reader.points()); @@ -273,7 +269,7 @@ void Foam::fileFormats::STLsurfaceFormat<Face>::writeBinary // Write the STL header unsigned int nTris = surf.nTriangles(); - STLsurfaceFormatCore::writeHeaderBINARY(os, nTris); + STLCore::writeBinaryHeader(os, nTris); label faceIndex = 0; forAll(zones, zoneI) @@ -379,7 +375,7 @@ void Foam::fileFormats::STLsurfaceFormat<Face>::writeBinary // Write the STL header unsigned int nTris = surf.nTriangles(); - STLsurfaceFormatCore::writeHeaderBINARY(os, nTris); + STLCore::writeBinaryHeader(os, nTris); // always write unsorted forAll(faceLst, facei) @@ -402,10 +398,20 @@ void Foam::fileFormats::STLsurfaceFormat<Face>::write const MeshedSurfaceProxy<Face>& surf ) { - const word ext = filename.ext(); + // Auto-detect ASCII/BINARY extension + write(filename, surf, STLCore::DETECT); +} - // handle 'stlb' as binary directly - if (ext == "stlb") + +template<class Face> +void Foam::fileFormats::STLsurfaceFormat<Face>::write +( + const fileName& filename, + const MeshedSurfaceProxy<Face>& surf, + const STLFormat& format +) +{ + if (STLCore::isBinaryName(filename, format)) { writeBinary(filename, surf); } @@ -423,10 +429,20 @@ void Foam::fileFormats::STLsurfaceFormat<Face>::write const UnsortedMeshedSurface<Face>& surf ) { - word ext = filename.ext(); + // Auto-detect ASCII/BINARY extension + write(filename, surf, STLCore::DETECT); +} + - // handle 'stlb' as binary directly - if (ext == "stlb") +template<class Face> +void Foam::fileFormats::STLsurfaceFormat<Face>::write +( + const fileName& filename, + const UnsortedMeshedSurface<Face>& surf, + const STLFormat& format +) +{ + if (STLCore::isBinaryName(filename, format)) { writeBinary(filename, surf); } diff --git a/src/surfMesh/surfaceFormats/stl/STLsurfaceFormat.H b/src/surfMesh/surfaceFormats/stl/STLsurfaceFormat.H index 02c12ae24b56dde6543bc2a22aa8062e85f14e5d..76aaf028a327350f74f4bb737e10e90ff844476b 100644 --- a/src/surfMesh/surfaceFormats/stl/STLsurfaceFormat.H +++ b/src/surfMesh/surfaceFormats/stl/STLsurfaceFormat.H @@ -25,7 +25,7 @@ Class Foam::fileFormats::STLsurfaceFormat Description - Provide a means of reading/writing STL files (ASCII and binary). + Provide a means of reading/writing STL files (ASCII and BINARY). Note For efficiency, the zones are sorted before creating the faces. @@ -40,7 +40,7 @@ SourceFiles #ifndef STLsurfaceFormat_H #define STLsurfaceFormat_H -#include "STLsurfaceFormatCore.H" +#include "STLReader.H" #include "MeshedSurface.H" #include "MeshedSurfaceProxy.H" #include "UnsortedMeshedSurface.H" @@ -59,7 +59,8 @@ namespace fileFormats template<class Face> class STLsurfaceFormat : - public MeshedSurface<Face> + public MeshedSurface<Face>, + public STLCore { // Private Member Functions @@ -80,6 +81,7 @@ class STLsurfaceFormat const label zoneI ); + //- Disallow default bitwise copy construct STLsurfaceFormat(const STLsurfaceFormat<Face>&); @@ -132,6 +134,15 @@ public: // as ASCII or BINARY, depending on the extension static void write(const fileName&, const MeshedSurfaceProxy<Face>&); + //- Write surface mesh components by proxy + // as ASCII or BINARY or dependent on the extension + static void write + ( + const fileName&, + const MeshedSurfaceProxy<Face>&, + const STLFormat& + ); + //- Write UnsortedMeshedSurface (as ASCII) sorted by zone static void writeAscii ( @@ -150,6 +161,15 @@ public: // as ASCII or BINARY, depending on the extension static void write(const fileName&, const UnsortedMeshedSurface<Face>&); + //- Write UnsortedMeshedSurface + // as ASCII or BINARY or dependent on the extension + static void write + ( + const fileName&, + const UnsortedMeshedSurface<Face>&, + const STLFormat& + ); + //- Read from file virtual bool read(const fileName&);