3c3d9187e96a9356f551472a826748d5432c6c79
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 configuration of precision

Stefan Schuermans authored 11 years ago

368) /**
369)  * @brief process set_precision command
370)  * @param[in] strm stream to read command arguments from
371)  * @return if processing command was successful
372)  */
373) bool CmdParser::procCmd_set_precision(std::istream &strm)
374) {
375)   // get arguments and check them
376)   double precision;
377)   strm >> precision;
378)   if (strm.fail()) {
379)     std::cerr << "missing precision" << std::endl;
380)     return false;
381)   }
382)   if (precision < 1.0e-8 || precision > 1.0) {
383)     std::cerr << "invalid precision (" << precision << ")" << std::endl;
384)     return false;
385)   }
386) 
387)   // update settings
388)   mSettings.precision = precision;
389)   return true;
390) }
391) 
Stefan Schuermans initial version, DXFs can b...

Stefan Schuermans authored 11 years ago

392) /**
393)  * @brief process set_tool_diameter command
394)  * @param[in] strm stream to read command arguments from
395)  * @return if processing command was successful
396)  */
397) bool CmdParser::procCmd_set_tool_diameter(std::istream &strm)
398) {
399)   // get arguments and check them
400)   double diameter;
401)   strm >> diameter;
402)   if (strm.fail()) {
403)     std::cerr << "missing tool diameter" << std::endl;
404)     return false;
405)   }
406)   if (diameter < 0.0) {
407)     std::cerr << "invalid tool diameter (" << diameter << ")" << std::endl;
408)     return false;
409)   }
410) 
411)   // update settings
412)   mSettings.tool_diameter = diameter;
413)   return true;
414) }
415) 
416) /**
417)  * @brief process write_ngc command
418)  * @param[in] strm stream to read command arguments from
419)  * @return if processing command was successful
420)  */
421) bool CmdParser::procCmd_write_ngc(std::istream &strm)
422) {
423)   // get arguments
424)   std::string fileName;
425)   strm >> fileName;
426)   if (strm.fail()) {
427)     std::cerr << "missing NGC file name" << std::endl;
428)     return false;
429)   }
430) 
431)   // re-base NGC file name
432)   fileName = filename_rebase(fileName, mBaseDir);
433) 
Stefan Schuermans configuration of precision

Stefan Schuermans authored 11 years ago

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

Stefan Schuermans authored 11 years ago

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

Stefan Schuermans authored 11 years ago

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

Stefan Schuermans authored 11 years ago

439)     std::cerr << "could not write NGC file \"" << fileName << "\""
440)               << std::endl;
441)     return false;
442)   }
443) 
444)   return true;
445) }
446) 
447) /**
448)  * @brief process command from line of text
449)  * @param[in] strLine line containing command to process
450)  * @return if processing command was successful
451)  */
452) bool CmdParser::procLine(const std::string &strLine)
453) {
454)   std::stringstream strm(strLine);
455) 
456)   // read command
457)   std::string cmd;
458)   strm >> cmd;
459)   if (strm.fail())
460)     return true; // ignore empty lines
461) 
462)   // commands
463)   if (cmd == "cmd")
464)     return procCmd_cmd(strm);
465)   else if (cmd == "cut")
466)     return procCmd_cut(strm);
Stefan Schuermans implement converting paths...

Stefan Schuermans authored 11 years ago

467)   else if (cmd == "cut_inside")
468)     return procCmd_cut_inside(strm);
469)   else if (cmd == "cut_outside")
470)     return procCmd_cut_outside(strm);
471)   else if (cmd == "cut_pocket")
472)     return procCmd_cut_pocket(strm);
Stefan Schuermans initial version, DXFs can b...

Stefan Schuermans authored 11 years ago

473)   else if (cmd == "read_dxf")
474)     return procCmd_read_dxf(strm);
475)   else if (cmd == "set_base_z")
476)     return procCmd_set_base_z(strm);
477)   else if (cmd == "set_cut_z")
478)     return procCmd_set_cut_z(strm);
479)   else if (cmd == "set_cut_z_step")
480)     return procCmd_set_cut_z_step(strm);
481)   else if (cmd == "set_feed_drill")
482)     return procCmd_set_feed_drill(strm);
483)   else if (cmd == "set_feed_mill")
484)     return procCmd_set_feed_mill(strm);
485)   else if (cmd == "set_move_z")
486)     return procCmd_set_move_z(strm);
Stefan Schuermans configuration of precision

Stefan Schuermans authored 11 years ago

487)   else if (cmd == "set_precision")
488)     return procCmd_set_precision(strm);