#!/usr/bin/python from __future__ import absolute_import from __future__ import print_function import sys import os import xml.etree.ElementTree as ET import shapes as shapes_pkg from shapes import point_generator from config import * debug = True example_usage = "-i test_data/Test_H.svg -o test_data/test.gcode -fr 300 -mr 1200 -p 1 -lp 20%" svg_shapes = set(['rect', 'circle', 'ellipse', 'line', 'polyline', 'polygon', 'path']) global conf def gcode_write(gcode_file, gcode): if (debug): for cmd in gcode.split("\n"): if len(cmd): print("[GCODE] " + str(cmd)) gcode_file.write(gcode) def close_on_failure(): os.remove(gcode_file_path) sys.exit(1) def laserpower_to_pwm(percent): if (percent <= 1): return int(percent*255) else: return 0 def read_input_file(svg_file_path): try: tree = ET.parse(svg_file_path) return tree.getroot() except Exception as e: print("unable to read svg file: \n" + str(e)) sys.exit(1) def generate_gcode(svg_file_root_tree, gcode_file): generated_points_count = 0 width = svg_file_root_tree.get('width') height = svg_file_root_tree.get('height') if width == None or height == None: viewbox = svg_file_root_tree.get('viewBox') if viewbox: if (debug): print("Using viewbox size") _, _, width, height = viewbox.split() if width == None or height == None: print("Unable to get width and height for the svg") close_on_failure() width = float(width.split("mm")[0]) height = float(height.split("mm")[0]) print("[SVG loaded] With:" + str(width) + "mm Height:" + str(height) + "mm") #generate start cmds's gcode_write(gcode_file, conf.preamble) for elem in svg_file_root_tree.iter(): try: _, tag_suffix = elem.tag.split('}') except ValueError: continue if tag_suffix in svg_shapes: shape_class = getattr(shapes_pkg, tag_suffix) shape_obj = shape_class(elem) obj_path = shape_obj.d_path() obj_trans_matrix = shape_obj.transformation_matrix() gcode_write(gcode_file, "G0 F" + str(conf.moverate) + " set the moverate to " + str(conf.moverate) + "mm/min;\n") if obj_path: gcode_write(gcode_file, "; == Start of " + tag_suffix + " ==\n") points = point_generator(obj_path, obj_trans_matrix, conf.smoothness) num_points = 0 for x,y in points: if (debug): print("[Point] X: " + str(x) + " Y: " + str(y)) if x > 0 and x < conf.bedsizex and y > 0 and y < conf.bedsizey: gcode_write(gcode_file, "G1 X%0.001f Y%0.001f\n" % (x, y)) num_points += 1 if (num_points == 1): gcode_write(gcode_file, "G0 F" + str(conf.feedrate) + " set the feedrate to " + str(conf.feedrate) + "mm/min;\n") gcode_write(gcode_file, "M3 I S" + str(laserpower_to_pwm(conf.laserpower)) + " ;start laser\n") elif (debug): print("\n; Coordinates out of range:", "G1 X%0.01f Y%0.01f" % (x, y)) print("; Raw:", str(x), str(y), "\nScaled:", str(x), str(y), "\n") close_on_failure() gcode_write(gcode_file, "M5 ;stop laser\n") gcode_write(gcode_file, "; == End of " + tag_suffix + " ==\n") generated_points_count += num_points gcode_write(gcode_file, "G0 F" + str(conf.moverate) + " set the moverate to " + str(conf.moverate) + "mm/min;\n") gcode_write(gcode_file, conf.postamble) print("\nGenerated", generated_points_count, "points") if __name__ == "__main__": sys.setrecursionlimit(20000) #needed for svg's with more indepented paths conf = Config() conf.parse_arguments() try: with open(conf.gcode_file_path, 'w') as gcode_file: generate_gcode(read_input_file(conf.svg_file_path),gcode_file) except Exception as e: print("unable to create gcode file: \n" + str(e)) close_on_failure()