Skip to content

Commit

Permalink
auto extrusion for arcs too
Browse files Browse the repository at this point in the history
  • Loading branch information
rmeno12 committed Jan 2, 2022
1 parent 43aef3c commit c386a17
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 14 deletions.
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,5 @@ G-code generator for Marlin printers.
Inspired by [Full Control GCODE](http://fullcontrolgcode.com/).

## Planned features
- create g-code based on mathematical functions/generators
- cleaner interfacing for absolute movements

2 changes: 1 addition & 1 deletion examples/circlegrid.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
g.travel((0, 20, 0))
for j in range(3):
g.travel((20, 0, 0))
g.draw_arc(0, -10, e=5)
g.draw_arc(0, -10)
g.travel((-60, 0, 0))

g.set_tool_temp(0)
Expand Down
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[metadata]
name = gcodepy
version = 0.0.1
version = 0.1.0
author = Rahul Menon
author_email = [email protected]
description = Tool to generate g-code for Marlin based printers
Expand Down
41 changes: 32 additions & 9 deletions src/gcodepy/gcode.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
from typing import Callable, Tuple, Union
import math
from . import util

# circumference calcs for arcs
# TODO:
# minimize feedrate output
# draw absolute
# catch more invalid inputs
class Gcode:
def __init__(
self,
Expand Down Expand Up @@ -92,9 +94,14 @@ def travel(self, delta: Tuple[float, float, float], feedrate: int = 2400):
self.pos[0] += delta[0]
self.pos[1] += delta[1]
self.pos[2] += delta[2]
self.file.write(
f"G0 F{feedrate} X{self.pos[0]} Y{self.pos[1]} Z{self.pos[2]}\n"
)
out = f"G0 F{feedrate}"
if delta[0] != 0.0:
out += f" X{self.pos[0]}"
if delta[1] != 0.0:
out += f" Y{self.pos[1]}"
if delta[2] != 0.0:
out += f" Z{self.pos[2]}"
self.file.write(out + "\n")

def travel_arc(
self,
Expand Down Expand Up @@ -139,9 +146,15 @@ def draw(
self.pos[1] += delta[1]
self.pos[2] += delta[2]
self.e += e
self.file.write(
f"G1 F{feedrate} X{self.pos[0]} Y{self.pos[1]} Z{self.pos[2]} E{self.e}\n"
)
out = f"G1 F{feedrate}"
if delta[0] != 0.0:
out += f" X{self.pos[0]}"
if delta[1] != 0.0:
out += f" Y{self.pos[1]}"
if delta[2] != 0.0:
out += f" Z{self.pos[2]}"
out += f" E{e}"
self.file.write(out + "\n")

def draw_arc(
self,
Expand All @@ -154,7 +167,7 @@ def draw_arc(
):
if e is None:
e = self.extrusion_length_calculator(
util.dist(delta), # REPLACE
util.arclen((i, j), delta[:2], clockwise),
self.line_width,
self.layer_height,
self.filament_width,
Expand Down Expand Up @@ -182,9 +195,19 @@ def draw_arc_r(
clockwise: bool = True,
feedrate: int = 2400,
):
if r == 0 or r is None:
raise ValueError("Radius r cannot be 0 or None.")
if e is None:
d2 = (delta[0] / 2, delta[1] / 2)
m = -1 if clockwise ^ (r < 0) else 1
l = util.dist(d2)
h2 = (r - l) * (r + l)
h = 0 if h2 < 0 else math.sqrt(h2)
s = (-d2[1], d2[0])
s = [s[i] / l * m * h for i in range(2)]
center = tuple(d2[i] + s[i] for i in range(2))
e = self.extrusion_length_calculator(
util.dist(delta), # REPLACE
util.arclen(center, delta[:2], clockwise),
self.line_width,
self.layer_height,
self.filament_width,
Expand Down
28 changes: 26 additions & 2 deletions src/gcodepy/util.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,35 @@
import math
from typing import Tuple
from typing import Iterable, Tuple


def dist(delta: Tuple[float, float, float]) -> float:
def dist(delta: Iterable[float]) -> float:
return math.sqrt(sum(i ** 2 for i in delta))


def arclen(
center: Tuple[float, float], other: Tuple[float, float], clockwise: bool
) -> float:
radius = dist(center)
if other == (0.0, 0.0):
return math.pi * radius ** 2

# using formula theta = atan2(||u x v||, u . v)
rvec = tuple(-i for i in center)
rt = tuple(other[i] - center[i] for i in range(2))
uxv = rvec[0] * rt[1] - rvec[1] * rt[0]
udv = rvec[0] * rt[0] + rvec[1] * rt[1]
angle = math.atan2(uxv, udv)
if abs(angle) < 1e-6:
return 0

if clockwise and angle > 0:
angle = 2 * math.pi - angle
elif not clockwise and angle < 0:
angle += 2 * math.pi

return angle * radius


def calculate_extrusion_length(
path_length: float,
line_width: float,
Expand Down

0 comments on commit c386a17

Please sign in to comment.