diff --git a/.idea/other.xml b/.idea/other.xml new file mode 100644 index 0000000..a708ec7 --- /dev/null +++ b/.idea/other.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/GCodeRenderer.py b/GCodeRenderer.py index b0942cd..af683a1 100644 --- a/GCodeRenderer.py +++ b/GCodeRenderer.py @@ -16,11 +16,17 @@ class Renderer(): def clear_screen(self): - self.svg_context.rectangle(0, 0, self.settings.canvas_x, self.settings.canvas_y) - self.svg_context.set_source_rgba(1, 1, 1, 1.0) - self.svg_context.fill() - self.svg_context.set_source_rgba(0, 0, 0, 1.0) - self.svg_context.stroke() + self.svg_surface.finish() + self.svg_surface = cairo.SVGSurface("tmp/rendered-output-t.svg", self.settings.canvas_x, self.settings.canvas_y) + self.svg_context = cairo.Context(self.svg_surface) + self.svg_context.scale(1, 1) + self.svg_context.set_line_width(0.1) + + # self.svg_context.rectangle(0, 0, self.settings.canvas_x, self.settings.canvas_y) + # self.svg_context.set_source_rgba(1, 1, 1, 1.0) + # self.svg_context.fill() + # self.svg_context.set_source_rgba(0, 0, 0, 1.0) + # self.svg_context.stroke() # Render GCODE from the gcode-output.gcode output file that was generated in convert_gcode def render_gcode(self): @@ -116,18 +122,5 @@ class Renderer(): self.svg_surface = cairo.SVGSurface("tmp/rendered-output-t.svg", self.settings.canvas_x, self.settings.canvas_y) self.svg_context = cairo.Context(self.svg_surface) - # def render(self): - # self.clear_screen() - # # self.render_gcode() - # # - # # if self.label is not None: - # # self.label.pack_forget() - # # - # # # Apply the rendered gcode image to the UI - # # self.image_ref = ImageTk.PhotoImage( - # # Image.frombuffer("RGBA", (self.bed_actual_x, self.bed_actual_y), self.png_surface.get_data().tobytes(), "raw", "BGRA", 0, 1)) - # # self.label = Label(self, image=self.image_ref) - # # self.label.pack(expand=True, fill="both") - def toggle_flip_markers(self): self.settings.lift_markers = not self.settings.lift_markers \ No newline at end of file diff --git a/ImageConverter.py b/ImageConverter.py index ba86cfb..a20073f 100644 --- a/ImageConverter.py +++ b/ImageConverter.py @@ -7,6 +7,8 @@ class ImageConverter: # mkbitmap settings self.highpass_filter = 0 self.blur = 0 + # potrace settings + self.turd = 0 # This function takes a file and runs it through mogrify, mkbitmap, and finally potrace. # The flow of the intermediate files is @@ -39,12 +41,17 @@ class ImageConverter: print("Running potrace...") start = time.time() - subprocess.call(["potrace", - # "-t", "0.1", + + potrace_args = ["potrace", "-z", "white", "-b", "svg", "input-images/{}-n.pbm".format(base_name), "--rotate", "0", - "-o", "tmp/conversion-output.svg", - ]) + "-o", "tmp/conversion-output.svg"] + + if settings.turd > 0: + potrace_args.append(["-t", settings.turd]) + + subprocess.call(potrace_args) + print("Run took [{:.2f}] seconds\n".format(time.time() - start)) \ No newline at end of file diff --git a/Svg2GcodeConverter.py b/Svg2GcodeConverter.py index c4e9582..8915c93 100644 --- a/Svg2GcodeConverter.py +++ b/Svg2GcodeConverter.py @@ -19,9 +19,10 @@ def triangulate_lengths(settings, dest_xy): return left_pulley_length, right_pulley_length - +# http://paulbourke.net/geometry/circlesphere/ +# https://math.stackexchange.com/questions/187107/calculate-coordinates-of-3rd-point-vertex-of-a-scalene-triangle-if-angles-and +# http://xaktly.com/MathNonRightTrig.html def untriangulate_lengths(settings, x, y): - result = [0, 0] r0 = x r1 = y @@ -30,6 +31,9 @@ def untriangulate_lengths(settings, x, y): a = (pow(r0, 2) - pow(r1, 2) + pow(r2, 2)) / (2 * r2) h = math.sqrt(pow(r0, 2) - pow(a, 2)) + a = a + settings.left_pulley_x_offset + h = h - settings.pulley_y_droop + return a, h @@ -96,8 +100,8 @@ class Svg2GcodeConverter: max_x_dim = max(bounding_x_max, bounding_x_min) max_y_dim = max(bounding_y_max, bounding_y_min) - scale_x = self.settings.canvas_x / max_x_dim - scale_y = self.settings.canvas_y / max_y_dim + scale_x = self.settings.canvas_x / max_x_dim + scale_y = self.settings.canvas_y / max_y_dim scale = min(scale_x, scale_y) print("Scaling to : {:.5f}\n".format(scale)) @@ -106,8 +110,6 @@ class Svg2GcodeConverter: gcode = "" gcode += self.gcode_preamble - current_position = (self.settings.canvas_x/2, self.settings.pulley_y_droop) - # Walk through the paths and create the GCODE for path in paths: @@ -155,11 +157,8 @@ class Svg2GcodeConverter: for i in pos: evals.append(curve.evaluate(i)) - - #gcode += "G1 X{:.3f} Y{:.3f}\n".format(start_x, start_y) - lengths = triangulate_lengths(self.settings, (start_x, start_y)) - gcode += "; Setting down tip at beginning of line ({}, {})\n".format(start_x, start_y) + # gcode += "; Setting down tip at beginning of line ({}, {})\n".format(start_x, start_y) gcode += "G1 X{:.3f} Y{:.3f}\n".format(lengths[0], lengths[1]) gcode += "G1 Z{:.3f} \n".format(0) @@ -167,17 +166,17 @@ class Svg2GcodeConverter: x = i[0][0] y = i[1][0] tmp_len = triangulate_lengths(self.settings, (x * scale, y * scale)) - gcode += "; Continuing the line ({}, {})\n".format(x * scale, y * scale) + # gcode += "; Continuing the line ({}, {})\n".format(x * scale, y * scale) gcode += "G1 X{:.3f} Y{:.3f}\n".format(tmp_len[0], tmp_len[1]) if isinstance(part, Line): start_len = triangulate_lengths(self.settings, (start_x, start_y)) end_len = triangulate_lengths(self.settings, (end_x, end_y)) - gcode += "; Setting down tip at beginning of line ({}, {})\n".format(start_x, start_y) + # gcode += "; Setting down tip at beginning of line ({}, {})\n".format(start_x, start_y) gcode += "G1 X{:.3f} Y{:.3f}\n".format(start_len[0], start_len[1]) gcode += "G1 Z{:.3f} \n".format(0) - gcode += "; Moving tip to the end of the line ({}, {})\n".format(end_x, end_y) + # gcode += "; Moving tip to the end of the line ({}, {})\n".format(end_x, end_y) gcode += "G1 X{:.3f} Y{:.3f}\n".format(end_len[0], end_len[1]) gcode += self.gcode_end diff --git a/input-images/funky-bird.jpg b/input-images/funky-bird.jpg new file mode 100755 index 0000000..d4d1dc1 Binary files /dev/null and b/input-images/funky-bird.jpg differ diff --git a/input-images/leaf.jpg b/input-images/leaf.jpg new file mode 100755 index 0000000..21d9015 Binary files /dev/null and b/input-images/leaf.jpg differ diff --git a/input-images/new-york.jpg b/input-images/new-york.jpg new file mode 100755 index 0000000..a7899e4 Binary files /dev/null and b/input-images/new-york.jpg differ diff --git a/main.py b/main.py index 42000fb..4901fde 100644 --- a/main.py +++ b/main.py @@ -11,7 +11,6 @@ from ImageConverter import ImageConverter from Simulator import Simulator - class Settings: def __init__(self): @@ -19,8 +18,8 @@ class Settings: # ============ HARDCODED VALUES =========== # Canvas size - self.canvas_x = 300 - self.canvas_y = 300 + self.canvas_x = 1000 + self.canvas_y = 1000 # The position of the pulley centers in relation to the top left and right of the canvas self.left_pulley_x_offset = -40 @@ -50,6 +49,8 @@ class Tracer(Tk): def update_blur_value(self, value): self.blur = value + def update_turd_value(self, value): + self.turd = value def __init__(self): @@ -83,17 +84,20 @@ class Tracer(Tk): self.image_ref = None # Initialize TK - self.geometry("{}x{}".format(500, 500)) + self.geometry("{}x{}".format(800, 800)) - self.n = Notebook(self, width= 400, height =400) - self.n.pack(fill=BOTH, expand=1) + self.tab_bar = Notebook(self, width= 400, height =400) + self.tab_bar.pack(fill=BOTH, expand=1) - self.f1 = Frame(self.n) - self.f2 = Frame(self.n) + self.converted_image_tab = Frame(self.tab_bar) + self.original_image_tab = Frame(self.tab_bar) self.rightframe = Frame(self) self.rightframe.pack(side=RIGHT) + self.centerframe = Frame(self) + self.centerframe.pack(side=BOTTOM) + self.image_select_button = Button(self.rightframe, text="Select Image", command=self.file_select_callback) self.image_select_button.pack() @@ -106,14 +110,24 @@ class Tracer(Tk): self.lift_markers_checkbox = Checkbutton(self.rightframe, text="Lift Markers", command=self.cairo_renderer.toggle_flip_markers) self.lift_markers_checkbox.pack() - self.highpass_slider = Scale(self.rightframe, command=self.update_highpass_value, resolution=0.1, to=15) + self.highpass_label = Label(self.centerframe, text="Highpass filter", fg="black") + self.highpass_label.pack() + self.highpass_slider = Scale(self.centerframe, command=self.update_highpass_value, resolution=0.0, to=15, orient=HORIZONTAL) self.highpass_slider.set(self.image_converter_settings.highpass_filter) self.highpass_slider.pack() - self.blur_slider = Scale(self.rightframe, command=self.update_blur_value, resolution=0.1, to=5) + self.blur_label = Label(self.centerframe, text="Blur", fg="black") + self.blur_label.pack() + self.blur_slider = Scale(self.centerframe, command=self.update_blur_value, resolution=0.0, to=5, orient=HORIZONTAL) self.blur_slider.set(self.image_converter_settings.blur) self.blur_slider.pack() + self.turd_label = Label(self.centerframe, text="Turds", fg="black") + self.turd_label.pack() + self.turd_slider = Scale(self.centerframe, command=self.update_turd_value, resolution=0.0, to=5, orient=HORIZONTAL) + self.turd_slider.set(self.image_converter_settings.turd) + self.turd_slider.pack() + # Start TK self.mainloop() @@ -139,8 +153,8 @@ class Tracer(Tk): self.cairo_renderer.clear_screen() self.cairo_renderer.render_gcode() - self.f1.pack_forget() - self.f2.pack_forget() + self.converted_image_tab.pack_forget() + self.original_image_tab.pack_forget() if self.label is not None: self.label.pack_forget() @@ -152,14 +166,14 @@ class Tracer(Tk): # scale = self.winfo_width() / pil_image.width # pil_image = pil_image.resize((int(scale * pil_image.width), int(scale * pil_image.height))) self.image_ref = ImageTk.PhotoImage(pil_image) - self.label = Label(self.f1, image=self.image_ref) - self.n.add(self.f1, text="Converted") + self.label = Label(self.converted_image_tab, image=self.image_ref) + self.tab_bar.add(self.converted_image_tab, text="Converted") self.label.pack(expand=True, fill="both") self.pic = ImageTk.PhotoImage(file="input-images/{}".format(self.filename)) - self.label1 = Label(self.f2, image=self.pic) - self.n.add(self.f2, text="Original") + self.label1 = Label(self.original_image_tab, image=self.pic) + self.tab_bar.add(self.original_image_tab, text="Original") self.label1.pack(expand=True, fill="both") def render_simulation(self):