Xinqi Bao's Git

README.md: updated paper url
[XbSlicer.git] / src / Slicing.cc
1 #include "Slicing.hh"
2
3 #include <cmath>
4 #include <iostream>
5
6 #include "Configurations.hh"
7 using namespace std;
8
9 Slicing::Slicing(Stl* stl, Layer* layer) : Slicing(*stl, *layer) {}
10
11 Slicing::Slicing(Stl& stl, Layer& layer)
12 : z(layer.getZ()), loops(layer.getLoops()), triangles(stl.getLevel(z))
13 {
14 intersection();
15 mkLoop();
16 Gcode g(layer);
17 }
18
19 // return true if this pair of vectors cross this level
20 inline bool Slicing::isCross(const Vec3d& v1, const Vec3d& v2) const
21 { // not include at the vertex
22 return (v1.z + thr < z && z < v2.z - thr) ||
23 (v2.z + thr < z && z < v1.z - thr);
24 }
25
26 // check if the cut through both triangles' sides
27 bool Slicing::isSectionExist(Cross& cr) const
28 {
29 for (const auto& temp : intersections)
30 if (temp.equal(cr)) return true;
31 return false;
32 }
33
34 // push every sections into the vetor
35 // Total as 10 different cross cases, side-side for 3, vertex-side for 3,
36 // vertex-vertex for 3, through whole facet for 1.
37 // More rare cases been checked more, saving whole execution time.
38 void Slicing::intersection()
39 {
40 intersections.reserve(triangles.size() >> 1);
41 for (const auto& t : triangles)
42 {
43 if (isCross(t.v1, t.v2))
44 {
45 if (isCross(t.v1, t.v3))
46 { // Cross v1--v2 and v1--v3
47 intersections.push_back(
48 Cross(Vec2d(t.v1, t.v2, z), Vec2d(t.v1, t.v3, z)));
49 continue;
50 }
51 else if (fabs(z - t.v3.z) < thr)
52 { // Cross v1--v2 and v3
53 intersections.push_back(
54 Cross(Vec2d(t.v1, t.v2, z), Vec2d(t.v3.x, t.v3.y)));
55 continue;
56 }
57 else
58 { // definitely cross v1--v2 and v2--v3
59 intersections.push_back(
60 Cross(Vec2d(t.v1, t.v2, z), Vec2d(t.v2, t.v3, z)));
61 continue;
62 }
63 }
64 else if (isCross(t.v1, t.v3))
65 {
66 if (fabs(z - t.v2.z) < thr)
67 { // Cross v1--v3 and v2
68 intersections.push_back(
69 Cross(Vec2d(t.v1, t.v3, z), Vec2d(t.v2.x, t.v2.y)));
70 continue;
71 }
72 else
73 { // Cross v1--v3 and v2--v3
74 intersections.push_back(
75 Cross(Vec2d(t.v1, t.v3, z), Vec2d(t.v2, t.v3, z)));
76 continue;
77 }
78 }
79 else if (fabs(z - t.v1.z) < thr)
80 {
81 if (isCross(t.v2, t.v3))
82 { // Cross v1 and v2--v3
83 intersections.push_back(
84 Cross(Vec2d(t.v1.x, t.v1.y), Vec2d(t.v2, t.v3, z)));
85 continue;
86 }
87 else if (fabs(z - t.v2.z) < thr)
88 {
89 if (fabs(z - t.v3.z) < thr) // Through the whole facet
90 continue;
91 else
92 { // v1 and v2
93 Cross cr(Vec2d(t.v1.x, t.v1.y), Vec2d(t.v2.x, t.v2.y));
94 if (!isSectionExist(cr)) intersections.push_back(cr);
95 continue;
96 }
97 }
98 else if (fabs(z - t.v3.z) < thr)
99 { // v1 and v3, still need "if()", because may only cross one
100 // vertex(v1)
101 Cross cr(Vec2d(t.v1.x, t.v1.y), Vec2d(t.v3.x, t.v3.y));
102 if (!isSectionExist(cr)) intersections.push_back(cr);
103 continue;
104 }
105 }
106 else if (fabs(z - t.v2.z) < thr)
107 {
108 if (fabs(z - t.v3.z) < thr)
109 { // v2 and v3
110 Cross cr(Vec2d(t.v2.x, t.v2.y), Vec2d(t.v3.x, t.v3.y));
111 if (!isSectionExist(cr)) intersections.push_back(cr);
112 continue;
113 }
114 }
115 }
116 }
117
118 // Combine intersections to loops
119 // TODO: vector.erase() take to much time, need to be optimied
120 void Slicing::mkLoop()
121 {
122 if (intersections.empty()) return;
123 #if 1 // implement with subLoops
124 Vec2d p1(intersections.back().p1);
125 Vec2d p2(intersections.back().p2);
126 Loop lp(p1, intersections.size() >> 1);
127 lp.add(p2);
128 intersections.erase(intersections.end() - 1);
129 while (!intersections.empty())
130 {
131 if (!lp.isCompleted())
132 {
133 /**/
134 for (int i = intersections.size() - 1; i >= 0; i--)
135 {
136 if (p2.equal(intersections[i].p1))
137 {
138 p1 = p2;
139 p2 = intersections[i].p2;
140 intersections.erase(intersections.begin() + i);
141 lp.add(p2);
142 break;
143 }
144 else if (p2.equal(intersections[i].p2))
145 {
146 p1 = p2;
147 p2 = intersections[i].p1;
148 intersections.erase(intersections.begin() + i);
149 lp.add(p2);
150 break;
151 }
152 }
153 /*
154 int i = 0;
155 for (const auto& temp : intersections) {
156 if (p2.equal(temp.p1)) {
157 p1 = p2;
158 p2 = temp.p2;
159 intersections.erase(intersections.begin() + i);
160 lp.add(p2);
161 break;
162 }
163 else if (p2.equal(temp.p2)) {
164 p1 = p2;
165 p2 = temp.p1;
166 intersections.erase(intersections.begin() + i);
167 lp.add(p2);
168 break;
169 }
170 i++;
171 }*/
172 }
173 else
174 { // creat a new Loop
175 bool isSubLoop = false;
176 for (int i = loops.size() - 1; i >= 0; i--)
177 {
178 isSubLoop = loops[i].checkSubLoop(lp);
179 if (isSubLoop) break;
180 if (lp.checkSubLoop(loops[i]))
181 {
182 // lp.subLoops.push_back(loops[i]);
183 loops.erase(loops.begin() + i);
184 }
185 }
186 if (!isSubLoop) loops.push_back(lp);
187 p1 = intersections.back().p1;
188 p2 = intersections.back().p2;
189 lp = Loop(p1, intersections.size() >> 1);
190 lp.add(p2);
191 intersections.erase(intersections.end());
192 }
193 }
194 bool isSubLoop = false;
195 for (int i = loops.size() - 1; i >= 0; i--)
196 {
197 isSubLoop = loops[i].checkSubLoop(lp);
198 if (isSubLoop) break;
199 if (lp.checkSubLoop(loops[i]))
200 {
201 // lp.subLoops.push_back(loops[i]);
202 loops.erase(loops.begin() + i);
203 }
204 }
205 if (!isSubLoop) loops.push_back(lp);
206 #endif
207 #if 0
208 //Vec2d p1(intersections.front().p1);
209 //Vec2d p2(intersections.front().p2);
210 Vec2d p1(intersections.back().p1);
211 Vec2d p2(intersections.back().p2);
212 loops.push_back(Loop(p1, intersections.size() >> 1));
213 loops.back().add(p2);
214 //intersections.erase(intersections.begin());
215 intersections.pop_back();
216 while (!intersections.empty()) {
217 if (!loops.back().isCompleted()) {
218 /**/
219 for (int i = intersections.size()-1; i >= 0; i--) {
220 if (p2.equal(intersections[i].p1)) {
221 p1 = p2;
222 p2 = intersections[i].p2;
223 intersections.erase(intersections.begin() + i);
224 loops.back().add(p2);
225 break;
226 }
227 else if (p2.equal(intersections[i].p2)) {
228 p1 = p2;
229 p2 = intersections[i].p1;
230 intersections.erase(intersections.begin() + i);
231 loops.back().add(p2);
232 break;
233 }
234 }
235 /*
236 int i = 0;
237 for (const auto& temp : intersections) {
238 if (p2.equal(temp.p1)) {
239 p1 = p2;
240 p2 = temp.p2;
241 intersections.erase(intersections.begin() + i);
242 loops.back().add(p2);
243 break;
244 }
245 else if (p2.equal(temp.p2)) {
246 p1 = p2;
247 p2 = temp.p1;
248 intersections.erase(intersections.begin() + i);
249 loops.back().add(p2);
250 break;
251 }
252 i++;
253 }*/
254 }
255 else { //creat a new Loop
256 //p1 = intersections.front().p1;
257 //p2 = intersections.front().p2;
258 p1 = intersections.back().p1;
259 p2 = intersections.back().p2;
260 loops.push_back(Loop(p1, intersections.size() >> 1));
261 loops.back().add(p2);
262 //intersections.erase(intersections.begin());
263 intersections.pop_back();
264 }
265 }
266 #endif
267 #if 0 // Why take more time??
268 int size = intersections.size();
269 bool* bools = new bool[size];
270 for (int i = 0; i < size; i++)
271 bools[i] = true;
272 Vec2d p1(intersections.front().p1);
273 Vec2d p2(intersections.front().p2);
274 loops.push_back(Loop(p1, intersections.size() >> 1));
275 loops.back().add(p2);
276 bools[0] = false;
277 for (int i = 1; i < size; i++) {
278 if (!loops.back().isCompleted()) {
279 for (int k = 0; k < size; k++) {
280 if (!bools[k])
281 continue;
282 if (p2.equal(intersections[k].p1)) {
283 p1 = p2;
284 p2 = intersections[k].p2;
285 loops.back().add(p2);
286 bools[k] = false;
287 break;
288 }
289 else if (p2.equal(intersections[k].p2)) {
290 p1 = p2;
291 p2 = intersections[k].p1;
292 loops.back().add(p2);
293 bools[k] = false;
294 break;
295 }
296 }
297 }
298 else {
299 for (int k = 0; k < size; k++) {
300 if (!bools[k])
301 continue;
302 Vec2d p1(intersections[k].p1);
303 Vec2d p2(intersections[k].p2);
304 loops.push_back(Loop(p1, intersections.size() >> 1));
305 loops.back().add(p2);
306 bools[k] = false;
307 }
308 }
309 }
310 delete bools;
311 #endif
312 for (auto& lp : loops) lp.optimize();
313 }
314
315 void Slicing::printVector() const
316 {
317 cout << "\nZ as " << z << ":\tcontain " << intersections.size() << "\n";
318 for (const auto& i : intersections)
319 {
320 cout << i << '\n';
321 }
322 }
323
324 void Slicing::printLoop() const
325 {
326 for (int i = 0; i < loops.size(); i++)
327 {
328 cout << "\nLoop " << i << ", Z as " << z << '\n';
329 loops.at(i).print();
330 cout << "\n\n";
331 }
332 }