tidied up / removed sqrt
This commit is contained in:
1 parent
90ef63fd7b
commit
13ee50db4c
6 files changed
+97
-245
No files matched your search
@@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
from svg2gcode import generate_gcode
|
from svg2gcode import main
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
# from config import *
|
# from config import *
|
||||||
@@ -24,9 +24,6 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
print(source, target)
|
print(source, target)
|
||||||
|
|
||||||
with open(target, 'w+') as output_file:
|
main(source, target)
|
||||||
g = generate_gcode(source)
|
|
||||||
for i in g:
|
|
||||||
output_file.write(i + "\n")
|
|
||||||
|
|
||||||
print("done!")
|
print("done!")
|
||||||
@@ -27,8 +27,6 @@ value is greater than 0.1
|
|||||||
"""
|
"""
|
||||||
smoothness = 0.02
|
smoothness = 0.02
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
""" height that the z axis will use to travel between strokes """
|
""" height that the z axis will use to travel between strokes """
|
||||||
zTravel = 4
|
zTravel = 4
|
||||||
|
|
||||||
@@ -43,4 +41,7 @@ precision = 2
|
|||||||
|
|
||||||
|
|
||||||
""" scale gcode to fit bed size"""
|
""" scale gcode to fit bed size"""
|
||||||
auto_scale = False
|
auto_scale = False
|
||||||
|
|
||||||
|
""" optimize path - slow for large files"""
|
||||||
|
optimise = True
|
||||||
+2
-11
@@ -1,16 +1,12 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
from svg2gcode import generate_gcode
|
from svg2gcode import main
|
||||||
import sys
|
import sys
|
||||||
# from config import *
|
# from config import *
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
||||||
|
|
||||||
if len(sys.argv) < 3:
|
if len(sys.argv) < 3:
|
||||||
print("usage: python convert.py source.svg destination.gcode")
|
print("usage: python convert.py source.svg destination.gcode")
|
||||||
sys.exit()
|
sys.exit()
|
||||||
@@ -18,15 +14,10 @@ if __name__ == "__main__":
|
|||||||
source = sys.argv[1]
|
source = sys.argv[1]
|
||||||
target = sys.argv[2]
|
target = sys.argv[2]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
print("converting!")
|
print("converting!")
|
||||||
|
|
||||||
print(source, target)
|
print(source, target)
|
||||||
|
|
||||||
with open(target, 'w+') as output_file:
|
main(source, target)
|
||||||
g = generate_gcode(source)
|
|
||||||
for i in g:
|
|
||||||
output_file.write(i + "\n")
|
|
||||||
|
|
||||||
print("done!")
|
print("done!")
|
||||||
+11
-137
@@ -1,103 +1,6 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import xml.etree.ElementTree as ET
|
|
||||||
import shapes as shapes_pkg
|
|
||||||
from shapes import point_generator
|
|
||||||
from config import *
|
|
||||||
import re
|
|
||||||
from math import sqrt
|
from math import sqrt
|
||||||
from datetime import datetime as dt
|
from datetime import datetime as dt
|
||||||
|
from utils import *
|
||||||
debug = False
|
|
||||||
|
|
||||||
def get_shapes(path, autoScale=True):
|
|
||||||
print("\n get shapes")
|
|
||||||
t1 = dt.now()
|
|
||||||
svg_shapes = set(['rect', 'circle', 'ellipse', 'line', 'polyline', 'polygon', 'path'])
|
|
||||||
shapes = []
|
|
||||||
tree = ET.parse(path)
|
|
||||||
root = tree.getroot()
|
|
||||||
width = root.get('width')
|
|
||||||
height = root.get('height')
|
|
||||||
|
|
||||||
if width is None or height is None:
|
|
||||||
viewbox = root.get('viewBox')
|
|
||||||
if viewbox:
|
|
||||||
_, _, width, height = viewbox.split()
|
|
||||||
|
|
||||||
if width is None or height is None:
|
|
||||||
print("Unable to get width and height for the svg")
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
width = float(re.sub("[^0-9]", "", width))
|
|
||||||
height = float(re.sub("[^0-9]", "", height))
|
|
||||||
|
|
||||||
for elem in root.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)
|
|
||||||
d = shape_obj.d_path()
|
|
||||||
m = shape_obj.transformation_matrix() # todo work out what d and m are
|
|
||||||
|
|
||||||
coords = []
|
|
||||||
|
|
||||||
if d: # begin shape processing
|
|
||||||
|
|
||||||
p = point_generator(d, m, smoothness) # tuples of x y coords
|
|
||||||
first = True
|
|
||||||
|
|
||||||
for x, y in p: # todo sort out this nightmare
|
|
||||||
|
|
||||||
if first:
|
|
||||||
coords.append((x, -y + height))
|
|
||||||
|
|
||||||
else:
|
|
||||||
|
|
||||||
if not (x, y) == coords[-1]:
|
|
||||||
coords.append((x, -y + height))
|
|
||||||
|
|
||||||
if first:
|
|
||||||
first = False
|
|
||||||
|
|
||||||
shapes.append(coords)
|
|
||||||
|
|
||||||
timer(t1, "parsing gcode")
|
|
||||||
|
|
||||||
return shapes
|
|
||||||
|
|
||||||
|
|
||||||
def g_string(x, y, z=False, prefix="G1", p=3):
|
|
||||||
if z is not False:
|
|
||||||
return f"{prefix} X{x:.{p}f} Y{y:.{p}f} Z{z:.{p}f}"
|
|
||||||
|
|
||||||
else:
|
|
||||||
return f"{prefix} X{x:.{p}f} Y{y:.{p}f}"
|
|
||||||
|
|
||||||
|
|
||||||
def shapes_2_gcode(shapes):
|
|
||||||
print(" shapes 2 gcode")
|
|
||||||
t1 = dt.now()
|
|
||||||
commands = []
|
|
||||||
for i in shapes:
|
|
||||||
|
|
||||||
commands.append(g_string(i[0][0], i[0][1], zTravel, "G0"))
|
|
||||||
|
|
||||||
for j in i:
|
|
||||||
commands.append(g_string(j[0], j[1], zDraw))
|
|
||||||
|
|
||||||
commands.append(g_string(i[-1][0], i[-1][1], zTravel, "G0"))
|
|
||||||
|
|
||||||
timer(t1, "shapes_2_gcode")
|
|
||||||
return commands
|
|
||||||
|
|
||||||
|
|
||||||
def get_distance(a, b, sq=True):
|
def get_distance(a, b, sq=True):
|
||||||
@@ -112,21 +15,16 @@ def get_distance(a, b, sq=True):
|
|||||||
return x * x + y * y
|
return x * x + y * y
|
||||||
|
|
||||||
|
|
||||||
def timer(t, label):
|
|
||||||
duration = dt.now() - t
|
|
||||||
duration = duration.total_seconds()
|
|
||||||
print("{} took {}".format(label, duration))
|
|
||||||
return duration
|
|
||||||
|
|
||||||
|
|
||||||
def optimise_path(shapes, sq=True):
|
def optimise_path(shapes, sq=True):
|
||||||
newOrder = []
|
|
||||||
newOrder.append(shapes.pop(0))
|
t1 = dt.now()
|
||||||
|
new_order = []
|
||||||
|
new_order.append(shapes.pop(0))
|
||||||
l = len(shapes)
|
l = len(shapes)
|
||||||
while len(newOrder) <= l:
|
while len(new_order) <= l:
|
||||||
|
|
||||||
shortest = float("Inf")
|
shortest = float("Inf")
|
||||||
last = newOrder[-1][-1]
|
last = new_order[-1][-1]
|
||||||
|
|
||||||
for shape in shapes:
|
for shape in shapes:
|
||||||
|
|
||||||
@@ -144,34 +42,10 @@ def optimise_path(shapes, sq=True):
|
|||||||
selection = shape
|
selection = shape
|
||||||
|
|
||||||
if reverse:
|
if reverse:
|
||||||
newOrder.append([x for x in reversed(selection)])
|
new_order.append([x for x in reversed(selection)])
|
||||||
else:
|
else:
|
||||||
newOrder.append(selection)
|
new_order.append(selection)
|
||||||
shapes.remove(selection)
|
shapes.remove(selection)
|
||||||
|
|
||||||
|
timer(t1, "optimizing ")
|
||||||
if __name__ == "__main__":
|
return new_order
|
||||||
|
|
||||||
file_path = "./svg/lines.svg"
|
|
||||||
file_path = "./svg/medium_example.svg"
|
|
||||||
file_path = "./svg/text.svg"
|
|
||||||
file_path = "./svg/example.svg"
|
|
||||||
|
|
||||||
output = "./gcode_optimised/1.gcode"
|
|
||||||
|
|
||||||
shapes = get_shapes(file_path)
|
|
||||||
|
|
||||||
if optimize:
|
|
||||||
|
|
||||||
newOrder = optimise_path(shapes)
|
|
||||||
commands = shapes_2_gcode(newOrder)
|
|
||||||
|
|
||||||
else:
|
|
||||||
|
|
||||||
commands = shapes_2_gcode(shapes)
|
|
||||||
|
|
||||||
with open(output, 'w+') as output_file:
|
|
||||||
for i in c:
|
|
||||||
output_file.write(i + "\n")
|
|
||||||
|
|
||||||
print("done")
|
|
||||||
+71
-89
@@ -6,69 +6,40 @@ import shapes as shapes_pkg
|
|||||||
from shapes import point_generator
|
from shapes import point_generator
|
||||||
from config import *
|
from config import *
|
||||||
import re
|
import re
|
||||||
|
from datetime import datetime as dt
|
||||||
|
from optimise import optimise_path
|
||||||
|
from utils import *
|
||||||
|
|
||||||
path = "./example.svg"
|
|
||||||
output = "./gcode/output1.gcode"
|
|
||||||
debug = False
|
debug = False
|
||||||
|
|
||||||
# todo add manual scale option
|
# todo add manual scale option
|
||||||
# todo add z rise option
|
# todo add z rise option
|
||||||
|
# todo why do i need to flip?
|
||||||
|
|
||||||
def generate_gcode(path, autoScale = True):
|
def get_shapes(path, autoScale=True):
|
||||||
|
|
||||||
|
t1 = dt.now()
|
||||||
svg_shapes = set(['rect', 'circle', 'ellipse', 'line', 'polyline', 'polygon', 'path'])
|
svg_shapes = set(['rect', 'circle', 'ellipse', 'line', 'polyline', 'polygon', 'path'])
|
||||||
|
shapes = []
|
||||||
with open("header.txt") as headerFile:
|
|
||||||
header = headerFile.read()
|
|
||||||
|
|
||||||
commands = []
|
|
||||||
tree = ET.parse(path)
|
tree = ET.parse(path)
|
||||||
root = tree.getroot()
|
root = tree.getroot()
|
||||||
width = root.get('width')
|
width = root.get('width')
|
||||||
height = root.get('height')
|
height = root.get('height')
|
||||||
|
|
||||||
if width == None or height == None:
|
if width is None or height is None:
|
||||||
viewbox = root.get('viewBox')
|
viewbox = root.get('viewBox')
|
||||||
if viewbox:
|
if viewbox:
|
||||||
_, _, width, height = viewbox.split()
|
_, _, width, height = viewbox.split()
|
||||||
|
|
||||||
if width == None or height == None:
|
if width is None or height is None:
|
||||||
print("Unable to get width and height for the svg")
|
print("Unable to get width and height for the svg")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
width = float(re.sub("[^0-9]", "", width))
|
width = float(re.sub("[^0-9]", "", width))
|
||||||
height = float(re.sub("[^0-9]", "", height))
|
height = float(re.sub("[^0-9]", "", height))
|
||||||
print("\n width / height")
|
|
||||||
print(width, height)
|
|
||||||
|
|
||||||
if autoScale:
|
|
||||||
|
|
||||||
scale_x = min(bed_max_x / max(width, height),bed_max_y / max(width, height))
|
|
||||||
scale_y = scale_x
|
|
||||||
|
|
||||||
else:
|
|
||||||
|
|
||||||
scale_x = 1
|
|
||||||
scale_y = 1
|
|
||||||
|
|
||||||
print("scale factor: ", scale_y)
|
|
||||||
|
|
||||||
if debug:
|
|
||||||
print("\n preamble")
|
|
||||||
print(preamble)
|
|
||||||
|
|
||||||
commands.append(header)
|
|
||||||
commands.append("(begintintin)")
|
|
||||||
commands.append(preamble)
|
|
||||||
commands.append(f"F{feed_rate}")
|
|
||||||
|
|
||||||
print("\n begin main loop")
|
|
||||||
|
|
||||||
for elem in root.iter():
|
for elem in root.iter():
|
||||||
|
|
||||||
if debug:
|
|
||||||
print("\n\n\n***************** elem ******************")
|
|
||||||
print(elem)
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
_, tag_suffix = elem.tag.split('}')
|
_, tag_suffix = elem.tag.split('}')
|
||||||
|
|
||||||
@@ -77,70 +48,36 @@ def generate_gcode(path, autoScale = True):
|
|||||||
|
|
||||||
if tag_suffix in svg_shapes:
|
if tag_suffix in svg_shapes:
|
||||||
|
|
||||||
if debug:
|
|
||||||
print("\n tag_suffix")
|
|
||||||
print(tag_suffix)
|
|
||||||
|
|
||||||
for i in ["\n", "({})".format(tag_suffix), ""]:
|
|
||||||
commands.append(i) # add tag name ad comment
|
|
||||||
|
|
||||||
shape_class = getattr(shapes_pkg, tag_suffix)
|
shape_class = getattr(shapes_pkg, tag_suffix)
|
||||||
if debug:
|
|
||||||
print("\n shape_class")
|
|
||||||
print(shape_class)
|
|
||||||
|
|
||||||
shape_obj = shape_class(elem)
|
shape_obj = shape_class(elem)
|
||||||
if debug:
|
|
||||||
print("\n shape_obj")
|
|
||||||
#print(shape_obj)
|
|
||||||
|
|
||||||
d = shape_obj.d_path()
|
d = shape_obj.d_path()
|
||||||
|
|
||||||
m = shape_obj.transformation_matrix() # todo work out what d and m are
|
m = shape_obj.transformation_matrix() # todo work out what d and m are
|
||||||
|
|
||||||
if debug:
|
coords = []
|
||||||
print("\n d", d)
|
|
||||||
print(d)
|
|
||||||
print("\n m", m)
|
|
||||||
print(m)
|
|
||||||
|
|
||||||
if d: # begin shape processing
|
if d: # begin shape processing
|
||||||
if debug:
|
|
||||||
print("\n shape preamble")
|
|
||||||
print(shape_preamble)
|
|
||||||
|
|
||||||
commands.append(shape_preamble)
|
|
||||||
|
|
||||||
p = point_generator(d, m, smoothness) # tuples of x y coords
|
p = point_generator(d, m, smoothness) # tuples of x y coords
|
||||||
|
|
||||||
first = True
|
first = True
|
||||||
for x, y in p:
|
|
||||||
|
for x, y in p: # todo sort out this nightmare
|
||||||
|
|
||||||
if first:
|
if first:
|
||||||
|
coords.append((x, -y + height))
|
||||||
|
|
||||||
command = g_string(x * scale_x, (-y+height) * scale_y, zTravel, "G0", precision) #todo why do i need to flip?
|
else:
|
||||||
commands.append(command)
|
|
||||||
if debug:
|
if not (x, y) == coords[-1]:
|
||||||
print(command)
|
coords.append((x, -y + height))
|
||||||
|
|
||||||
|
if first:
|
||||||
first = False
|
first = False
|
||||||
|
|
||||||
# if x > 0 and x < bed_max_x and y > 0 and y < bed_max_y:
|
shapes.append(coords)
|
||||||
|
|
||||||
command = g_string(x * scale_x, (-y+height) * scale_y, zDraw, "G1", precision)
|
timer(t1, "parsing gcode ")
|
||||||
commands.append(command)
|
|
||||||
if debug:
|
|
||||||
print(command)
|
|
||||||
|
|
||||||
command = g_string(x, y, zTravel, "G0", precision)
|
return shapes
|
||||||
commands.append(command)
|
|
||||||
|
|
||||||
if debug:
|
|
||||||
print(shape_postamble)
|
|
||||||
commands.append(shape_postamble)
|
|
||||||
|
|
||||||
print(postamble)
|
|
||||||
commands.append(postamble)
|
|
||||||
return commands
|
|
||||||
|
|
||||||
|
|
||||||
def g_string(x, y, z=False, prefix="G1", p=3):
|
def g_string(x, y, z=False, prefix="G1", p=3):
|
||||||
@@ -151,12 +88,57 @@ def g_string(x, y, z=False, prefix="G1", p=3):
|
|||||||
return f"{prefix} X{x:.{p}f} Y{y:.{p}f}"
|
return f"{prefix} X{x:.{p}f} Y{y:.{p}f}"
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
def shapes_2_gcode(shapes):
|
||||||
c = generate_gcode(path)
|
|
||||||
|
|
||||||
|
t1 = dt.now()
|
||||||
|
commands = []
|
||||||
|
for i in shapes:
|
||||||
|
|
||||||
|
commands.append(g_string(i[0][0], i[0][1], zTravel, "G0"))
|
||||||
|
|
||||||
|
for j in i:
|
||||||
|
commands.append(g_string(j[0], j[1], zDraw))
|
||||||
|
|
||||||
|
commands.append(g_string(i[-1][0], i[-1][1], zTravel, "G0"))
|
||||||
|
|
||||||
|
timer(t1, "shapes_2_gcode ")
|
||||||
|
return commands
|
||||||
|
|
||||||
|
def write_file(output, commands):
|
||||||
|
|
||||||
|
t1 = dt.now()
|
||||||
with open(output, 'w+') as output_file:
|
with open(output, 'w+') as output_file:
|
||||||
for i in c:
|
for i in commands:
|
||||||
output_file.write(i + "\n")
|
output_file.write(i + "\n")
|
||||||
|
timer(t1, "writing file ")
|
||||||
|
|
||||||
|
def main(file_path, output):
|
||||||
|
|
||||||
|
shapes = get_shapes(file_path)
|
||||||
|
|
||||||
|
if optimise:
|
||||||
|
|
||||||
|
new_order = optimise_path(shapes)
|
||||||
|
commands = shapes_2_gcode(new_order)
|
||||||
|
|
||||||
|
else:
|
||||||
|
|
||||||
|
commands = shapes_2_gcode(shapes)
|
||||||
|
|
||||||
|
write_file(output, commands)
|
||||||
|
|
||||||
print("done")
|
print("done")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
|
||||||
|
# file_path = "./svg/lines.svg"
|
||||||
|
# file_path = "./svg/medium_example.svg"
|
||||||
|
file_path = "./svg/text.svg"
|
||||||
|
# file_path = "./svg/example.svg"
|
||||||
|
|
||||||
|
output = "./gcode_optimised/1.gcode"
|
||||||
|
|
||||||
|
main(file_path, output)
|
||||||
|
|
||||||
|
|
||||||
Reference in new issue
Block a user