ba3a06cd66c627e2317b0fda60f6d76be5425a81
Stefan Schuermans initial version, DXFs can b...

Stefan Schuermans authored 11 years ago

1) /* drawing (DXF) to G-code (NGC) converter
2)  * Copyright 2013 Stefan Schuermans <stefan@schuermans.info>
3)  * Copyleft: CC-BY-SA http://creativecommons.org/licenses/by-sa/3.0/
4)  */
5) 
6) #include <fstream>
7) #include <iostream>
Stefan Schuermans configuration of precision

Stefan Schuermans authored 11 years ago

8) #include <math.h>
Stefan Schuermans initial version, DXFs can b...

Stefan Schuermans authored 11 years ago

9) #include <sstream>
10) #include <string>
11) 
12) #include "cmdparser.h"
13) #include "drawing.h"
14) #include "filename.h"
15) #include "gcode.h"
Stefan Schuermans implement converting paths...

Stefan Schuermans authored 11 years ago

16) #include "polygons.h"
Stefan Schuermans initial version, DXFs can b...

Stefan Schuermans authored 11 years ago

17) #include "settings.h"
18) 
Stefan Schuermans implement converting paths...

Stefan Schuermans authored 11 years ago

19) /**
20)  * @brief get layer by name from stream
21)  * @param[in] strm stream to read layer name from
22)  * @param[out] name layer name from stream
23)  * @param[out] layer layer indicated by name from stream
24)  * @return if layer could be found
25)  */
26) bool CmdParser::getLayer(std::istream &strm, std::string &name,
27)                          const Layer *&layer) const
28) {
29)   // get layer name argument
30)   strm >> name;
31)   if (strm.fail()) {
32)     std::cerr << "missing layer name" << std::endl;
33)     return false;
34)   }
35) 
36)   // get layer
37)   Drawing::Layers::const_iterator itLayer = mDrawing.mLayers.find(name);
38)   if (itLayer == mDrawing.mLayers.end()) {
39)     std::cerr << "layer \"" << name << "\" not found" << std::endl;
40)     return false;
41)   }
42)   layer = &itLayer->second;
43) 
44)   return true;
45) }
46) 
47) /**
48)  * @brief get layer by name from stream and convert to polygons
49)  * @param[in] strm stream to read layer name from
50)  * @param[out] name layer name from stream
51)  * @param[out] layer layer indicated by name from stream
52)  * @param[in,out] polys polygons created from layer
53)  * @return if layer could be found and converted to polygons
54)  */
55) bool CmdParser::getLayerPolys(std::istream &strm, std::string &name,
56)                               const Layer *&layer, Polygons &polys) const
57) {
58)   // get layer
59)   if (!getLayer(strm, name, layer))
60)     return false;
61) 
62)   // convert layer to polygons
63)   if (!polys.loadLayer(*layer, mSettings.precision)) {
64)     std::cerr << "cannot convert layer \"" << name << "\" to polygons"
65)               << std::endl;
66)     return false;
67)   }
68) 
69)   return true;
70) }
71) 
Stefan Schuermans initial version, DXFs can b...

Stefan Schuermans authored 11 years ago

72) /**
73)  * @brief process cmd command
74)  * @param[in] strm stream to read command arguments from
75)  * @return if processing command was successful
76)  */
77) bool CmdParser::procCmd_cmd(std::istream &strm)
78) {
79)   // skip whitespace and use rest of line as custom command
80)   strm >> std::ws;
81)   std::string cmd;
82)   getline(strm, cmd);
83) 
84)   // add custom command to G-code
85)   mGCode.appendCustom(cmd);
86) 
87)   return true;
88) }
89) 
90) /**
91)  * @brief process cut command
92)  * @param[in] strm stream to read command arguments from
93)  * @return if processing command was successful
94)  */
95) bool CmdParser::procCmd_cut(std::istream &strm)
96) {
Stefan Schuermans implement converting paths...

Stefan Schuermans authored 11 years ago

97)   // get layer from arguments
Stefan Schuermans initial version, DXFs can b...

Stefan Schuermans authored 11 years ago

98)   std::string layerName;
Stefan Schuermans implement converting paths...

Stefan Schuermans authored 11 years ago

99)   const Layer *layer;
100)   if (!getLayer(strm, layerName, layer))
Stefan Schuermans initial version, DXFs can b...

Stefan Schuermans authored 11 years ago

101)     return false;
102) 
Stefan Schuermans implement converting paths...

Stefan Schuermans authored 11 years ago

103)   // convert layer to G-code
104)   layer->toGCode(mSettings, mGCode);
105) 
106)   return true;
107) }
108) 
109) /**
110)  * @brief process cut_inside command
111)  * @param[in] strm stream to read command arguments from
112)  * @return if processing command was successful
113)  */
114) bool CmdParser::procCmd_cut_inside(std::istream &strm)
115) {
116)   // get layer from arguments and convert to polygons
117)   std::string layerName;
118)   const Layer *layer;
119)   Polygons polys;
120)   if (!getLayerPolys(strm, layerName, layer, polys))
Stefan Schuermans initial version, DXFs can b...

Stefan Schuermans authored 11 years ago

121)     return false;
122) 
Stefan Schuermans implement inside cutting (h...

Stefan Schuermans authored 11 years ago

123)   // innner offset polygons
124)   Polygons newPolys;
125)   polys.createInnerOffset(mSettings.tool_diameter * 0.5, newPolys);
126) 
127)   // convert polygons back to layer (containing paths)
Stefan Schuermans implement converting polygo...

Stefan Schuermans authored 11 years ago

128)   Layer newLayer;
Stefan Schuermans implement inside cutting (h...

Stefan Schuermans authored 11 years ago

129)   newPolys.writeToLayer(newLayer);
Stefan Schuermans implement converting polygo...

Stefan Schuermans authored 11 years ago

130) 
131)   // convert layer to G-code
132)   newLayer.toGCode(mSettings, mGCode);
Stefan Schuermans implement converting paths...

Stefan Schuermans authored 11 years ago

133) 
134)   return true;
135) }
136) 
137) /**
138)  * @brief process cut_outside command
139)  * @param[in] strm stream to read command arguments from
140)  * @return if processing command was successful
141)  */
142) bool CmdParser::procCmd_cut_outside(std::istream &strm)
143) {
144)   // get layer from arguments and convert to polygons
145)   std::string layerName;
146)   const Layer *layer;
147)   Polygons polys;
148)   if (!getLayerPolys(strm, layerName, layer, polys))
149)     return false;
150) 
151)   // TODO
152)   std::cerr << "TODO: cut_outside" << std::endl;
Stefan Schuermans implement converting polygo...

Stefan Schuermans authored 11 years ago

153)   Layer newLayer;
154)   polys.writeToLayer(newLayer);
155) 
156)   // convert layer to G-code
157)   newLayer.toGCode(mSettings, mGCode);
Stefan Schuermans implement converting paths...

Stefan Schuermans authored 11 years ago

158) 
159)   return true;
160) }
161) 
162) /**
163)  * @brief process cut_pocket command
164)  * @param[in] strm stream to read command arguments from
165)  * @return if processing command was successful
166)  */
167) bool CmdParser::procCmd_cut_pocket(std::istream &strm)
168) {
169)   // get layer from arguments and convert to polygons
170)   std::string layerName;
171)   const Layer *layer;
172)   Polygons polys;
173)   if (!getLayerPolys(strm, layerName, layer, polys))
174)     return false;
175) 
176)   // TODO
177)   std::cerr << "TODO: cut_pocket" << std::endl;
Stefan Schuermans implement converting polygo...

Stefan Schuermans authored 11 years ago

178)   Layer newLayer;
179)   polys.writeToLayer(newLayer);
180) 
181)   // convert layer to G-code
182)   newLayer.toGCode(mSettings, mGCode);
Stefan Schuermans initial version, DXFs can b...

Stefan Schuermans authored 11 years ago

183) 
184)   return true;
185) }
186) 
187) /**
188)  * @brief process read_dxf command
189)  * @param[in] strm stream to read command arguments from
190)  * @return if processing command was successful
191)  */
192) bool CmdParser::procCmd_read_dxf(std::istream &strm)
193) {
194)   // get arguments
195)   std::string fileName;
196)   strm >> fileName;
197)   if (strm.fail()) {
198)     std::cerr << "missing DXF file name" << std::endl;
199)     return false;
200)   }
201) 
202)   // re-base DXF file name
203)   fileName = filename_rebase(fileName, mBaseDir);
204) 
205)   // read DXF file
206)   if (!mDrawing.loadDxf(fileName)) {
207)     std::cerr << "could not read DXF file \"" << fileName << "\""
208)               << std::endl;
209)     return false;
210)   }
211) 
Stefan Schuermans implement joining and impro...

Stefan Schuermans authored 11 years ago

212)   // improve paths in layers
213)   mDrawing.improvePaths(mSettings.precision);
214) 
Stefan Schuermans initial version, DXFs can b...

Stefan Schuermans authored 11 years ago

215)   return true;
216) }
217) 
218) /**
219)  * @brief process set_base_z command
220)  * @param[in] strm stream to read command arguments from
221)  * @return if processing command was successful
222)  */
223) bool CmdParser::procCmd_set_base_z(std::istream &strm)
224) {
225)   // get arguments
226)   double z;
227)   strm >> z;
228)   if (strm.fail()) {
229)     std::cerr << "missing z coordinate" << std::endl;
230)     return false;
231)   }
232) 
233)   // update settings
234)   mSettings.base_z = z;
235)   return true;
236) }
237) 
238) /**
239)  * @brief process set_cut_z command
240)  * @param[in] strm stream to read command arguments from
241)  * @return if processing command was successful
242)  */
243) bool CmdParser::procCmd_set_cut_z(std::istream &strm)
244) {
245)   // get arguments
246)   double z;
247)   strm >> z;
248)   if (strm.fail()) {
249)     std::cerr << "missing z coordinate" << std::endl;
250)     return false;
251)   }
252) 
253)   // update settings
254)   mSettings.cut_z = z;
255)   return true;
256) }
257) 
258) /**
259)  * @brief process set_cut_z_step command
260)  * @param[in] strm stream to read command arguments from
261)  * @return if processing command was successful
262)  */
263) bool CmdParser::procCmd_set_cut_z_step(std::istream &strm)
264) {
265)   // get arguments and check them
266)   double z;
267)   strm >> z;
268)   if (strm.fail()) {
269)     std::cerr << "missing z value" << std::endl;
270)     return false;
271)   }
272)   if (z <= 0.0) {
273)     std::cerr << "invalid z cut step value (" << z << ")" << std::endl;
274)     return false;
275)   }
276) 
277)   // update settings
278)   mSettings.cut_z_step = z;
279)   return true;
280) }
281) 
282) /**
283)  * @brief process set_feed_drill command
284)  * @param[in] strm stream to read command arguments from
285)  * @return if processing command was successful
286)  */
287) bool CmdParser::procCmd_set_feed_drill(std::istream &strm)
288) {
289)   // get arguments and check them
290)   double feed;
291)   strm >> feed;
292)   if (strm.fail()) {
293)     std::cerr << "missing feed rate" << std::endl;
294)     return false;
295)   }
296)   if (feed <= 0.0) {
297)     std::cerr << "invalid feed rate (" << feed << ")" << std::endl;
298)     return false;
299)   }
300) 
301)   // update settings
302)   mSettings.feed_drill = feed;
303)   return true;
304) }
305) 
306) /**
307)  * @brief process set_feed_mill command
308)  * @param[in] strm stream to read command arguments from
309)  * @return if processing command was successful
310)  */
311) bool CmdParser::procCmd_set_feed_mill(std::istream &strm)
312) {
313)   // get arguments and check them
314)   double feed;
315)   strm >> feed;
316)   if (strm.fail()) {
317)     std::cerr << "missing feed rate" << std::endl;
318)     return false;
319)   }
320)   if (feed <= 0.0) {
321)     std::cerr << "invalid feed rate (" << feed << ")" << std::endl;
322)     return false;
323)   }
324) 
325)   // update settings
326)   mSettings.feed_mill = feed;
327)   return true;
328) }
329) 
330) /**
331)  * @brief process set_move_z command
332)  * @param[in] strm stream to read command arguments from
333)  * @return if processing command was successful
334)  */
335) bool CmdParser::procCmd_set_move_z(std::istream &strm)
336) {
337)   // get arguments
338)   double z;
339)   strm >> z;
340)   if (strm.fail()) {
341)     std::cerr << "missing z coordinate" << std::endl;
342)     return false;
343)   }
344) 
345)   // update settings
346)   mSettings.move_z = z;
347)   return true;
348) }
349) 
Stefan Schuermans configuration of precision

Stefan Schuermans authored 11 years ago

350) /**
351)  * @brief process set_precision command
352)  * @param[in] strm stream to read command arguments from
353)  * @return if processing command was successful
354)  */
355) bool CmdParser::procCmd_set_precision(std::istream &strm)
356) {
357)   // get arguments and check them
358)   double precision;
359)   strm >> precision;
360)   if (strm.fail()) {
361)     std::cerr << "missing precision" << std::endl;
362)     return false;
363)   }
364)   if (precision < 1.0e-8 || precision > 1.0) {
365)     std::cerr << "invalid precision (" << precision << ")" << std::endl;
366)     return false;
367)   }
368) 
369)   // update settings
370)   mSettings.precision = precision;
371)   return true;
372) }
373) 
Stefan Schuermans initial version, DXFs can b...

Stefan Schuermans authored 11 years ago

374) /**
375)  * @brief process set_tool_diameter command
376)  * @param[in] strm stream to read command arguments from
377)  * @return if processing command was successful
378)  */
379) bool CmdParser::procCmd_set_tool_diameter(std::istream &strm)
380) {
381)   // get arguments and check them
382)   double diameter;
383)   strm >> diameter;
384)   if (strm.fail()) {
385)     std::cerr << "missing tool diameter" << std::endl;
386)     return false;
387)   }
388)   if (diameter < 0.0) {
389)     std::cerr << "invalid tool diameter (" << diameter << ")" << std::endl;
390)     return false;
391)   }
392) 
393)   // update settings
394)   mSettings.tool_diameter = diameter;
395)   return true;
396) }
397) 
398) /**
399)  * @brief process write_ngc command
400)  * @param[in] strm stream to read command arguments from
401)  * @return if processing command was successful
402)  */
403) bool CmdParser::procCmd_write_ngc(std::istream &strm)
404) {
405)   // get arguments
406)   std::string fileName;
407)   strm >> fileName;
408)   if (strm.fail()) {
409)     std::cerr << "missing NGC file name" << std::endl;
410)     return false;
411)   }
412) 
413)   // re-base NGC file name
414)   fileName = filename_rebase(fileName, mBaseDir);
415) 
Stefan Schuermans configuration of precision

Stefan Schuermans authored 11 years ago

416)   // calculate number of digits after decimal point
417)   unsigned int digits = (unsigned int)ceil(-log10(mSettings.precision));
418) 
Stefan Schuermans initial version, DXFs can b...

Stefan Schuermans authored 11 years ago

419)   // write NGC file
Stefan Schuermans configuration of precision

Stefan Schuermans authored 11 years ago

420)   if (!mGCode.toFile(fileName, digits)) {
Stefan Schuermans initial version, DXFs can b...

Stefan Schuermans authored 11 years ago

421)     std::cerr << "could not write NGC file \"" << fileName << "\""
422)               << std::endl;
423)     return false;
424)   }
425) 
426)   return true;
427) }
428) 
429) /**
430)  * @brief process command from line of text
431)  * @param[in] strLine line containing command to process
432)  * @return if processing command was successful
433)  */
434) bool CmdParser::procLine(const std::string &strLine)
435) {
436)   std::stringstream strm(strLine);
437) 
438)   // read command
439)   std::string cmd;
440)   strm >> cmd;
441)   if (strm.fail())
442)     return true; // ignore empty lines
443) 
444)   // commands
445)   if (cmd == "cmd")
446)     return procCmd_cmd(strm);
447)   else if (cmd == "cut")
448)     return procCmd_cut(strm);
Stefan Schuermans implement converting paths...

Stefan Schuermans authored 11 years ago

449)   else if (cmd == "cut_inside")
450)     return procCmd_cut_inside(strm);
451)   else if (cmd == "cut_outside")
452)     return procCmd_cut_outside(strm);
453)   else if (cmd == "cut_pocket")
454)     return procCmd_cut_pocket(strm);
Stefan Schuermans initial version, DXFs can b...

Stefan Schuermans authored 11 years ago

455)   else if (cmd == "read_dxf")
456)     return procCmd_read_dxf(strm);
457)   else if (cmd == "set_base_z")
458)     return procCmd_set_base_z(strm);
459)   else if (cmd == "set_cut_z")
460)     return procCmd_set_cut_z(strm);
461)   else if (cmd == "set_cut_z_step")
462)     return procCmd_set_cut_z_step(strm);
463)   else if (cmd == "set_feed_drill")
464)     return procCmd_set_feed_drill(strm);
465)   else if (cmd == "set_feed_mill")
466)     return procCmd_set_feed_mill(strm);
467)   else if (cmd == "set_move_z")
468)     return procCmd_set_move_z(strm);
Stefan Schuermans configuration of precision

Stefan Schuermans authored 11 years ago

469)   else if (cmd == "set_precision")
470)     return procCmd_set_precision(strm);