Xinqi Bao's Git

README.md: updated paper url
[XbSlicer.git] / src / GCode.cc
1 #include "GCode.hh"
2
3 #include <algorithm>
4 #include <cmath>
5
6 #include "Configurations.hh"
7 using namespace std;
8
9 Gcode::Gcode(Layer& layer)
10 : loops(layer.getLoops()),
11 commands(layer.getCommands()),
12 parts(layer.getParts()),
13 minX(layer.getMinX()),
14 maxX(layer.getMaxX())
15 {
16 if (loops.empty()) return;
17 int reserveSize = 0;
18 for (const auto& lp : loops)
19 reserveSize += lp.size() + int((lp.getmaxX() - lp.getminX()) / dp) * 2;
20 commands.reserve(reserveSize);
21 G0_high(layer.getZ());
22 // outline();
23 // fill();
24 doLoops();
25 layer.generateDe();
26 }
27
28 void Gcode::G0(double x, double y, double z)
29 {
30 commands.push_back(Command(0, x, y));
31 // f << "G0 F6600 X" << x << " Y" << y << " Z" << z << '\n';
32 // f.flush();
33 }
34 void Gcode::G0(double x, double y)
35 {
36 commands.push_back(Command(0, x, y));
37 // f << "G0 F6600 X" << x << " Y" << y << '\n';
38 // f.flush();
39 }
40 void Gcode::G0_high(double z)
41 {
42 // f << "G0 F6600 Z" << z << '\n';
43 // f.flush();
44 }
45 void Gcode::G1(double x, double y)
46 {
47 commands.push_back(Command(1, x, y));
48 // f << "G1 F783 X" << x << " Y" << y << " E" << e << '\n';
49 // f.flush();
50 }
51 void Gcode::resetE()
52 { // Reset E to 0
53 // f << "G92 E0 ; reset the expected extruder position\n";
54 // f.flush();
55 }
56
57 static double x = 0, y = 0;
58
59 void Gcode::doLoops()
60 {
61 #if 0 // by erasing the finished loop
62 while(!loops.empty()){
63 double minDistance = pow(loops.front().midX - x, 2) + pow(loops.front().midY - y, 2);
64 int k = 0;
65 double distance;
66 for(int i = 1; i < loops.size(); i++){
67 distance = pow(loops[i].midX - x, 2) + pow(loops[i].midY - y, 2);
68 if(distance < minDistance){
69 minDistance = distance;
70 k = i;
71 }
72 }
73 fillLoop(loops[k]);
74 x = commands.back().x;
75 y = commands.back().y;
76 loops.erase(loops.begin() + k);
77 }
78 #endif
79 #if 1 // by checking the visited value
80 int numLoop = loops.size();
81 while (numLoop)
82 {
83 int i = 0, k = 0;
84 double minDistance, distance;
85 while (loops[i].visited) i++;
86 minDistance = pow(loops[i].midX - x, 2) + pow(loops[i].midY - y, 2);
87 k = i;
88 for (i++; i < loops.size(); i++)
89 {
90 if (loops[i].visited) continue;
91 distance = pow(loops[i].midX - x, 2) + pow(loops[i].midY - y, 2);
92 if (distance < minDistance)
93 {
94 minDistance = distance;
95 k = i;
96 }
97 }
98 fillLoop(loops[k]);
99 loops[k].visited = true; // mark as filled loop
100 x = commands.back().x;
101 y = commands.back().y;
102 numLoop--;
103 }
104 #endif
105 }
106
107 void Gcode::fillLoop(Loop& loop)
108 {
109 vector<Loop> ploops;
110 ploops.push_back(loop);
111 int numIntersectionsTotal = loop.size();
112 for (auto& plp : loop.subLoops)
113 {
114 ploops.push_back(plp);
115 numIntersectionsTotal += plp.size();
116 }
117
118 // outline
119 double x1, y1, x2, y2;
120
121 int numLoop = ploops.size();
122 while (numLoop)
123 {
124 int i = 0, k = 0;
125 double minDistance, distance;
126 while (ploops[i].visited) i++;
127 minDistance = pow(ploops[i].midX - x, 2) + pow(ploops[i].midY - y, 2);
128 k = i;
129 for (i++; i < ploops.size(); i++)
130 {
131 if (ploops[i].visited) continue;
132 distance = pow(ploops[i].midX - x, 2) + pow(ploops[i].midY - y, 2);
133 if (distance < minDistance)
134 {
135 minDistance = distance;
136 k = i;
137 }
138 }
139 // start to print this loop's outline
140 x1 = ploops[k].back().x;
141 y1 = ploops[k].back().y;
142 G0(x1, y1);
143 for (int i = 0; i < ploops[k].size(); i++)
144 {
145 x2 = ploops[k].at(i).x;
146 y2 = ploops[k].at(i).y;
147 G1(x2, y2);
148 x1 = x2, y1 = y2;
149 }
150 ploops[k].visited = true;
151 x = commands.back().x;
152 y = commands.back().y;
153 numLoop--;
154 }
155 /*
156 for (auto& lp : ploops) {
157 x1 = lp.back().x;
158 y1 = lp.back().y;
159 G0(x1, y1);
160 for (int i = 0; i < lp.size(); i++) {
161 x2 = lp.at(i).x;
162 y2 = lp.at(i).y;
163 G1(x2, y2);
164 x1 = x2, y1 = y2;
165 }
166 }
167 */
168
169 // fill
170 vector<vector<Cross>> pparts;
171 double invDp = 1.0 / dp;
172 numParts = (loop.getmaxX() - loop.getminX()) * dp + 1;
173 pparts.reserve(numParts);
174 int meanIntersectionsPerPart = numIntersectionsTotal / numParts * 1.5;
175 for (int i = 0; i < numParts; i++)
176 {
177 pparts.push_back(vector<Cross>());
178 pparts.back().reserve(meanIntersectionsPerPart);
179 }
180 for (const auto& lp : ploops)
181 { // assign all intersections to partial
182 Vec2d v1, v2(lp.back());
183 int index1, index2 = (v2.x - loop.getminX()) * invDp;
184 int imin, imax;
185
186 for (auto& l : lp.head)
187 {
188 v1 = v2;
189 index1 = index2;
190 v2 = l;
191 index2 = (v2.x - loop.getminX()) * invDp;
192 if (index1 < index2)
193 {
194 imin = index1;
195 imax = index2;
196 }
197 else
198 {
199 imin = index2;
200 imax = index1;
201 }
202 for (int i = imin; i <= imax; i++)
203 pparts[i].push_back(Cross(v1, v2));
204 }
205 }
206
207 vector<double> ys;
208 bool isUp = true;
209 for (double x = loop.getminX() + ingap; x < loop.getmaxX(); x += ingap)
210 {
211 ys.clear();
212 double y1, y2;
213 for (auto& cr : pparts.at((x - loop.getminX()) * invDp))
214 {
215 double x1 = cr.p1.x, y1 = cr.p1.y;
216 double x2 = cr.p2.x, y2 = cr.p2.y;
217 if ((x1 <= x && x < x2) || (x2 <= x && x < x1))
218 ys.push_back((x - x1) * (y2 - y1) / (x2 - x1) + y1);
219 }
220 std::sort(ys.begin(), ys.end());
221 if (ys.size() == 0) continue;
222
223 if (isUp)
224 {
225 y1 = ys.at(0);
226 G0(x, y1);
227 bool isE = true;
228 for (int i = 1; i < ys.size(); i++)
229 {
230 y2 = ys.at(i);
231 if (isE)
232 {
233 G1(x, y2);
234 isE = false;
235 }
236 else
237 {
238 G0(x, y2);
239 y1 = y2;
240 isE = true;
241 }
242 }
243 isUp = false;
244 }
245 else
246 {
247 y1 = ys.at(ys.size() - 1);
248 G0(x, y1);
249 bool isE = true;
250 for (int i = ys.size() - 2; i >= 0; i--)
251 {
252 y2 = ys.at(i);
253 if (isE)
254 {
255 G1(x, y2);
256 isE = false;
257 }
258 else
259 {
260 G0(x, y2);
261 y1 = y2;
262 isE = true;
263 }
264 }
265 isUp = true;
266 }
267 }
268 }
269
270 void Gcode::outline()
271 {
272 double x1, y1, x2, y2;
273 for (auto& lp : loops)
274 {
275 x1 = lp.back().x;
276 y1 = lp.back().y;
277 G0(x1, y1);
278 for (int i = 0; i < lp.size(); i++)
279 {
280 x2 = lp.at(i).x;
281 y2 = lp.at(i).y;
282 G1(x2, y2);
283 x1 = x2, y1 = y2;
284 }
285 }
286 }
287
288 void Gcode::fill()
289 {
290 double invDp = 1.0 / dp;
291 minX = loops.front().getminX();
292 maxX = loops.front().getmaxX();
293 int numIntersectionsTotal = loops.front().size();
294 for (int i = 1; i < loops.size(); i++)
295 {
296 numIntersectionsTotal += loops.at(i).size();
297 if (minX > loops.at(i).getminX()) minX = loops.at(i).getminX();
298 if (maxX < loops.at(i).getmaxX()) maxX = loops.at(i).getmaxX();
299 }
300 numParts = (maxX - minX) * dp + 1;
301 parts.reserve(numParts);
302 int meanIntersectionsPerPart = numIntersectionsTotal / numParts * 1.5;
303 for (int i = 0; i < numParts; i++)
304 {
305 parts.push_back(std::vector<Cross>());
306 parts.back().reserve(meanIntersectionsPerPart);
307 }
308 for (const auto& lp : loops)
309 { // assign all intersections to partial
310 Vec2d v1(lp.back());
311 Vec2d v2(lp.front());
312 int index1 = (v1.x - minX) * invDp;
313 int index2 = (v2.x - minX) * invDp;
314 int imin, imax;
315 if (index1 < index2)
316 {
317 imin = index1;
318 imax = index2;
319 }
320 else
321 {
322 imin = index2;
323 imax = index1;
324 }
325 for (int i = imin; i <= imax; i++) parts[i].push_back(Cross(v1, v2));
326
327 for (int i = 1; i < lp.size(); i++)
328 { // from the front to the item before the back
329 v1 = v2;
330 index1 = index2;
331 v2 = lp.at(i);
332 index2 = (v2.x - minX) * invDp;
333 if (index1 < index2)
334 {
335 imin = index1;
336 imax = index2;
337 }
338 else
339 {
340 imin = index2;
341 imax = index1;
342 }
343 for (int i = imin; i <= imax; i++)
344 parts[i].push_back(Cross(v1, v2));
345 }
346 }
347 std::vector<double> ys;
348 bool isUp = true;
349 for (double x = minX + ingap; x < maxX; x += ingap)
350 {
351 ys.clear();
352 double y1, y2;
353 for (auto& cr : parts.at((x - minX) * invDp))
354 {
355 double x1 = cr.p1.x, y1 = cr.p1.y;
356 double x2 = cr.p2.x, y2 = cr.p2.y;
357 if ((x1 <= x && x < x2) || (x2 <= x && x < x1))
358 ys.push_back((x - x1) * (y2 - y1) / (x2 - x1) + y1);
359 }
360 std::sort(ys.begin(), ys.end());
361 if (ys.size() == 0) continue;
362
363 if (isUp)
364 {
365 y1 = ys.at(0);
366 G0(x, y1);
367 bool isE = true;
368 for (int i = 1; i < ys.size(); i++)
369 {
370 y2 = ys.at(i);
371 if (isE)
372 {
373 G1(x, y2);
374 isE = false;
375 }
376 else
377 {
378 G0(x, y2);
379 y1 = y2;
380 isE = true;
381 }
382 }
383 isUp = false;
384 }
385 else
386 {
387 y1 = ys.at(ys.size() - 1);
388 G0(x, y1);
389 bool isE = true;
390 for (int i = ys.size() - 2; i >= 0; i--)
391 {
392 y2 = ys.at(i);
393 if (isE)
394 {
395 G1(x, y2);
396 isE = false;
397 }
398 else
399 {
400 G0(x, y2);
401 y1 = y2;
402 isE = true;
403 }
404 }
405 isUp = true;
406 }
407 }
408 }