48bbb1bc1df6edbcb2fd3091cf59ef94cf8deb91
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;
125)   return false;
126) 
127)   return true;
128) }
129) 
130) /**
131)  * @brief process cut_outside command
132)  * @param[in] strm stream to read command arguments from
133)  * @return if processing command was successful
134)  */
135) bool CmdParser::procCmd_cut_outside(std::istream &strm)
136) {
137)   // get layer from arguments and convert to polygons
138)   std::string layerName;
139)   const Layer *layer;
140)   Polygons polys;
141)   if (!getLayerPolys(strm, layerName, layer, polys))
142)     return false;
143) 
144)   // TODO
145)   std::cerr << "TODO: cut_outside" << std::endl;
146)   return false;
147) 
148)   return true;
149) }
150) 
151) /**
152)  * @brief process cut_pocket command
153)  * @param[in] strm stream to read command arguments from
154)  * @return if processing command was successful
155)  */
156) bool CmdParser::procCmd_cut_pocket(std::istream &strm)
157) {
158)   // get layer from arguments and convert to polygons
159)   std::string layerName;
160)   const Layer *layer;
161)   Polygons polys;
162)   if (!getLayerPolys(strm, layerName, layer, polys))
163)     return false;
164) 
165)   // TODO
166)   std::cerr << "TODO: cut_pocket" << std::endl;
167)   return false;
Stefan Schuermans initial version, DXFs can b...

Stefan Schuermans authored 11 years ago

168) 
169)   return true;
170) }
171) 
172) /**
173)  * @brief process read_dxf command
174)  * @param[in] strm stream to read command arguments from
175)  * @return if processing command was successful
176)  */
177) bool CmdParser::procCmd_read_dxf(std::istream &strm)
178) {
179)   // get arguments
180)   std::string fileName;
181)   strm >> fileName;
182)   if (strm.fail()) {
183)     std::cerr << "missing DXF file name" << std::endl;
184)     return false;
185)   }
186) 
187)   // re-base DXF file name
188)   fileName = filename_rebase(fileName, mBaseDir);
189) 
190)   // read DXF file
191)   if (!mDrawing.loadDxf(fileName)) {
192)     std::cerr << "could not read DXF file \"" << fileName << "\""
193)               << std::endl;
194)     return false;
195)   }
196) 
Stefan Schuermans implement joining and impro...

Stefan Schuermans authored 11 years ago

197)   // improve paths in layers
198)   mDrawing.improvePaths(mSettings.precision);
199) 
Stefan Schuermans initial version, DXFs can b...

Stefan Schuermans authored 11 years ago

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

Stefan Schuermans authored 11 years ago

335) /**
336)  * @brief process set_precision command
337)  * @param[in] strm stream to read command arguments from
338)  * @return if processing command was successful
339)  */
340) bool CmdParser::procCmd_set_precision(std::istream &strm)
341) {
342)   // get arguments and check them
343)   double precision;
344)   strm >> precision;
345)   if (strm.fail()) {
346)     std::cerr << "missing precision" << std::endl;
347)     return false;
348)   }
349)   if (precision < 1.0e-8 || precision > 1.0) {
350)     std::cerr << "invalid precision (" << precision << ")" << std::endl;
351)     return false;
352)   }
353) 
354)   // update settings
355)   mSettings.precision = precision;
356)   return true;
357) }
358) 
Stefan Schuermans initial version, DXFs can b...

Stefan Schuermans authored 11 years ago

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

Stefan Schuermans authored 11 years ago

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

Stefan Schuermans authored 11 years ago

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

Stefan Schuermans authored 11 years ago

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

Stefan Schuermans authored 11 years ago

406)     std::cerr << "could not write NGC file \"" << fileName << "\""
407)               << std::endl;
408)     return false;
409)   }
410) 
411)   return true;
412) }
413) 
414) /**
415)  * @brief process command from line of text
416)  * @param[in] strLine line containing command to process
417)  * @return if processing command was successful
418)  */
419) bool CmdParser::procLine(const std::string &strLine)
420) {
421)   std::stringstream strm(strLine);
422) 
423)   // read command
424)   std::string cmd;
425)   strm >> cmd;
426)   if (strm.fail())
427)     return true; // ignore empty lines
428) 
429)   // commands
430)   if (cmd == "cmd")
431)     return procCmd_cmd(strm);
432)   else if (cmd == "cut")
433)     return procCmd_cut(strm);
Stefan Schuermans implement converting paths...

Stefan Schuermans authored 11 years ago

434)   else if (cmd == "cut_inside")
435)     return procCmd_cut_inside(strm);
436)   else if (cmd == "cut_outside")
437)     return procCmd_cut_outside(strm);
438)   else if (cmd == "cut_pocket")
439)     return procCmd_cut_pocket(strm);
Stefan Schuermans initial version, DXFs can b...

Stefan Schuermans authored 11 years ago

440)   else if (cmd == "read_dxf")
441)     return procCmd_read_dxf(strm);
442)   else if (cmd == "set_base_z")
443)     return procCmd_set_base_z(strm);
444)   else if (cmd == "set_cut_z")
445)     return procCmd_set_cut_z(strm);
446)   else if (cmd == "set_cut_z_step")
447)     return procCmd_set_cut_z_step(strm);
448)   else if (cmd == "set_feed_drill")
449)     return procCmd_set_feed_drill(strm);
450)   else if (cmd == "set_feed_mill")
451)     return procCmd_set_feed_mill(strm);
452)   else if (cmd == "set_move_z")
453)     return procCmd_set_move_z(strm);
Stefan Schuermans configuration of precision

Stefan Schuermans authored 11 years ago

454)   else if (cmd == "set_precision")
455)     return procCmd_set_precision(strm);