986c763dc78b1df4d5e9fa723372b1c0469eb2b5
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 converting paths...

Stefan Schuermans authored 11 years ago

123)   // TODO
124)   std::cerr << "TODO: cut_inside" << std::endl;
Stefan Schuermans implement converting polygo...

Stefan Schuermans authored 11 years ago

125)   Layer newLayer;
126)   polys.writeToLayer(newLayer);
127) 
128)   // convert layer to G-code
129)   newLayer.toGCode(mSettings, mGCode);
Stefan Schuermans implement converting paths...

Stefan Schuermans authored 11 years ago

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

Stefan Schuermans authored 11 years ago

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

Stefan Schuermans authored 11 years ago

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

Stefan Schuermans authored 11 years ago

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

Stefan Schuermans authored 11 years ago

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

Stefan Schuermans authored 11 years ago

209)   // improve paths in layers
210)   mDrawing.improvePaths(mSettings.precision);
211) 
Stefan Schuermans initial version, DXFs can b...

Stefan Schuermans authored 11 years ago

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

Stefan Schuermans authored 11 years ago

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

Stefan Schuermans authored 11 years ago

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

Stefan Schuermans authored 11 years ago

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

Stefan Schuermans authored 11 years ago

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

Stefan Schuermans authored 11 years ago

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

Stefan Schuermans authored 11 years ago

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

Stefan Schuermans authored 11 years ago

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

Stefan Schuermans authored 11 years ago

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

Stefan Schuermans authored 11 years ago

466)   else if (cmd == "set_precision")
467)     return procCmd_set_precision(strm);