From 85ad5147bd66904c7506d2995d2fc5021186fce9 Mon Sep 17 00:00:00 2001 From: mark <mark@opencfd> Date: Wed, 25 Jan 2017 11:58:55 +0100 Subject: [PATCH] ENH: use STL reader from surfMesh library for triSurface as well (issue #294) - initial step in reducing duplicate IO for triSurface. - write STL triangle using common core routines from fileFormats --- src/fileFormats/stl/STLCore.C | 4 +- src/fileFormats/stl/STLCore.H | 4 +- src/fileFormats/stl/STLReader.C | 27 +- src/fileFormats/stl/STLReader.H | 53 +- src/fileFormats/stl/STLReaderASCII.L | 13 +- src/fileFormats/stl/STLpoint.H | 10 +- src/fileFormats/stl/STLtriangle.H | 31 +- src/fileFormats/stl/STLtriangleI.H | 22 +- .../surfaceFormats/stl/STLsurfaceFormat.C | 6 +- src/triSurface/Make/files | 2 - .../triSurface/interfaces/STL/readSTL.C | 84 +-- .../triSurface/interfaces/STL/readSTLASCII.L | 490 ------------------ .../triSurface/interfaces/STL/readSTLBINARY.C | 152 ------ .../triSurface/interfaces/STL/writeSTL.C | 109 ++-- src/triSurface/triSurface/triSurface.C | 4 +- src/triSurface/triSurface/triSurface.H | 6 +- 16 files changed, 204 insertions(+), 813 deletions(-) delete mode 100644 src/triSurface/triSurface/interfaces/STL/readSTLASCII.L delete mode 100644 src/triSurface/triSurface/interfaces/STL/readSTLBINARY.C diff --git a/src/fileFormats/stl/STLCore.C b/src/fileFormats/stl/STLCore.C index a38d3a3cdf..9b7c0c2e1c 100644 --- a/src/fileFormats/stl/STLCore.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 | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | Copyright (C) 2016-2017 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -52,7 +52,7 @@ bool Foam::fileFormats::STLCore::isBinaryName const STLFormat& format ) { - return (format == DETECT ? (filename.ext() == "stlb") : format == BINARY); + return (format == UNKNOWN ? (filename.ext() == "stlb") : format == BINARY); } diff --git a/src/fileFormats/stl/STLCore.H b/src/fileFormats/stl/STLCore.H index 548cfabde2..fede83b850 100644 --- a/src/fileFormats/stl/STLCore.H +++ b/src/fileFormats/stl/STLCore.H @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\ / A nd | Copyright (C) 2016-2017 OpenCFD Ltd. \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -61,7 +61,7 @@ public: { ASCII, //!< ASCII BINARY, //!< BINARY - DETECT //!< Detect based on (input) content or (output) extension + UNKNOWN //!< Detect based on (input) content or (output) extension }; diff --git a/src/fileFormats/stl/STLReader.C b/src/fileFormats/stl/STLReader.C index c507b02673..b7b91a0bb7 100644 --- a/src/fileFormats/stl/STLReader.C +++ b/src/fileFormats/stl/STLReader.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 | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | Copyright (C) 2016-2017 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -37,6 +37,7 @@ bool Foam::fileFormats::STLReader::readBINARY ) { sorted_ = true; + format_ = UNKNOWN; label nTris = 0; autoPtr<istream> streamPtr = readBinaryHeader(filename, nTris); @@ -123,6 +124,7 @@ bool Foam::fileFormats::STLReader::readBINARY names_.clear(); sizes_.transfer(dynSizes); + format_ = BINARY; return true; } @@ -133,7 +135,7 @@ bool Foam::fileFormats::STLReader::readFile const STLFormat& format ) { - if (format == DETECT ? detectBinaryHeader(filename) : format == BINARY) + if (format == UNKNOWN ? detectBinaryHeader(filename) : format == BINARY) { return readBINARY(filename); } @@ -155,10 +157,11 @@ Foam::fileFormats::STLReader::STLReader points_(), zoneIds_(), names_(), - sizes_() + sizes_(), + format_(STLCore::UNKNOWN) { // Auto-detect ASCII/BINARY format - readFile(filename, STLCore::DETECT); + readFile(filename, STLCore::UNKNOWN); } @@ -172,7 +175,8 @@ Foam::fileFormats::STLReader::STLReader points_(), zoneIds_(), names_(), - sizes_() + sizes_(), + format_(STLCore::UNKNOWN) { // Manually specified ASCII/BINARY format readFile(filename, format); @@ -185,4 +189,17 @@ Foam::fileFormats::STLReader::~STLReader() {} +// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // + +void Foam::fileFormats::STLReader::clear() +{ + sorted_ = true; + points_.clear(); + zoneIds_.clear(); + names_.clear(); + sizes_.clear(); + format_ = UNKNOWN; +} + + // ************************************************************************* // diff --git a/src/fileFormats/stl/STLReader.H b/src/fileFormats/stl/STLReader.H index db985181d0..9ed6838bc1 100644 --- a/src/fileFormats/stl/STLReader.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 | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | Copyright (C) 2016-2017 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -25,7 +25,7 @@ Class Foam::fileFormats::STLReader Description - Internal class used by the STLsurfaceFormat + Internal class used by the STLsurfaceFormat and triSurface. SourceFiles STLReader.C @@ -72,17 +72,20 @@ class STLReader //- The solid count, in the order of their first appearance List<label> sizes_; + //- The STL format used + STLFormat format_; + // Private Member Functions //- Read ASCII - bool readASCII(const fileName&); + bool readASCII(const fileName& filename); //- Read BINARY - bool readBINARY(const fileName&); + bool readBINARY(const fileName& filename); //- Read ASCII or BINARY - bool readFile(const fileName&, const STLFormat&); + bool readFile(const fileName& filename, const STLFormat& format); //- Disallow default bitwise copy construct @@ -96,12 +99,13 @@ public: // Constructors - //- Read from file, filling in the information - STLReader(const fileName&); + //- Read from file, filling in the information. + // Auto-detect ASCII/BINARY format. + STLReader(const fileName& filename); //- Read from file, filling in the information. - // Manually selected choice of ascii/binary/detect. - STLReader(const fileName&, const STLFormat&); + // Manually selected choice of ASCII/BINARY/UNKNOWN(detect) formats. + STLReader(const fileName& filename, const STLFormat& format); //- Destructor @@ -110,45 +114,44 @@ public: // Member Functions - //- File read was already sorted - bool sorted() const - { - return sorted_; - } - //- Flush all values - void clear() + void clear(); + + //- File read was already sorted? + inline bool sorted() const { - sorted_ = true; - points_.clear(); - zoneIds_.clear(); - names_.clear(); - sizes_.clear(); + return sorted_; } //- Return full access to the points - pointField& points() + inline pointField& points() { return points_; } //- Return full access to the zoneIds - List<label>& zoneIds() + inline List<label>& zoneIds() { return zoneIds_; } //- The list of solid names in the order of their first appearance - List<word>& names() + inline List<word>& names() { return names_; } //- The list of solid sizes in the order of their first appearance - List<label>& sizes() + inline List<label>& sizes() { return sizes_; } + + //- The STL format used (ASCII or BINARY) + inline enum STLFormat stlFormat() const + { + return format_; + } }; diff --git a/src/fileFormats/stl/STLReaderASCII.L b/src/fileFormats/stl/STLReaderASCII.L index 515a1be90d..0ea759151c 100644 --- a/src/fileFormats/stl/STLReaderASCII.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 | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | Copyright (C) 2016-2017 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -97,13 +97,13 @@ public: // Access - //- Do all the solid groups appear in order + //- Do all the solid groups appear in order? inline bool sorted() const { return sorted_; } - //- A list of points corresponding to a pointField + //- A list of unstitched triangle points inline DynamicList<point>& points() { return points_; @@ -116,13 +116,13 @@ public: return facets_; } - //- Names + //- Solid names in the order of their appearance. inline DynamicList<word>& names() { return names_; } - //- Sizes + //- Solid sizes in the order of their appearance. inline DynamicList<label>& sizes() { return sizes_; @@ -396,6 +396,8 @@ bool Foam::fileFormats::STLReader::readASCII const fileName& filename ) { + format_ = UNKNOWN; + IFstream is(filename); if (!is) { @@ -417,6 +419,7 @@ bool Foam::fileFormats::STLReader::readASCII names_.transfer(lexer.names()); sizes_.transfer(lexer.sizes()); + format_ = ASCII; return true; } diff --git a/src/fileFormats/stl/STLpoint.H b/src/fileFormats/stl/STLpoint.H index c9862eaf94..3c432c09ee 100644 --- a/src/fileFormats/stl/STLpoint.H +++ b/src/fileFormats/stl/STLpoint.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 | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | Copyright (C) 2016-2017 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -25,7 +25,7 @@ Class Foam::STLpoint Description - A vertex point representation for STL files. + A vertex point or facet normal representation for STL files. \*---------------------------------------------------------------------------*/ @@ -64,6 +64,12 @@ public: Vector<float>(x, y, z) {} + //- Construct from components + inline STLpoint(double x, double y, double z) + : + Vector<float>(float(x), float(y), float(z)) + {} + //- Construct from point inline STLpoint(const point& pt) : diff --git a/src/fileFormats/stl/STLtriangle.H b/src/fileFormats/stl/STLtriangle.H index a80f5498c5..bf2bed3ea1 100644 --- a/src/fileFormats/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 | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | Copyright (C) 2016-2017 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -46,7 +46,7 @@ namespace Foam // Forward declaration of friend functions and operators class STLtriangle; -Ostream& operator<<(Ostream&, const STLtriangle&); +Ostream& operator<<(Ostream& os, const STLtriangle& tri); /*---------------------------------------------------------------------------*\ Class STLtriangle Declaration @@ -54,18 +54,20 @@ Ostream& operator<<(Ostream&, const STLtriangle&); class STLtriangle { - // Private data + // Typedefs - //- Attribute is 16-bit - typedef unsigned short STLattrib; + //- Attribute is 16-bit + typedef unsigned short STLattrib; - //- The face normal, many programs write zero or other junk - STLpoint normal_; + // Private data + // NB: The order of the members (1 normal, 3 points, 1 attribute) is + // essential when reading/writing binary content. - //- The three points defining the triangle - STLpoint a_, b_, c_; + //- The face normal and the three points defining the triangle. + // Some programs may write zero or other junk for the normal. + STLpoint normal_, a_, b_, c_; - //- The attribute information could for colour or solid id, etc + //- The attribute information could be for 'color' or solid id, etc STLattrib attrib_; @@ -87,7 +89,7 @@ public: ); //- Construct from istream (read binary) - inline STLtriangle(istream&); + inline STLtriangle(std::istream& is); // Member Functions @@ -104,13 +106,13 @@ public: // Read //- Read from istream (binary) - inline void read(istream&); + inline void read(std::istream& is); // Write //- Write to ostream (binary) - inline void write(ostream&) const; + inline void write(std::ostream& os) const; //- Write to Ostream (ASCII) inline Ostream& print(Ostream& os) const; @@ -138,7 +140,8 @@ public: // Ostream operator - inline friend Ostream& operator<<(Ostream&, const STLtriangle&); + //- Print triangle contents + inline friend Ostream& operator<<(Ostream& os, const STLtriangle& tri); }; diff --git a/src/fileFormats/stl/STLtriangleI.H b/src/fileFormats/stl/STLtriangleI.H index 85e02be3d4..541bec22bf 100644 --- a/src/fileFormats/stl/STLtriangleI.H +++ b/src/fileFormats/stl/STLtriangleI.H @@ -48,7 +48,7 @@ inline Foam::STLtriangle::STLtriangle {} -inline Foam::STLtriangle::STLtriangle(istream& is) +inline Foam::STLtriangle::STLtriangle(std::istream& is) { read(is); } @@ -86,16 +86,16 @@ inline unsigned short Foam::STLtriangle::attrib() const } -inline void Foam::STLtriangle::read(istream& is) +inline void Foam::STLtriangle::read(std::istream& is) { - is.read(reinterpret_cast<char*>(this), 4*sizeof(STLpoint)); + is.read(reinterpret_cast<char*>(&normal_), 4*sizeof(STLpoint)); is.read(reinterpret_cast<char*>(&attrib_), sizeof(STLattrib)); } -inline void Foam::STLtriangle::write(ostream& os) const +inline void Foam::STLtriangle::write(std::ostream& os) const { - os.write(reinterpret_cast<const char*>(this), 4*sizeof(STLpoint)); + os.write(reinterpret_cast<const char*>(&normal_), 4*sizeof(STLpoint)); os.write(reinterpret_cast<const char*>(&attrib_), sizeof(STLattrib)); } @@ -153,13 +153,13 @@ inline void Foam::STLtriangle::write // * * * * * * * * * * * * * * * Ostream Operator * * * * * * * * * * * * * // -inline Foam::Ostream& Foam::operator<<(Ostream& os, const STLtriangle& t) +inline Foam::Ostream& Foam::operator<<(Ostream& os, const STLtriangle& tri) { - os << t.normal_ << token::SPACE - << t.a_ << token::SPACE - << t.b_ << token::SPACE - << t.c_ << token::SPACE - << t.attrib_; + os << tri.normal_ << token::SPACE + << tri.a_ << token::SPACE + << tri.b_ << token::SPACE + << tri.c_ << token::SPACE + << tri.attrib_; return os; } diff --git a/src/surfMesh/surfaceFormats/stl/STLsurfaceFormat.C b/src/surfMesh/surfaceFormats/stl/STLsurfaceFormat.C index 0529da9941..ee598a5228 100644 --- a/src/surfMesh/surfaceFormats/stl/STLsurfaceFormat.C +++ b/src/surfMesh/surfaceFormats/stl/STLsurfaceFormat.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 | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | Copyright (C) 2016-2017 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -399,7 +399,7 @@ void Foam::fileFormats::STLsurfaceFormat<Face>::write ) { // Auto-detect ASCII/BINARY extension - write(filename, surf, STLCore::DETECT); + write(filename, surf, STLCore::UNKNOWN); } @@ -430,7 +430,7 @@ void Foam::fileFormats::STLsurfaceFormat<Face>::write ) { // Auto-detect ASCII/BINARY extension - write(filename, surf, STLCore::DETECT); + write(filename, surf, STLCore::UNKNOWN); } diff --git a/src/triSurface/Make/files b/src/triSurface/Make/files index 337ccbac83..ba9df9c53d 100644 --- a/src/triSurface/Make/files +++ b/src/triSurface/Make/files @@ -5,8 +5,6 @@ triSurface/stitchTriangles.C interfaces = triSurface/interfaces $(interfaces)/STL/writeSTL.C $(interfaces)/STL/readSTL.C -$(interfaces)/STL/readSTLASCII.L -$(interfaces)/STL/readSTLBINARY.C $(interfaces)/GTS/writeGTS.C $(interfaces)/GTS/readGTS.C $(interfaces)/OBJ/readOBJ.C diff --git a/src/triSurface/triSurface/interfaces/STL/readSTL.C b/src/triSurface/triSurface/interfaces/STL/readSTL.C index 73dcb174fa..d12e78b037 100644 --- a/src/triSurface/triSurface/interfaces/STL/readSTL.C +++ b/src/triSurface/triSurface/interfaces/STL/readSTL.C @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2017 OpenCFD Ltd. \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -23,50 +23,68 @@ License \*---------------------------------------------------------------------------*/ +#include "STLReader.H" +#include "mergePoints.H" #include "triSurface.H" -#include "IFstream.H" - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -namespace Foam -{ // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // -bool triSurface::readSTL(const fileName& STLfileName) +bool Foam::triSurface::readSTL(const fileName& STLfileName, bool forceBinary) { - token firstToken; + // Read in the values + fileFormats::STLReader reader + ( + STLfileName, + ( + forceBinary + ? fileFormats::STLCore::BINARY + : fileFormats::STLCore::UNKNOWN + ) + ); + + // Stitch points + labelList pointMap; + label nUniquePoints = mergePoints + ( + reader.points(), + ( + // With the merge distance depending on the input format + (reader.stlFormat() == fileFormats::STLCore::BINARY ? 10 : 100) + * SMALL + ), + false, // verbose + pointMap // old to new point map + ); + + const pointField& readpts = reader.points(); + const labelList& zoneIds = reader.zoneIds(); + + pointField& pointLst = storedPoints(); + List<Face>& faceLst = storedFaces(); + + // Sizing + pointLst.setSize(nUniquePoints); + faceLst.setSize(zoneIds.size()); + + // Assign points + forAll(readpts, pointi) { - IFstream str(STLfileName); - - if (!str.good()) - { - return false; - } - firstToken = token(str); + pointLst[pointMap[pointi]] = readpts[pointi]; } - if (firstToken.isWord()) + // Assign triangles + label pointi = 0; + forAll(faceLst, i) { - word firstWord(firstToken.wordToken()); + Face& f = faceLst[i]; - for (size_t i = 0; i < firstWord.size(); i++) - { - firstWord[i] = std::toupper(firstWord[i]); - } - - if (firstWord == "SOLID" || firstWord(5) == "SOLID") - { - return readSTLASCII(STLfileName); - } + f[0] = pointMap[pointi++]; + f[1] = pointMap[pointi++]; + f[2] = pointMap[pointi++]; + f.region() = zoneIds[i]; } - return readSTLBINARY(STLfileName); + return true; } - -// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // - -} // End namespace Foam - // ************************************************************************* // diff --git a/src/triSurface/triSurface/interfaces/STL/readSTLASCII.L b/src/triSurface/triSurface/interfaces/STL/readSTLASCII.L deleted file mode 100644 index 2de0ac13aa..0000000000 --- a/src/triSurface/triSurface/interfaces/STL/readSTLASCII.L +++ /dev/null @@ -1,490 +0,0 @@ -/*--------------------------------*- C++ -*----------------------------------*\ - ========= | - \\ / F ield | OpenFOAM: The Open Source CFD Toolbox - \\ / O peration | - \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation - \\/ 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/>. - -\*---------------------------------------------------------------------------*/ - -%{ - -#undef yyFlexLexer - - /* ------------------------------------------------------------------------ *\ - ------ local definitions - \* ------------------------------------------------------------------------ */ - -#include "IFstream.H" -#include "triSurface.H" -#include "floatVector.H" -#include "OSspecific.H" -#include "mergePoints.H" -//#include "memInfo.H" - -using namespace Foam; - -// Dummy yyFlexLexer::yylex() to keep the linker happy. It is not called -//! \cond dummy -int yyFlexLexer::yylex() -{ - FatalErrorInFunction - << "Should not have called this function" - << abort(FatalError); - return 0; -} -//! \endcond - -// Dummy yywrap to keep yylex happy at compile time. -// It is called by yylex but is not used as the mechanism to change file. -// See <<EOF>> -//! \cond dummy -#if YY_FLEX_MINOR_VERSION < 6 && YY_FLEX_SUBMINOR_VERSION < 34 -extern "C" int yywrap() -#else -int yyFlexLexer::yywrap() -#endif -{ - return 1; -} -//! \endcond - - -class STLLexer -: - public yyFlexLexer -{ - // Private data - - label nTriangles_; - short region_; // current region - short maxRegion_; // max region - - label lineNo_; - word startError_; - - DynamicList<floatVector> STLpoints_; - //DynamicList<floatVector > STLnormals_; - DynamicList<label> STLlabels_; - HashTable<label, word> STLsolidNames_; - - -public: - - // Constructors - - //- From input stream and the approximate number of vertices in the STL - STLLexer(istream* is, const label approxNpoints); - - - // Member Functions - - //- The lexer function itself - int lex(); - - // Access - - label nTriangles() const - { - return nTriangles_; - } - - DynamicList<floatVector>& STLpoints() - { - return STLpoints_; - } - - //DynamicList<floatVector>& STLnormals() - //{ - // return STLnormals_; - //} - - DynamicList<label>& STLlabels() - { - return STLlabels_; - } - - const HashTable<label, word>& STLsolidNames() const - { - return STLsolidNames_; - } -}; - - -STLLexer::STLLexer(istream* is, const label approxNpoints) -: - yyFlexLexer(is), - - nTriangles_(0), - region_(-1), - maxRegion_(0), - - lineNo_(1), - - STLpoints_(approxNpoints), - //STLnormals_(approxNpoints), - STLlabels_(approxNpoints) -{} - - - /* ------------------------------------------------------------------------ *\ - ------ cppLexer::yylex() - \* ------------------------------------------------------------------------ */ - -#define YY_DECL int STLLexer::lex() - -%} - -one_space [ \t\f\r] -space {one_space}* -some_space {one_space}+ - -alpha [_A-Za-z] -digit [0-9] - -integer {digit}+ -signedInteger [-+]?{digit}+ - -word ([[:alnum:]]|[[:punct:]])* -string {word}({some_space}{word})* - -exponent_part [eE][-+]?{digit}+ -fractional_constant [-+]?(({digit}*"."{digit}+)|({digit}+"."?)) - -floatNum (({fractional_constant}{exponent_part}?)|({digit}+{exponent_part})) - -x {floatNum} -y {floatNum} -z {floatNum} - -solid {space}("solid"|"SOLID"){space} -color {space}("color"|"COLOR"){some_space}{floatNum}{some_space}{floatNum}{some_space}{floatNum}{space} -facet {space}("facet"|"FACET"){space} -normal {space}("normal"|"NORMAL"){space} -point {space}{x}{some_space}{y}{some_space}{z}{space} -outerloop {space}("outer"{some_space}"loop")|("OUTER"{some_space}"LOOP"){space} -vertex {space}("vertex"|"VERTEX"){space} -endloop {space}("endloop"|"ENDLOOP"){space} -endfacet {space}("endfacet"|"ENDFACET"){space} -endsolid {space}("endsolid"|"ENDSOLID")({some_space}{word})* - - - /* ------------------------------------------------------------------------ *\ - ----- Exclusive start states ----- - \* ------------------------------------------------------------------------ */ - -%option stack - -%x readSolidName -%x readFacet -%x readNormal -%x readVertices -%x readVertex -%x stlerror - -%% - -%{ - // End of read character pointer returned by strtof - // char* endPtr; - - floatVector normal; - floatVector vertex; - label cmpt = 0; // component index used for reading vertex - - static const char* stateNames[7] = - { - "reading solid", - "reading solid name", - "reading facet", - "reading normal", - "reading vertices", - "reading vertex", - "error" - }; - - static const char* stateExpects[7] = - { - "'solid', 'color', 'facet' or 'endsolid'", - "<string>", - "'normal', 'outer loop' or 'endfacet'", - "<float> <float> <float>", - "'vertex' or 'endloop'", - "<float> <float> <float>", - "" - }; -%} - - - /* ------------------------------------------------------------------------ *\ - ------ Start Lexing ------ - \* ------------------------------------------------------------------------ */ - - /* ------ Reading control header ------ */ - -{solid} { - BEGIN(readSolidName); - } - -<readSolidName>{string} { - word solidName(Foam::string::validate<word>(YYText())); - if (STLsolidNames_.found(solidName)) - { - region_ = STLsolidNames_[solidName]; - } - else - { - region_ = maxRegion_++; - STLsolidNames_.insert(solidName, region_); - } - BEGIN(INITIAL); - } - -<readSolidName>{space}\n { - word solidName("solid"); - if (STLsolidNames_.found(solidName)) - { - region_ = STLsolidNames_[solidName]; - } - else - { - region_ = maxRegion_++; - STLsolidNames_.insert(solidName, region_); - } - - lineNo_++; - - BEGIN(INITIAL); - } - -{color} { - } - -{facet} { - BEGIN(readFacet); - } - -<readFacet>{normal} { - BEGIN(readNormal); - } - -<readNormal>{point} { - /* - normal.x() = strtof(YYText(), &endPtr); - normal.y() = strtof(endPtr, &endPtr); - normal.z() = strtof(endPtr, &endPtr); - STLnormals_.append(normal); - */ - BEGIN(readFacet); - } - -<readFacet>{outerloop} { - BEGIN(readVertices); - } - -<readVertices>{vertex} { - BEGIN(readVertex); - } - -<readVertex>{space}{signedInteger}{space} { - vertex[cmpt++] = atol(YYText()); - - if (cmpt == 3) - { - cmpt = 0; - STLpoints_.append(vertex); - BEGIN(readVertices); - } - } - -<readVertex>{space}{floatNum}{space} { - vertex[cmpt++] = atof(YYText()); - - if (cmpt == 3) - { - cmpt = 0; - STLpoints_.append(vertex); - BEGIN(readVertices); - } - } - -<readVertices>{endloop} { - BEGIN(readFacet); - } - -<readFacet>{endfacet} { - nTriangles_++; - STLlabels_.append(region_); - BEGIN(INITIAL); - } - -{endsolid} { - } - - - /* ------------------ Ignore remaining space and \n s. -------------------- */ - -<*>{space} {} -<*>\n { lineNo_++; } - - - /* ------------------- Any other characters are errors -------------------- */ - -<*>. { - startError_ = YYText(); - yy_push_state(stlerror); - } - - - /* ---------------------------- Error handler ----------------------------- */ - -<stlerror>.* { - yy_pop_state(); - FatalErrorInFunction - << "while " << stateNames[YY_START] << " on line " << lineNo_ << nl - << " expected " << stateExpects[YY_START] - << " but found '" << startError_.c_str() << YYText() << "'" - << exit(FatalError); - } - - - /* ------------------------ On EOF terminate ---------------------------- */ - -<<EOF>> { - yyterminate(); - } -%% - - -#include <fstream> - -bool triSurface::readSTLASCII(const fileName& STLfileName) -{ - IFstream STLstream(STLfileName); - - if (!STLstream) - { - FatalErrorInFunction - << "file " << STLfileName << " not found" - << exit(FatalError); - } - - //memInfo memStat; - - //memStat.update(); - //Pout<< "At start:" << memStat.rss() << endl; - - // Create the lexer obtaining the approximate number of vertices in the STL - // from the file size - STLLexer lexer(&STLstream.stdStream(), Foam::fileSize(STLfileName)/400); - while (lexer.lex() != 0) - {} - - //memStat.update(); - //Pout<< "After lexing:" << memStat.rss() << endl; - - DynamicList<floatVector>& STLpoints = lexer.STLpoints(); - DynamicList<label>& STLlabels = lexer.STLlabels(); - - /* - DynamicList<floatVector>& STLnormals = lexer.STLnormals(); - - if (STLpoints.size() != 3*STLnormals.size()) - { - FatalErrorInFunction - << "in file " << STLfileName << endl - << "Problem: read " << STLnormals.size() << " normals" - << " but " << STLpoints.size() << " points" - << exit(FatalError); - } - */ - - labelList pointMap; - label nUniquePoints = mergePoints - ( - STLpoints, - 100*SMALL, // merge distance - false, // verbose - pointMap - ); - - //memStat.update(); - //Pout<< "After merging:" << memStat.rss() << endl; - - - pointField& sp = storedPoints(); - - setSize(lexer.nTriangles()); - sp.setSize(nUniquePoints); - forAll(STLpoints, pointi) - { - const floatVector& pt = STLpoints[pointi]; - sp[pointMap[pointi]] = vector - ( - scalar(pt.x()), - scalar(pt.y()), - scalar(pt.z()) - ); - } - - // Assign triangles - label pointi = 0; - forAll(*this, i) - { - operator[](i)[0] = pointMap[pointi++]; - operator[](i)[1] = pointMap[pointi++]; - operator[](i)[2] = pointMap[pointi++]; - operator[](i).region() = STLlabels[i]; - } - - //memStat.update(); - //Pout<< "After assigning:" << memStat.rss() << endl; - - - STLpoints.clear(); - STLlabels.clear(); - - - // Convert solidNames into regionNames - patches_.setSize(lexer.STLsolidNames().size()); - - for - ( - HashTable<label, word>::const_iterator iter = - lexer.STLsolidNames().begin(); - iter != lexer.STLsolidNames().end(); - ++iter - ) - { - patches_[iter()].name() = iter.key(); - } - - // Fill in the missing information in the patches - setDefaultPatches(); - - //memStat.update(); - //Pout<< "After patchifying:" << memStat.rss() << endl; - - return true; -} - - - /* ------------------------------------------------------------------------ *\ - ------ End of STLToFoam.L - \* ------------------------------------------------------------------------ */ diff --git a/src/triSurface/triSurface/interfaces/STL/readSTLBINARY.C b/src/triSurface/triSurface/interfaces/STL/readSTLBINARY.C deleted file mode 100644 index d44274b12c..0000000000 --- a/src/triSurface/triSurface/interfaces/STL/readSTLBINARY.C +++ /dev/null @@ -1,152 +0,0 @@ -/*---------------------------------------------------------------------------*\ - ========= | - \\ / F ield | OpenFOAM: The Open Source CFD Toolbox - \\ / O peration | - \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation - \\/ 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/>. - -\*---------------------------------------------------------------------------*/ - -#include "triSurface.H" -#include "STLtriangle.H" -#include "IFstream.H" -#include "OSspecific.H" -#include "gzstream.h" -#include "floatVector.H" -#include "mergePoints.H" - -// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // - -bool Foam::triSurface::readSTLBINARY(const fileName& STLfileName) -{ - bool compressed = false; - - autoPtr<istream> STLfilePtr - ( - new ifstream(STLfileName.c_str(), std::ios::binary) - ); - - // If the file is compressed, decompress it before reading. - if (!STLfilePtr->good() && isFile(STLfileName + ".gz", false)) - { - compressed = true; - STLfilePtr.reset(new igzstream((STLfileName + ".gz").c_str())); - } - istream& STLfile = STLfilePtr(); - - if (!STLfile.good()) - { - FatalErrorInFunction - << "Cannot read file " << STLfileName - << " or file " << STLfileName + ".gz" - << exit(FatalError); - } - - // Read the STL header - char header[STLheaderSize]; - STLfile.read(header, STLheaderSize); - - // Check that stream is OK, if not this maybe an ASCII file - if (!STLfile) - { - return false; - } - - // Read the number of triangles in the STl file - // (note: read as int so we can check whether >2^31) - int nTris; - STLfile.read(reinterpret_cast<char*>(&nTris), sizeof(unsigned int)); - - // Check that stream is OK and number of triangles is positive, - // if not this maybe an ASCII file - if (!STLfile || nTris < 0) - { - return false; - } - - // Compare the size of the file with that expected from the number of tris - // If the comparison is not sensible then it maybe an ASCII file - if (!compressed) - { - label dataFileSize = Foam::fileSize(STLfileName) - 80; - - if (nTris < dataFileSize/50 || nTris > dataFileSize/25) - { - return false; - } - } - - // Everything OK so go ahead and read the triangles. - - // Allocate storage for raw points - List<floatVector> STLpoints(3*nTris); - setSize(nTris); - - label pointi = 0; - - for (label i = 0; i < nTris; i++) - { - // Read an STL triangle - STLtriangle stlTri(STLfile); - - // Set the STLpoints to the vertices of the STL triangle - STLpoints[pointi++] = stlTri.a(); - STLpoints[pointi++] = stlTri.b(); - STLpoints[pointi++] = stlTri.c(); - operator[](i).region() = stlTri.attrib(); - } - - // Stitch points - labelList pointMap; - label nUniquePoints = mergePoints - ( - STLpoints, - 10*SMALL, // merge distance - false, // verbose - pointMap // old to new - ); - - pointField& sp = storedPoints(); - - sp.setSize(nUniquePoints); - forAll(STLpoints, pointi) - { - const floatVector& pt = STLpoints[pointi]; - sp[pointMap[pointi]] = vector - ( - scalar(pt.x()), - scalar(pt.y()), - scalar(pt.z()) - ); - } - - // Assign triangles - pointi = 0; - forAll(*this, i) - { - operator[](i)[0] = pointMap[pointi++]; - operator[](i)[1] = pointMap[pointi++]; - operator[](i)[2] = pointMap[pointi++]; - } - - return true; -} - - -// ************************************************************************* // diff --git a/src/triSurface/triSurface/interfaces/STL/writeSTL.C b/src/triSurface/triSurface/interfaces/STL/writeSTL.C index 3532b006ab..fc8c2d0b94 100644 --- a/src/triSurface/triSurface/interfaces/STL/writeSTL.C +++ b/src/triSurface/triSurface/interfaces/STL/writeSTL.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) 2017 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -24,9 +24,22 @@ License \*---------------------------------------------------------------------------*/ #include "triSurface.H" -#include "STLtriangle.H" +#include "STLCore.H" #include "primitivePatch.H" + +// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * // + +// A file-scope helper class to expose static member(s) +// This is a temporary measure and is expected to disappear in the future +struct triSurfaceSTLCore +: + public Foam::fileFormats::STLCore +{ + using Foam::fileFormats::STLCore::writeBinaryHeader; +}; + + // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // void Foam::triSurface::writeSTLASCII(const bool writeSorted, Ostream& os) const @@ -53,26 +66,17 @@ void Foam::triSurface::writeSTLASCII(const bool writeSorted, Ostream& os) const ) { const label facei = faceMap[faceIndex++]; - - const vector& n = faceNormals()[facei]; - - os << " facet normal " - << n.x() << ' ' << n.y() << ' ' << n.z() << nl - << " outer loop" << endl; - const labelledTri& f = (*this)[facei]; - const point& pa = points()[f[0]]; - const point& pb = points()[f[1]]; - const point& pc = points()[f[2]]; - - os << " vertex " - << pa.x() << ' ' << pa.y() << ' ' << pa.z() << nl - << " vertex " - << pb.x() << ' ' << pb.y() << ' ' << pb.z() << nl - << " vertex " - << pc.x() << ' ' << pc.y() << ' ' << pc.z() << nl - << " endloop" << nl - << " endfacet" << endl; + + // Write ASCII + STLtriangle::write + ( + os, + faceNormals()[facei], + points()[f[0]], + points()[f[1]], + points()[f[2]] + ); } os << "endsolid " << patch.name() << endl; @@ -93,46 +97,35 @@ void Foam::triSurface::writeSTLASCII(const bool writeSorted, Ostream& os) const } label currentPatchi = -1; - forAll(*this, facei) { if (currentPatchi != patchIDs[facei]) { if (currentPatchi != -1) { - // Have already valid patch. Close it. - os << "endsolid " << patches[currentPatchi].name() - << nl; + // Close previous solid + os << "endsolid " << patches[currentPatchi].name() << nl; } currentPatchi = patchIDs[facei]; os << "solid " << patches[currentPatchi].name() << nl; } - const vector& n = faceNormals()[facei]; - - os << " facet normal " - << n.x() << ' ' << n.y() << ' ' << n.z() << nl - << " outer loop" << endl; - const labelledTri& f = (*this)[facei]; - const point& pa = points()[f[0]]; - const point& pb = points()[f[1]]; - const point& pc = points()[f[2]]; - - os << " vertex " - << pa.x() << ' ' << pa.y() << ' ' << pa.z() << nl - << " vertex " - << pb.x() << ' ' << pb.y() << ' ' << pb.z() << nl - << " vertex " - << pc.x() << ' ' << pc.y() << ' ' << pc.z() << nl - << " endloop" << nl - << " endfacet" << endl; + + // Write ASCII + STLtriangle::write + ( + os, + faceNormals()[facei], + points()[f[0]], + points()[f[1]], + points()[f[2]] + ); } if (currentPatchi != -1) { - os << "endsolid " << patches[currentPatchi].name() - << nl; + os << "endsolid " << patches[currentPatchi].name() << nl; } } } @@ -141,27 +134,21 @@ void Foam::triSurface::writeSTLASCII(const bool writeSorted, Ostream& os) const void Foam::triSurface::writeSTLBINARY(std::ostream& os) const { // Write the STL header - string header("Foam binary STL", STLheaderSize); - os.write(header.c_str(), STLheaderSize); - - label nTris = size(); - os.write(reinterpret_cast<char*>(&nTris), sizeof(unsigned int)); - - const vectorField& normals = faceNormals(); + triSurfaceSTLCore::writeBinaryHeader(os, this->size()); forAll(*this, facei) { const labelledTri& f = (*this)[facei]; - // Convert vector into STL single precision - STLpoint n(normals[facei]); - STLpoint pa(points()[f[0]]); - STLpoint pb(points()[f[1]]); - STLpoint pc(points()[f[2]]); - - STLtriangle stlTri(n, pa, pb, pc, f.region()); - - stlTri.write(os); + // Write BINARY + STLtriangle + ( + faceNormals()[facei], + points()[f[0]], + points()[f[1]], + points()[f[2]], + f.region() + ).write(os); } } diff --git a/src/triSurface/triSurface/triSurface.C b/src/triSurface/triSurface/triSurface.C index a5478fcf3e..eb262d6cea 100644 --- a/src/triSurface/triSurface/triSurface.C +++ b/src/triSurface/triSurface/triSurface.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 | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | Copyright (C) 2016-2017 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -379,7 +379,7 @@ bool Foam::triSurface::read } else if (ext == "stlb") { - return readSTLBINARY(name); + return readSTL(name, true); } else if (ext == "gts") { diff --git a/src/triSurface/triSurface/triSurface.H b/src/triSurface/triSurface/triSurface.H index 4c05e8d1a8..d6debc7b3a 100644 --- a/src/triSurface/triSurface/triSurface.H +++ b/src/triSurface/triSurface/triSurface.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 | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | Copyright (C) 2016-2017 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -130,9 +130,7 @@ class triSurface //- Generic read routine. Chooses reader based on extension. bool read(const fileName&, const word& ext, const bool check = true); - bool readSTL(const fileName&); - bool readSTLASCII(const fileName&); - bool readSTLBINARY(const fileName&); + bool readSTL(const fileName&, bool forceBinary=false); bool readGTS(const fileName&); bool readOBJ(const fileName&); bool readOFF(const fileName&); -- GitLab