134 lines
5.7 KiB
Python
Executable File
134 lines
5.7 KiB
Python
Executable File
#!/usr/bin/python
|
|
|
|
from __future__ import absolute_import
|
|
from __future__ import print_function
|
|
import sys
|
|
import os
|
|
import argparse
|
|
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'])
|
|
gcode_file_path = " "
|
|
|
|
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 parse_arguments():
|
|
parser = argparse.ArgumentParser(description='Generate gcode from vector graphics.')
|
|
|
|
parser.add_argument("-i", "--input", dest='inputfile', metavar='image.svg', help="path to vector graphic file", required=True)
|
|
parser.add_argument("-o", "--output", dest='outputfile', metavar='data.gcode', help="path to file for generated gcode", required=True)
|
|
|
|
parser.add_argument("-fr", "--feedrate", dest='feedrate', metavar=300, default=300, help="rate while laser is on", required=False)
|
|
parser.add_argument("-mr", "--moverate", dest='moverate', metavar=1200, default=1200, help="rate while laser is off", required=False)
|
|
|
|
parser.add_argument("-p", "--passes", dest='passes', metavar=1, default=1, help="number of passes (for deeper cutting)", required=False)
|
|
parser.add_argument("-lp", "--laserpower", dest='laserpower', metavar="0%", default="0%", help="laser power in %%", required=False)
|
|
|
|
parser.add_argument("-bx", "--bedsizex", dest='bedsizex', default="376", help="x size of bed in mm", required=False)
|
|
parser.add_argument("-by", "--bedsizey", dest='bedsizey', default="315", help="y size of bed in mm", required=False)
|
|
|
|
parser.add_argument("-s", "--smoothness", dest='smoothness', metavar=0.2, default=0.2, help="Used to control the smoothness/sharpness of the curves.\nSmaller the value greater the sharpness.\nMake sure the value is greater than 0.1", required=False)
|
|
|
|
args = parser.parse_args()
|
|
return [args.inputfile, args.outputfile, int(args.feedrate), int(args.moverate), int(args.passes), ((float(args.laserpower.split("%")[0])/100.0)), int(args.bedsizex), int(args.bedsizey), float(args.smoothness) ]
|
|
|
|
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, 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()
|
|
|
|
if obj_path:
|
|
gcode_write(gcode_file, "; == Start of " + tag_suffix + " ==\n")
|
|
points = point_generator(obj_path, obj_trans_matrix, smoothness)
|
|
num_points = 0
|
|
for x,y in points:
|
|
if (debug): print("[Point] X: " + str(x) + " Y: " + str(y))
|
|
if x > 0 and x < bed_max_x and y > 0 and y < bed_max_y:
|
|
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, "M3 I S15 ;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, postamble)
|
|
print("\nGenerated", generated_points_count, "points")
|
|
|
|
if __name__ == "__main__":
|
|
sys.setrecursionlimit(20000) #needed for svg's with more indepented paths
|
|
|
|
svg_file_path, gcode_file_path, feedrate, moverate, passes, laserpower, bedsizex, bedsizey, smoothness = parse_arguments()
|
|
|
|
print("inputfile: " + str(svg_file_path))
|
|
print("outputfile: " + str(gcode_file_path))
|
|
print("feedrate: " + str(feedrate))
|
|
print("moverate: " + str(moverate))
|
|
print("passes: " + str(passes))
|
|
print("laserpower: " + str(laserpower))
|
|
print("bedsizex: " + str(bedsizex))
|
|
print("bedsizey: " + str(bedsizey))
|
|
print("smoothness: " + str(smoothness))
|
|
|
|
try:
|
|
with open(gcode_file_path, 'w') as gcode_file:
|
|
generate_gcode(read_input_file(svg_file_path),gcode_file)
|
|
except Exception as e:
|
|
print("unable to create gcode file: \n" + str(e))
|
|
close_on_failure()
|
|
|
|
|
|
|