readSTLBINARY.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
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.
15 
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.
20 
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/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "triSurface.H"
27 #include "STLtriangle.H"
28 #include "IFstream.H"
29 #include "OSspecific.H"
30 #include "gzstream.h"
31 #include "floatVector.H"
32 #include "mergePoints.H"
33 
34 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
35 
36 bool Foam::triSurface::readSTLBINARY(const fileName& STLfileName)
37 {
38  bool compressed = false;
39 
40  autoPtr<istream> STLfilePtr
41  (
42  new ifstream(STLfileName.c_str(), std::ios::binary)
43  );
44 
45  // If the file is compressed, decompress it before reading.
46  if (!STLfilePtr->good() && isFile(STLfileName + ".gz", false))
47  {
48  compressed = true;
49  STLfilePtr.reset(new igzstream((STLfileName + ".gz").c_str()));
50  }
51  istream& STLfile = STLfilePtr();
52 
53  if (!STLfile.good())
54  {
56  << "Cannot read file " << STLfileName
57  << " or file " << STLfileName + ".gz"
58  << exit(FatalError);
59  }
60 
61  // Read the STL header
62  char header[STLheaderSize];
63  STLfile.read(header, STLheaderSize);
64 
65  // Check that stream is OK, if not this maybe an ASCII file
66  if (!STLfile)
67  {
68  return false;
69  }
70 
71  // Read the number of triangles in the STl file
72  // (note: read as int so we can check whether >2^31)
73  int nTris;
74  STLfile.read(reinterpret_cast<char*>(&nTris), sizeof(unsigned int));
75 
76  // Check that stream is OK and number of triangles is positive,
77  // if not this maybe an ASCII file
78  if (!STLfile || nTris < 0)
79  {
80  return false;
81  }
82 
83  // Compare the size of the file with that expected from the number of tris
84  // If the comparison is not sensible then it maybe an ASCII file
85  if (!compressed)
86  {
87  label dataFileSize = Foam::fileSize(STLfileName) - 80;
88 
89  if (nTris < dataFileSize/50 || nTris > dataFileSize/25)
90  {
91  return false;
92  }
93  }
94 
95  // Everything OK so go ahead and read the triangles.
96 
97  // Allocate storage for raw points
98  List<floatVector> STLpoints(3*nTris);
99  setSize(nTris);
100 
101  label pointi = 0;
102 
103  for (label i = 0; i < nTris; i++)
104  {
105  // Read an STL triangle
106  STLtriangle stlTri(STLfile);
107 
108  // Set the STLpoints to the vertices of the STL triangle
109  STLpoints[pointi++] = stlTri.a();
110  STLpoints[pointi++] = stlTri.b();
111  STLpoints[pointi++] = stlTri.c();
112  operator[](i).region() = stlTri.attrib();
113  }
114 
115  // Stitch points
116  labelList pointMap;
117  label nUniquePoints = mergePoints
118  (
119  STLpoints,
120  10*SMALL, // merge distance
121  false, // verbose
122  pointMap // old to new
123  );
124 
125  pointField& sp = storedPoints();
126 
127  sp.setSize(nUniquePoints);
128  forAll(STLpoints, pointi)
129  {
130  const floatVector& pt = STLpoints[pointi];
131  sp[pointMap[pointi]] = vector
132  (
133  scalar(pt.x()),
134  scalar(pt.y()),
135  scalar(pt.z())
136  );
137  }
138 
139  // Assign triangles
140  pointi = 0;
141  forAll(*this, i)
142  {
143  operator[](i)[0] = pointMap[pointi++];
144  operator[](i)[1] = pointMap[pointi++];
145  operator[](i)[2] = pointMap[pointi++];
146  }
147 
148  return true;
149 }
150 
151 
152 // ************************************************************************* //
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:428
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
error FatalError
T & operator[](const label)
Return element of UList.
Definition: UListI.H:167
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:319
bool isFile(const fileName &, const bool checkGzip=true)
Does the name exist as a FILE in the file system?
Definition: POSIX.C:492
Vector< scalar > vector
A scalar version of the templated Vector.
Definition: vector.H:49
Functions used by OpenFOAM that are specific to POSIX compliant operating systems and need to be repl...
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:42
List< label > labelList
A List of labels.
Definition: labelList.H:56
off_t fileSize(const fileName &)
Return size of file.
Definition: POSIX.C:498
pointField & storedPoints()
Non-const access to global points.
Definition: triSurface.H:220
Merge points. See below.
Vector< float > floatVector
A float version of vector.
Definition: floatVector.H:48
void setSize(const label)
Reset size of List.
label mergePoints(const UList< Type > &points, const scalar mergeTol, const bool verbose, labelList &pointMap, const Type &origin=Type::zero)
Sorts and merges points. All points closer than/equal mergeTol get merged.