aedc34a40832e7bebe9ff13213d880d7acb17c63
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 outer polygon off...

Stefan Schuermans authored 11 years ago

123)   // inner offset polygons
Stefan Schuermans implement inside cutting (h...

Stefan Schuermans authored 11 years ago

124)   Polygons newPolys;
Stefan Schuermans implement outer polygon off...

Stefan Schuermans authored 11 years ago

125)   if (!polys.createInnerOffset(mSettings.tool_diameter * 0.5, newPolys)) {
126)     std::cerr << "creating inner offset polygons failed" << std::endl;
127)     return false;
128)   }
Stefan Schuermans implement inside cutting (h...

Stefan Schuermans authored 11 years ago

129) 
130)   // convert polygons back to layer (containing paths)
Stefan Schuermans implement converting polygo...

Stefan Schuermans authored 11 years ago

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

Stefan Schuermans authored 11 years ago

132)   newPolys.writeToLayer(newLayer);
Stefan Schuermans improve paths of layers aft...

Stefan Schuermans authored 11 years ago

133)   newLayer.improvePaths(mSettings.precision);
Stefan Schuermans implement converting polygo...

Stefan Schuermans authored 11 years ago

134) 
135)   // convert layer to G-code
136)   newLayer.toGCode(mSettings, mGCode);
Stefan Schuermans implement converting paths...

Stefan Schuermans authored 11 years ago

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

Stefan Schuermans authored 11 years ago

155)   // outer offset polygons
156)   Polygons newPolys;
157)   if (!polys.createOuterOffset(mSettings.tool_diameter * 0.5, newPolys)) {
158)     std::cerr << "creating outer offset polygons failed" << std::endl;
159)     return false;
160)   }
161) 
162)   // convert polygons back to layer (containing paths)
Stefan Schuermans implement converting polygo...

Stefan Schuermans authored 11 years ago

163)   Layer newLayer;
Stefan Schuermans implement outer polygon off...

Stefan Schuermans authored 11 years ago

164)   newPolys.writeToLayer(newLayer);
Stefan Schuermans improve paths of layers aft...

Stefan Schuermans authored 11 years ago

165)   newLayer.improvePaths(mSettings.precision);
Stefan Schuermans implement converting polygo...

Stefan Schuermans authored 11 years ago

166) 
167)   // convert layer to G-code
168)   newLayer.toGCode(mSettings, mGCode);
Stefan Schuermans implement converting paths...

Stefan Schuermans authored 11 years ago

169) 
170)   return true;
171) }
172) 
173) /**
174)  * @brief process cut_pocket command
175)  * @param[in] strm stream to read command arguments from
176)  * @return if processing command was successful
177)  */
178) bool CmdParser::procCmd_cut_pocket(std::istream &strm)
179) {
180)   // get layer from arguments and convert to polygons
181)   std::string layerName;
182)   const Layer *layer;
183)   Polygons polys;
184)   if (!getLayerPolys(strm, layerName, layer, polys))
185)     return false;
186) 
Stefan Schuermans implement filling polygon w...

Stefan Schuermans authored 11 years ago

187)   // fill insides of polygons by creating inner offset polygons
188)   Polygons newPolys;
189)   if (!polys.fillInnerOffset(mSettings.tool_diameter * 0.5, newPolys)) {
190)     std::cerr << "filling insides of polygons failed" << std::endl;
191)     return false;
192)   }
193) 
194)   // convert polygons back to layer (containing paths)
Stefan Schuermans implement converting polygo...

Stefan Schuermans authored 11 years ago

195)   Layer newLayer;
Stefan Schuermans implement filling polygon w...

Stefan Schuermans authored 11 years ago

196)   newPolys.writeToLayer(newLayer);
Stefan Schuermans improve paths of layers aft...

Stefan Schuermans authored 11 years ago

197)   newLayer.improvePaths(mSettings.precision);
Stefan Schuermans implement converting polygo...

Stefan Schuermans authored 11 years ago

198) 
199)   // convert layer to G-code
200)   newLayer.toGCode(mSettings, mGCode);
Stefan Schuermans initial version, DXFs can b...

Stefan Schuermans authored 11 years ago

201) 
202)   return true;
203) }
204) 
205) /**
206)  * @brief process read_dxf command
207)  * @param[in] strm stream to read command arguments from
208)  * @return if processing command was successful
209)  */
210) bool CmdParser::procCmd_read_dxf(std::istream &strm)
211) {
212)   // get arguments
213)   std::string fileName;
214)   strm >> fileName;
215)   if (strm.fail()) {
216)     std::cerr << "missing DXF file name" << std::endl;
217)     return false;
218)   }
219) 
220)   // re-base DXF file name
221)   fileName = filename_rebase(fileName, mBaseDir);
222) 
223)   // read DXF file
Stefan Schuermans implement finer approximati...

Stefan Schuermans authored 11 years ago

224)   if (!mDrawing.loadDxf(fileName, mSettings.precision)) {
Stefan Schuermans initial version, DXFs can b...

Stefan Schuermans authored 11 years ago

225)     std::cerr << "could not read DXF file \"" << fileName << "\""
226)               << std::endl;
227)     return false;
228)   }
229) 
Stefan Schuermans implement joining and impro...

Stefan Schuermans authored 11 years ago

230)   // improve paths in layers
231)   mDrawing.improvePaths(mSettings.precision);
232) 
Stefan Schuermans initial version, DXFs can b...

Stefan Schuermans authored 11 years ago

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

Stefan Schuermans authored 11 years ago

368) /**
369)  * @brief process set_offset_x command
370)  * @param[in] strm stream to read command arguments from
371)  * @return if processing command was successful
372)  */
373) bool CmdParser::procCmd_set_offset_x(std::istream &strm)
374) {
375)   // get arguments
376)   double x;
377)   strm >> x;
378)   if (strm.fail()) {
379)     std::cerr << "missing x coordinate" << std::endl;
380)     return false;
381)   }
382) 
383)   // update settings
384)   mSettings.offset_x = x;
385)   return true;
386) }
387) 
388) /**
389)  * @brief process set_offset_y command
390)  * @param[in] strm stream to read command arguments from
391)  * @return if processing command was successful
392)  */
393) bool CmdParser::procCmd_set_offset_y(std::istream &strm)
394) {
395)   // get arguments
396)   double y;
397)   strm >> y;
398)   if (strm.fail()) {
399)     std::cerr << "missing y coordinate" << std::endl;
400)     return false;
401)   }
402) 
403)   // update settings
404)   mSettings.offset_y = y;
405)   return true;
406) }
407) 
Stefan Schuermans configuration of precision

Stefan Schuermans authored 11 years ago

408) /**
409)  * @brief process set_precision command
410)  * @param[in] strm stream to read command arguments from
411)  * @return if processing command was successful
412)  */
413) bool CmdParser::procCmd_set_precision(std::istream &strm)
414) {
415)   // get arguments and check them
416)   double precision;
417)   strm >> precision;
418)   if (strm.fail()) {
419)     std::cerr << "missing precision" << std::endl;
420)     return false;
421)   }
422)   if (precision < 1.0e-8 || precision > 1.0) {
423)     std::cerr << "invalid precision (" << precision << ")" << std::endl;
424)     return false;
425)   }
426) 
427)   // update settings
428)   mSettings.precision = precision;
429)   return true;
430) }
431) 
Stefan Schuermans initial version, DXFs can b...

Stefan Schuermans authored 11 years ago

432) /**
433)  * @brief process set_tool_diameter command
434)  * @param[in] strm stream to read command arguments from
435)  * @return if processing command was successful
436)  */
437) bool CmdParser::procCmd_set_tool_diameter(std::istream &strm)
438) {
439)   // get arguments and check them
440)   double diameter;
441)   strm >> diameter;
442)   if (strm.fail()) {
443)     std::cerr << "missing tool diameter" << std::endl;
444)     return false;
445)   }
446)   if (diameter < 0.0) {
447)     std::cerr << "invalid tool diameter (" << diameter << ")" << std::endl;
448)     return false;
449)   }
450) 
451)   // update settings
452)   mSettings.tool_diameter = diameter;
453)   return true;
454) }
455) 
456) /**
457)  * @brief process write_ngc command
458)  * @param[in] strm stream to read command arguments from
459)  * @return if processing command was successful
460)  */
461) bool CmdParser::procCmd_write_ngc(std::istream &strm)
462) {
463)   // get arguments
464)   std::string fileName;
465)   strm >> fileName;
466)   if (strm.fail()) {
467)     std::cerr << "missing NGC file name" << std::endl;
468)     return false;
469)   }
470) 
471)   // re-base NGC file name
472)   fileName = filename_rebase(fileName, mBaseDir);
473) 
Stefan Schuermans configuration of precision

Stefan Schuermans authored 11 years ago

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

Stefan Schuermans authored 11 years ago

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

Stefan Schuermans authored 11 years ago

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

Stefan Schuermans authored 11 years ago

479)     std::cerr << "could not write NGC file \"" << fileName << "\""
480)               << std::endl;
481)     return false;
482)   }
483) 
484)   return true;
485) }
486) 
487) /**
488)  * @brief process command from line of text
489)  * @param[in] strLine line containing command to process
490)  * @return if processing command was successful
491)  */
492) bool CmdParser::procLine(const std::string &strLine)
493) {
494)   std::stringstream strm(strLine);
495) 
496)   // read command
497)   std::string cmd;
498)   strm >> cmd;
499)   if (strm.fail())
500)     return true; // ignore empty lines
501) 
502)   // commands
503)   if (cmd == "cmd")
504)     return procCmd_cmd(strm);
505)   else if (cmd == "cut")
506)     return procCmd_cut(strm);
Stefan Schuermans implement converting paths...

Stefan Schuermans authored 11 years ago

507)   else if (cmd == "cut_inside")
508)     return procCmd_cut_inside(strm);
509)   else if (cmd == "cut_outside")
510)     return procCmd_cut_outside(strm);
511)   else if (cmd == "cut_pocket")
512)     return procCmd_cut_pocket(strm);
Stefan Schuermans initial version, DXFs can b...

Stefan Schuermans authored 11 years ago

513)   else if (cmd == "read_dxf")
514)     return procCmd_read_dxf(strm);
515)   else if (cmd == "set_base_z")
516)     return procCmd_set_base_z(strm);
517)   else if (cmd == "set_cut_z")
518)     return procCmd_set_cut_z(strm);
519)   else if (cmd == "set_cut_z_step")
520)     return procCmd_set_cut_z_step(strm);
521)   else if (cmd == "set_feed_drill")
522)     return procCmd_set_feed_drill(strm);
523)   else if (cmd == "set_feed_mill")
524)     return procCmd_set_feed_mill(strm);
525)   else if (cmd == "set_move_z")
526)     return procCmd_set_move_z(strm);
Stefan Schuermans add support for offset in x...

Stefan Schuermans authored 11 years ago

527)   else if (cmd == "set_offset_x")
528)     return procCmd_set_offset_x(strm);
529)   else if (cmd == "set_offset_y")
530)     return procCmd_set_offset_y(strm);
Stefan Schuermans configuration of precision

Stefan Schuermans authored 11 years ago

531)   else if (cmd == "set_precision")
532)     return procCmd_set_precision(strm);