Xinqi Bao's Git

XbSlicer, re-organized the entire project
[XbSlicer.git] / src / STL.cc
1 #include "STL.hh"
2
3 #include <fstream>
4
5 #include "BufferReadBinary.hh"
6 #include "Configurations.hh"
7 using namespace std;
8
9 Stl::Stl() {} // Have to call the function read() later
10 Stl::Stl(std::string& stl_target, bool isBinary)
11 {
12 // TODO: if the stl file does not exist
13 read(stl_target, isBinary);
14 }
15
16 double Stl::getZmax() const { return zmax; }
17 double Stl::getZmin() const { return zmin; }
18
19 int Stl::read(string& stl_target, bool isBinary)
20 {
21 // TODO: read for ASCII and binary
22 int numTriangles;
23 if (isBinary)
24 numTriangles = readBinary(stl_target);
25 else
26 numTriangles = readASCII(stl_target);
27 setMinAndMax();
28 if (needMoveToCenter) moveToCenter();
29 assignTriangles();
30 return numTriangles;
31 }
32
33 // see stl format for ASCII file
34 int Stl::readASCII(string& fileTarget)
35 {
36 ifstream f(fileTarget);
37 streampos pos = f.tellg();
38 f.seekg(0, ios_base::end);
39 int len = f.tellg();
40 f.seekg(pos);
41 triangles.reserve(len / 150);
42 /*char s[256];
43 while (f >> s) {
44 if (!strcmp(s,"facet")) {
45 triangles.push_back(Triangle(f));
46 }
47 }*/ //old version for read stl
48 f.ignore(256, '\n');
49 while (f.peek() != 'e') triangles.push_back(Triangle(f));
50 f.close();
51 return triangles.size();
52 }
53
54 // see stl format for binary file
55 // will much faster than read in by ASCII file
56 // and using BufferReadBinary.o to reduce the I/O time
57 int Stl::readBinary(string& fileTarget)
58 {
59 BufferReadBinary buffer(fileTarget);
60 // a number in the stl file which means total number for triangles
61 uint32_t numTrianglesInFile = buffer.getNumTrianglesInFile();
62 triangles.reserve(numTrianglesInFile);
63 while (numTrianglesInFile)
64 {
65 int numTrianglesInBlock = buffer.getNumTrianglesInBlock();
66 numTrianglesInFile -= numTrianglesInBlock;
67 while (numTrianglesInBlock)
68 {
69 triangles.push_back(Triangle(buffer));
70 numTrianglesInBlock--;
71 }
72 buffer.readBuffer();
73 }
74 return triangles.size();
75 }
76
77 // By using more memory to speed up the program
78 // After assign the triangles, no need to check triangles which is out of the
79 // high range
80 void Stl::assignTriangles()
81 {
82 double invDz = 1.0 / dzEachLevel;
83 numLevels = (zmax - zmin) * invDz + 1;
84 levels.reserve(numLevels);
85 int meanTrianglesPerLevel = triangles.size() / numLevels * 1.5;
86 for (int i = 0; i < numLevels; i++)
87 {
88 levels.push_back(vector<Triangle>());
89 levels.back().reserve(meanTrianglesPerLevel);
90 }
91 for (const auto& t : triangles)
92 {
93 double zmint, zmaxt;
94 if (t.v1.z < t.v2.z)
95 {
96 zmint = t.v1.z;
97 zmaxt = t.v2.z;
98 }
99 else
100 {
101 zmaxt = t.v1.z;
102 zmint = t.v2.z;
103 }
104 zmint = zmint < t.v3.z ? zmint : t.v3.z;
105 zmaxt = zmaxt > t.v3.z ? zmaxt : t.v3.z;
106 for (int slice = int((zmint - zmin) * invDz);
107 slice <= int((zmaxt - zmin) * invDz); slice++)
108 levels[slice].push_back(t);
109 }
110 triangles.clear();
111 // triangles.~vector();
112 }
113
114 // set the minimum and maximum of x, y and z, can be used by latter optimization
115 void Stl::setMinAndMax()
116 {
117 if (triangles.empty()) return;
118 xmin = xmax = triangles.front().v1.x;
119 ymin = ymax = triangles.front().v1.y;
120 zmin = zmax = triangles.front().v1.z;
121
122 for (const auto& t : triangles)
123 {
124 double xmint = t.v1.x, xmaxt = t.v1.x;
125 double ymint = t.v1.y, ymaxt = t.v1.y;
126 double zmint = t.v1.z, zmaxt = t.v1.z;
127
128 if (t.v2.x < xmint)
129 xmint = t.v2.x;
130 else
131 xmaxt = t.v2.x;
132 if (t.v3.x < xmint)
133 xmint = t.v3.x;
134 else if (t.v3.x > xmaxt)
135 xmaxt = t.v3.x;
136
137 if (t.v2.y < ymint)
138 ymint = t.v2.y;
139 else
140 ymaxt = t.v2.y;
141 if (t.v3.y < ymint)
142 ymint = t.v3.y;
143 else if (t.v3.y > ymaxt)
144 ymaxt = t.v3.y;
145
146 if (t.v2.z < zmint)
147 zmint = t.v2.z;
148 else
149 zmaxt = t.v2.z;
150 if (t.v3.z < zmint)
151 zmint = t.v3.z;
152 else if (t.v3.z > zmaxt)
153 zmaxt = t.v3.z;
154
155 if (xmint < xmin) xmin = xmint;
156 if (xmaxt > xmax) xmax = xmaxt;
157 if (ymint < ymin) ymin = ymint;
158 if (ymaxt > ymax) ymax = ymaxt;
159 if (zmint < zmin) zmin = zmint;
160 if (zmaxt > zmax) zmax = zmaxt;
161 }
162 }
163
164 // Sometime the model does not locate at a great position
165 // By the setted center point of printer table, move the model to a nice place
166 void Stl::moveToCenter()
167 {
168 double mvX = centerX - (xmax + xmin) / 2;
169 double mvY = centerY - (ymax + ymin) / 2;
170 double mvZ = centerZ - zmin;
171
172 for (auto& t : triangles)
173 {
174 t.v1.x += mvX;
175 t.v1.y += mvY;
176 t.v1.z += mvZ;
177
178 t.v2.x += mvX;
179 t.v2.y += mvY;
180 t.v2.z += mvZ;
181
182 t.v3.x += mvX;
183 t.v3.y += mvY;
184 t.v3.z += mvZ;
185 }
186
187 xmin += mvX;
188 xmax += mvX;
189 ymin += mvY;
190 ymax += mvY;
191 zmin += mvZ;
192 zmax += mvZ;
193 }
194
195 vector<Triangle>& Stl::getLevel(double z)
196 {
197 return levels.at(int(z - zmin) / dzEachLevel);
198 }
199
200 void Stl::printSTL()
201 { // need to comment "triangles.clear();" in assignTriangles function
202 cout << "number of triangles: " << triangles.size() << '\n';
203 for (int i = 0; i < triangles.size(); i++)
204 cout << "# " << i << " :\n" << triangles.at(i) << '\n';
205 }