Compare commits
10 Commits
52ff3e60e7
...
develop
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ade1aba1b1 | ||
| 6447a11768 | |||
| a1d73a26da | |||
| fa1122b32c | |||
| f9232df233 | |||
| 20c943b73c | |||
| b4a774b2b9 | |||
| 3acbff18e7 | |||
| ac709f9925 | |||
| d3fcba9ebc |
@@ -1,21 +0,0 @@
|
|||||||
|
|
||||||
class GCodeParser():
|
|
||||||
def __init__(self, gcode_file):
|
|
||||||
self.gcode_file = gcode_file
|
|
||||||
self.lines = []
|
|
||||||
self._parse_gcode()
|
|
||||||
|
|
||||||
def _parse_gcode(self):
|
|
||||||
from pygcode import Line, Machine
|
|
||||||
machine = Machine()
|
|
||||||
positions = []
|
|
||||||
with open(self.gcode_file, "r") as gcode_file:
|
|
||||||
for line_text in gcode_file:
|
|
||||||
line = Line(line_text)
|
|
||||||
if line.block.gcodes:
|
|
||||||
machine.process_gcodes(*line.block.gcodes)
|
|
||||||
positions.append((machine.pos.X, machine.pos.Y, machine.pos.Z))
|
|
||||||
self.lines = positions
|
|
||||||
|
|
||||||
def get_positions(self):
|
|
||||||
return self.lines
|
|
||||||
210
gcodeinterpreter.py
Normal file
210
gcodeinterpreter.py
Normal file
@@ -0,0 +1,210 @@
|
|||||||
|
import math
|
||||||
|
import re
|
||||||
|
|
||||||
|
class GcodeInterpreter:
|
||||||
|
"""
|
||||||
|
A basic G-code interpreter that converts G-code commands into a list of coordinates.
|
||||||
|
Supports G00, G01, G02, and G03 commands.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
current_position (list): The current position in 3D space [X, Y, Z].
|
||||||
|
feed_rate (float): The current feed rate.
|
||||||
|
coordinates (list): The list of calculated coordinates.
|
||||||
|
segment_multiplier (float): Multiplier for distance to determine number of segments.
|
||||||
|
max_segments (int): Maximum number of segments allowed.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, initial_position=[0, 0, 0], initial_feed_rate=0, segment_multiplier=2, max_segments=50):
|
||||||
|
"""
|
||||||
|
Initializes the GcodeInterpreter with the initial position, feed rate, segment multiplier, and maximum segments.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
initial_position (list, optional): The initial position [X, Y, Z]. Defaults to [0, 0, 0].
|
||||||
|
initial_feed_rate (float, optional): The initial feed rate. Defaults to 0.
|
||||||
|
segment_multiplier (float, optional): Multiplier for distance to determine number of segments. Defaults to 10.0
|
||||||
|
max_segments (int, optional): Maximum number of segments allowed. Defaults to 100.
|
||||||
|
"""
|
||||||
|
self.current_position = initial_position[:] # Use a copy to avoid modifying the original
|
||||||
|
self.feed_rate = initial_feed_rate
|
||||||
|
self.coordinates = [initial_position[:]] # Store the initial position
|
||||||
|
self.segment_multiplier = segment_multiplier # Added segment multiplier
|
||||||
|
self.max_segments = max_segments # Added max segments
|
||||||
|
|
||||||
|
def parse_file(self, filename):
|
||||||
|
"""
|
||||||
|
Parses a G-code file and processes each line.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
filename (str): The path to the G-code file.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
GcodeInterpreter: The instance of the GcodeInterpreter with processed coordinates.
|
||||||
|
"""
|
||||||
|
with open(filename, 'r') as file:
|
||||||
|
for line in file:
|
||||||
|
self.parse_line(line)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def parse_line(self, line):
|
||||||
|
"""
|
||||||
|
Parses a single line of G-code.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
line (str): The G-code line to parse.
|
||||||
|
"""
|
||||||
|
line = line.strip()
|
||||||
|
if not line or line.startswith('%') or line.startswith('('): # Skip empty lines and lines starting with '%'
|
||||||
|
return
|
||||||
|
|
||||||
|
# Use regular expression for more robust parsing
|
||||||
|
parts = re.findall(r'([A-Za-z])([-+]?\d*\.?\d*)', line) # Find all letter-number pairs
|
||||||
|
if not parts:
|
||||||
|
return # Skip lines without any recognized G-code commands
|
||||||
|
|
||||||
|
command = parts[0][0].upper() + parts[0][1]
|
||||||
|
args = {}
|
||||||
|
for part in parts:
|
||||||
|
if part[0].upper() != command:
|
||||||
|
try:
|
||||||
|
args[part[0].upper()] = float(part[1]) if part[1] else 0.0 # convert the number part to float
|
||||||
|
except ValueError:
|
||||||
|
print(f"Warning: Could not convert value '{part[1]}' to float for argument {part[0]}. Skipping.")
|
||||||
|
args[part[0].upper()] = 0.0
|
||||||
|
self.process_command(command, args)
|
||||||
|
|
||||||
|
def process_command(self, command, args):
|
||||||
|
"""
|
||||||
|
Processes a G-code command and calls the appropriate function.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
command (str): The G-code command (e.g., 'G00', 'G01', 'G02', 'G03').
|
||||||
|
args (dict): A dictionary of arguments for the command (e.g., {'X': 10, 'Y': 20}).
|
||||||
|
"""
|
||||||
|
if not command: # Add this check
|
||||||
|
return
|
||||||
|
if command in ('G00', 'G01'):
|
||||||
|
self.process_g00_g01(command, args)
|
||||||
|
elif command == 'G02':
|
||||||
|
self.process_g02_g03(command, args, clockwise=True)
|
||||||
|
elif command == 'G03':
|
||||||
|
self.process_g02_g03(command, args, clockwise=False)
|
||||||
|
elif command == 'G04':
|
||||||
|
self.process_g04(args)
|
||||||
|
elif command == 'F':
|
||||||
|
self.feed_rate = args.get('F', self.feed_rate) # Keep the current feed rate if not provided
|
||||||
|
# Add other G-code commands as needed (e.g., G02, G03, G28, etc.)
|
||||||
|
else:
|
||||||
|
print(f"Unsupported G-code command: {command}")
|
||||||
|
|
||||||
|
def process_g00_g01(self, command, args):
|
||||||
|
"""
|
||||||
|
Processes G00 (Rapid Linear Move) and G01 (Controlled Linear Move) commands.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
command (str): The G-code command ('G00' or 'G01').
|
||||||
|
args (dict): A dictionary of arguments for the command (e.g., {'X': 10, 'Y': 20, 'Z': 5}).
|
||||||
|
"""
|
||||||
|
new_position = [args.get('X', self.current_position[0]),
|
||||||
|
args.get('Y', self.current_position[1]),
|
||||||
|
args.get('Z', self.current_position[2])]
|
||||||
|
|
||||||
|
# Calculate the distance between the current position and the new position
|
||||||
|
distance = math.sqrt(
|
||||||
|
(new_position[0] - self.current_position[0]) ** 2 +
|
||||||
|
(new_position[1] - self.current_position[1]) ** 2 +
|
||||||
|
(new_position[2] - self.current_position[2]) ** 2
|
||||||
|
)
|
||||||
|
|
||||||
|
# Number of segments. Increase for smoother lines, but use a reasonable maximum.
|
||||||
|
segments = int(distance * self.segment_multiplier) + 1
|
||||||
|
segments = min(segments, self.max_segments) # Limit the maximum number of segments
|
||||||
|
|
||||||
|
for i in range(segments + 1):
|
||||||
|
x = self.current_position[0] + (new_position[0] - self.current_position[0]) * i / segments
|
||||||
|
y = self.current_position[1] + (new_position[1] - self.current_position[1]) * i / segments
|
||||||
|
z = self.current_position[2] + (new_position[2] - self.current_position[2]) * i / segments
|
||||||
|
self.current_position = [x, y, z]
|
||||||
|
self.coordinates.append([x, y, z])
|
||||||
|
|
||||||
|
def process_g02_g03(self, command, args, clockwise=True):
|
||||||
|
"""
|
||||||
|
Processes G02 (Clockwise Circular Interpolation) and G03 (Counter-Clockwise Circular Interpolation) commands.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
command (str): The G-code command ('G02' or 'G03').
|
||||||
|
args (dict): A dictionary of arguments for the command.
|
||||||
|
clockwise (bool): True for G02 (clockwise), False for G03 (counter-clockwise).
|
||||||
|
"""
|
||||||
|
new_position = [args.get('X', self.current_position[0]),
|
||||||
|
args.get('Y', self.current_position[1]),
|
||||||
|
args.get('Z', self.current_position[2])]
|
||||||
|
center = [self.current_position[0] + args.get('I', 0),
|
||||||
|
self.current_position[1] + args.get('J', 0),
|
||||||
|
self.current_position[2] + args.get('K', 0)]
|
||||||
|
|
||||||
|
radius = math.sqrt((self.current_position[0] - center[0]) ** 2 +
|
||||||
|
(self.current_position[1] - center[1]) ** 2 +
|
||||||
|
(self.current_position[2] - center[2]) ** 2)
|
||||||
|
# Handle the case where the radius is zero
|
||||||
|
if radius == 0:
|
||||||
|
print(f"Warning: Radius is zero for {command}. No interpolation performed.")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Calculate the angle between the current point and the target point
|
||||||
|
start_angle = math.atan2(self.current_position[1] - center[1], self.current_position[0] - center[0])
|
||||||
|
end_angle = math.atan2(new_position[1] - center[1], new_position[0] - center[0])
|
||||||
|
|
||||||
|
# Ensure angles are between 0 and 2*pi
|
||||||
|
if start_angle < 0:
|
||||||
|
start_angle += 2 * math.pi
|
||||||
|
if end_angle < 0:
|
||||||
|
end_angle += 2 * math.pi
|
||||||
|
|
||||||
|
# Calculate the total angle
|
||||||
|
total_angle = end_angle - start_angle
|
||||||
|
if clockwise:
|
||||||
|
if total_angle > 0:
|
||||||
|
total_angle -= 2 * math.pi
|
||||||
|
else:
|
||||||
|
if total_angle < 0:
|
||||||
|
total_angle += 2 * math.pi
|
||||||
|
|
||||||
|
# Number of segments. Increase for smoother curves.
|
||||||
|
arc_length = radius * abs(total_angle)
|
||||||
|
segments = int(arc_length * self.segment_multiplier) + 1 # Dynamic segments, at least 1.
|
||||||
|
segments = min(segments, self.max_segments) # Limit max segments
|
||||||
|
angle_increment = total_angle / segments
|
||||||
|
|
||||||
|
for i in range(segments + 1):
|
||||||
|
angle = start_angle + i * angle_increment
|
||||||
|
x = center[0] + radius * math.cos(angle)
|
||||||
|
y = center[1] + radius * math.sin(angle)
|
||||||
|
z = (self.current_position[2] + (new_position[2] - self.current_position[2]) * i / segments)
|
||||||
|
self.current_position = [x, y, z]
|
||||||
|
self.coordinates.append([x, y, z])
|
||||||
|
|
||||||
|
def process_g04(self, args):
|
||||||
|
"""Processes G04 (Dwell) command. For now, just prints a message.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
args (dict): A dictionary of arguments, containing 'P' for the dwell time in milliseconds
|
||||||
|
"""
|
||||||
|
dwell_time = args.get('P', 0)
|
||||||
|
print(f"G04 Dwell for {dwell_time} milliseconds")
|
||||||
|
# In a real implementation, you would pause execution here. For this example, we just print.
|
||||||
|
pass
|
||||||
|
|
||||||
|
def get_coordinates(self):
|
||||||
|
"""
|
||||||
|
Returns the list of calculated coordinates.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
list: The list of coordinates.
|
||||||
|
"""
|
||||||
|
return self.coordinates
|
||||||
|
|
||||||
|
def reset(self):
|
||||||
|
"""Resets the interpreter to its initial state."""
|
||||||
|
self.current_position = [0, 0, 0]
|
||||||
|
self.feed_rate = 0
|
||||||
|
self.coordinates = [[0,0,0]]
|
||||||
16
main.py
16
main.py
@@ -1,6 +1,7 @@
|
|||||||
#! /usr/bin/env python
|
#! /usr/bin/env python
|
||||||
from argparse import ArgumentParser
|
from argparse import ArgumentParser
|
||||||
from gcode_parser import GCodeParser
|
from gcodeinterpreter import GcodeInterpreter
|
||||||
|
from pwm_driver import PWMDriver
|
||||||
from visualizer import Visualizer
|
from visualizer import Visualizer
|
||||||
|
|
||||||
# A4
|
# A4
|
||||||
@@ -12,12 +13,19 @@ if __name__ == "__main__":
|
|||||||
argparser.add_argument("-f", "--file", type=str)
|
argparser.add_argument("-f", "--file", type=str)
|
||||||
argparser.add_argument("-W", "--width", type=float, default=WIDTH_MM, required=False)
|
argparser.add_argument("-W", "--width", type=float, default=WIDTH_MM, required=False)
|
||||||
argparser.add_argument("-H", "--height", type=float, default=HEIGHT_MM, required=False)
|
argparser.add_argument("-H", "--height", type=float, default=HEIGHT_MM, required=False)
|
||||||
|
argparser.add_argument("-V", "--visualize", action="store_true", default=False, required=False)
|
||||||
|
argparser.add_argument("-P", "--port", type=str, default=None)
|
||||||
|
|
||||||
args = argparser.parse_args()
|
args = argparser.parse_args()
|
||||||
|
|
||||||
parser = GCodeParser(args.file)
|
parser = GcodeInterpreter().parse_file(args.file)
|
||||||
positions = parser.get_positions()
|
positions = parser.get_coordinates()
|
||||||
|
|
||||||
screen_dimensions = (1024*1.5, 1024*1.5 * HEIGHT_MM/WIDTH_MM)
|
if args.visualize:
|
||||||
|
screen_dimensions = (1024*1.5, 1024*1.5 * args.height/args.width)
|
||||||
visualizer = Visualizer(positions, screen_dimensions, (args.width, args.height))
|
visualizer = Visualizer(positions, screen_dimensions, (args.width, args.height))
|
||||||
visualizer.visualize()
|
visualizer.visualize()
|
||||||
|
|
||||||
|
if args.port:
|
||||||
|
pwm = PWMDriver(positions, (args.width, args.height), args.port)
|
||||||
|
pwm.run()
|
||||||
18
port-finder.py
Executable file
18
port-finder.py
Executable file
@@ -0,0 +1,18 @@
|
|||||||
|
#! /usr/bin/env python3
|
||||||
|
|
||||||
|
import serial.tools.list_ports
|
||||||
|
from serial.tools.list_ports_common import ListPortInfo
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
ports = serial.tools.list_ports.comports()
|
||||||
|
for port in ports:
|
||||||
|
if port.interface and port.interface.startswith("CircuitPython CDC2"): # CDC2 is the data-port
|
||||||
|
print(f"Port: {port.device}")
|
||||||
|
print(f" Description: {port.description}")
|
||||||
|
print(f" Manufacturer: {port.manufacturer}")
|
||||||
|
print(f" VID: {port.vid}")
|
||||||
|
print(f" PID: {port.pid}")
|
||||||
|
print(f" Serial Number: {port.serial_number}")
|
||||||
|
print(f" Location: {port.location}")
|
||||||
|
print(f" Interface: {port.interface}")
|
||||||
|
print()
|
||||||
39
pwm_driver.py
Normal file
39
pwm_driver.py
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
|
||||||
|
class PWMDriver():
|
||||||
|
def __init__(self, positions : list[tuple[float, float, float]], gcode_size : tuple[float, float], port : str, baudrate : int = 115200) -> None:
|
||||||
|
self.positions = positions
|
||||||
|
self.gcode_size = gcode_size
|
||||||
|
self.port = port
|
||||||
|
self.baudrate = baudrate
|
||||||
|
self._init_pwm()
|
||||||
|
|
||||||
|
def _init_pwm(self) -> None:
|
||||||
|
from serial import Serial
|
||||||
|
self.serial = Serial(self.port, self.baudrate)
|
||||||
|
|
||||||
|
def _send_position(self, pos : tuple[float, float, float]) -> None:
|
||||||
|
x, y, z = pos
|
||||||
|
# Convert coordinates to PWM values
|
||||||
|
precision = ((2 ** 16) - 1)
|
||||||
|
pwm_x : int = int(x / self.gcode_size[0] * precision)
|
||||||
|
pwm_y : int = int(y / self.gcode_size[1] * precision)
|
||||||
|
pen : int = 1 if z < 0 else 0
|
||||||
|
|
||||||
|
# Send PWM values to the serial port
|
||||||
|
print(f"Sending PWM values: X={pwm_x:<5}, Y={pwm_y:<5}, Pen={pen}")
|
||||||
|
self.serial.write(f"{pwm_x},{pwm_y},{pen}\n".encode())
|
||||||
|
|
||||||
|
def _position_reached(self) -> bool:
|
||||||
|
# Check if the position has been reached
|
||||||
|
return self.serial.readline().decode().strip() == "OK"
|
||||||
|
|
||||||
|
def _wait_for_position(self) -> None:
|
||||||
|
# Wait until the position is reached
|
||||||
|
while not self._position_reached():
|
||||||
|
pass
|
||||||
|
|
||||||
|
def run(self) -> None:
|
||||||
|
for pos in self.positions:
|
||||||
|
self._send_position(pos)
|
||||||
|
self._wait_for_position()
|
||||||
|
print("All positions sent successfully.")
|
||||||
@@ -1,2 +1,3 @@
|
|||||||
pygame==2.6.1
|
pygame==2.6.1
|
||||||
pygcode==0.2.1
|
colorama==0.4.6
|
||||||
|
pyserial
|
||||||
26
set_pos.py
Executable file
26
set_pos.py
Executable file
@@ -0,0 +1,26 @@
|
|||||||
|
#! /usr/bin/env python3
|
||||||
|
import serial
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
parser = argparse.ArgumentParser(description="Set the position of the PWM driver.")
|
||||||
|
parser.add_argument("x", type=float, help="X coordinate [0 - 1]")
|
||||||
|
parser.add_argument("y", type=float, help="Y coordinate [0 - 1]")
|
||||||
|
parser.add_argument("pen", type=int, help="pen down (True) or pen up (False)")
|
||||||
|
parser.add_argument("-p", "--port", type=str, required=True, help="Serial port")
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
# Open the serial port
|
||||||
|
ser = serial.Serial(args.port, 115200)
|
||||||
|
|
||||||
|
# Saturate values to [0, 1]
|
||||||
|
args.x = int(max(0, min(1, args.x)) * 0xFFFF)
|
||||||
|
args.y = int(max(0, min(1, args.y)) * 0xFFFF)
|
||||||
|
args.z = int(max(0, min(1, args.pen)))
|
||||||
|
|
||||||
|
# Send the position
|
||||||
|
print(f"{args.x},{args.y},{args.z}\n")
|
||||||
|
ser.write(f"{args.x},{args.y},{args.z}\n".encode())
|
||||||
|
|
||||||
|
# Close the serial port
|
||||||
|
ser.close()
|
||||||
3669
test/gothenburg.gcode
Normal file
3669
test/gothenburg.gcode
Normal file
File diff suppressed because it is too large
Load Diff
@@ -6,119 +6,206 @@ M3
|
|||||||
(Header end.)
|
(Header end.)
|
||||||
G21 (All units in mm)
|
G21 (All units in mm)
|
||||||
|
|
||||||
(Start cutting path id: path1471)
|
(Start cutting path id: path686)
|
||||||
(Change tool to Cylindrical cutter)
|
(Change tool to Cylindrical cutter)
|
||||||
|
|
||||||
G00 Z4.000000
|
G00 Z4.000000
|
||||||
G00 X40.792992 Y80.926340
|
G00 X14.552637 Y93.606430
|
||||||
|
|
||||||
G01 Z-0.100000 F100.0(Penetrate)
|
G01 Z-0.100000 F100.0(Penetrate)
|
||||||
G03 X48.432275 Y88.140738 Z-0.100000 I-204.578799 J224.279063 F400.000000
|
G02 X20.744531 Y97.132218 Z-0.100000 I58.837019 J-96.128067 F400.000000
|
||||||
G03 X53.994514 Y93.810363 Z-0.100000 I-133.160993 J136.202090
|
G02 X25.716552 Y99.525614 Z-0.100000 I34.485847 J-65.279503
|
||||||
G03 X59.272395 Y99.729942 Z-0.100000 I-107.634090 J101.278949
|
G02 X30.860300 Y101.491015 Z-0.100000 I23.790996 J-54.550899
|
||||||
G03 X62.820468 Y104.228711 Z-0.100000 I-65.304081 J55.152310
|
G02 X34.959887 Y102.600926 Z-0.100000 I12.260142 J-37.158180
|
||||||
G03 X65.994164 Y108.976904 Z-0.100000 I-51.047939 J37.555235
|
G02 X39.150265 Y103.209091 Z-0.100000 I6.697716 J-31.408261
|
||||||
G03 X67.828284 Y112.451877 Z-0.100000 I-28.758974 J17.400746
|
G02 X42.532580 Y103.224539 Z-0.100000 I1.795934 J-22.932442
|
||||||
G03 X69.150010 Y116.118517 Z-0.100000 I-21.870192 J9.955166
|
G02 X45.870181 Y102.713250 Z-0.100000 I-1.404588 J-20.318145
|
||||||
G03 X69.575390 Y118.750352 Z-0.100000 I-12.328848 J3.342987
|
G02 X48.684570 Y101.788627 Z-0.100000 I-4.188822 J-17.495591
|
||||||
G03 X69.368199 Y121.376336 Z-0.100000 I-9.811238 J0.547056
|
G02 X51.317759 Y100.411842 Z-0.100000 I-7.068443 J-16.725319
|
||||||
G03 X68.619214 Y123.394630 Z-0.100000 I-7.424736 J-1.607186
|
G02 X53.665796 Y98.685361 Z-0.100000 I-11.078526 J-17.526859
|
||||||
G03 X67.328874 Y125.148383 Z-0.100000 I-7.014669 J-3.809540
|
G02 X55.775079 Y96.652958 Z-0.100000 I-15.188138 J-17.873400
|
||||||
G03 X65.517184 Y126.655202 Z-0.100000 I-7.995064 J-7.770148
|
G02 X57.726196 Y94.306916 Z-0.100000 I-23.584596 J-21.598798
|
||||||
G03 X63.423291 Y127.812114 Z-0.100000 I-7.988995 J-11.985955
|
G02 X59.470711 Y91.791387 Z-0.100000 I-30.810456 J-23.229671
|
||||||
G03 X60.826730 Y128.802563 Z-0.100000 I-9.942260 J-22.165825
|
G02 X61.115709 Y89.045465 Z-0.100000 I-50.136040 J-31.900659
|
||||||
G03 X58.130482 Y129.528270 Z-0.100000 I-9.541314 J-30.077639
|
G02 X62.630031 Y86.220124 Z-0.100000 I-67.202070 J-37.837378
|
||||||
G03 X55.105279 Y130.107203 Z-0.100000 I-11.295310 J-50.829803
|
G02 X64.084273 Y83.293181 Z-0.100000 I-144.036213 J-73.388621
|
||||||
G03 X52.049800 Y130.526407 Z-0.100000 I-10.577428 J-65.751531
|
G02 X65.494590 Y80.343272 Z-0.100000 I-291.514429 J-141.180087
|
||||||
G03 X48.910261 Y130.839617 Z-0.100000 I-12.954376 J-113.959914
|
G03 X66.881828 Y77.442236 Z-0.100000 I283.572929 J133.817113
|
||||||
G03 X45.762044 Y131.079031 Z-0.100000 I-13.816738 J-160.866844
|
G03 X68.313824 Y74.564333 Z-0.100000 I137.241882 J66.494060
|
||||||
G03 X42.799102 Y131.270295 Z-0.100000 I-59.054412 J-891.785707
|
G03 X69.758311 Y71.884805 Z-0.100000 I61.141728 J31.231317
|
||||||
G02 X39.833939 Y131.464707 Z-0.100000 I34.926137 J555.401921
|
G03 X71.336939 Y69.288112 Z-0.100000 I44.576782 J25.321713
|
||||||
G02 X37.329233 Y131.669732 Z-0.100000 I6.322592 J92.642654
|
G03 X72.963662 Y67.013060 Z-0.100000 I26.152579 J16.980690
|
||||||
G02 X34.832837 Y131.966743 Z-0.100000 I5.148114 J53.909978
|
G03 X74.802248 Y64.922485 Z-0.100000 I19.649002 J15.426825
|
||||||
G02 X33.058081 Y132.308419 Z-0.100000 I2.627877 J18.429995
|
G03 X76.747819 Y63.219174 Z-0.100000 I12.369484 J12.165982
|
||||||
G02 X31.376807 Y132.877795 Z-0.100000 I2.394198 J9.836617
|
G03 X78.923535 Y61.857370 Z-0.100000 I9.054792 J12.047641
|
||||||
G02 X30.543074 Y133.456849 Z-0.100000 I1.066724 J2.425631
|
G03 X81.360720 Y60.895321 Z-0.100000 I6.109585 J11.909471
|
||||||
G02 X30.160248 Y134.253900 Z-0.100000 I0.998202 J0.969902
|
G03 X83.931304 Y60.421258 Z-0.100000 I3.758224 J13.172327
|
||||||
G02 X30.341642 Y135.385514 Z-0.100000 I2.033035 J0.254456
|
G03 X87.052305 Y60.433674 Z-0.100000 I1.492311 J17.147166
|
||||||
G02 X31.053355 Y136.462075 Z-0.100000 I4.128165 J-1.955590
|
G03 X90.141616 Y60.965854 Z-0.100000 I-1.957952 J20.598780
|
||||||
G02 X33.011212 Y138.364908 Z-0.100000 I13.851663 J-12.293556
|
G03 X94.072512 Y62.226406 Z-0.100000 I-7.883990 J31.344689
|
||||||
G02 X35.209343 Y140.058106 Z-0.100000 I21.730814 J-25.937792
|
G03 X97.849430 Y63.933050 Z-0.100000 I-15.102771 J38.456045
|
||||||
G02 X39.109213 Y142.665522 Z-0.100000 I52.049120 J-73.628840
|
G03 X102.671280 Y66.665690 Z-0.100000 I-30.887708 J60.123069
|
||||||
G02 X43.215542 Y145.015461 Z-0.100000 I29.025488 J-45.956988
|
G02 X107.455492 Y69.516107 Z-0.100000 I76.319751 J-122.656834
|
||||||
G02 X48.133576 Y147.339948 Z-0.100000 I35.918327 J-69.629317
|
G02 X111.778145 Y71.864657 Z-0.100000 I59.849304 J-105.004055
|
||||||
G02 X53.194572 Y149.346402 Z-0.100000 I36.693592 J-85.168337
|
G02 X116.195789 Y74.026840 Z-0.100000 I50.953186 J-98.510484
|
||||||
G02 X58.948615 Y151.278535 Z-0.100000 I42.902754 J-118.233694
|
G02 X120.197678 Y75.765423 Z-0.100000 I39.542572 J-85.544426
|
||||||
G02 X64.785575 Y152.949199 Z-0.100000 I42.582637 J-137.743082
|
G02 X124.277762 Y77.309185 Z-0.100000 I32.945222 J-80.908914
|
||||||
G02 X71.161336 Y154.508415 Z-0.100000 I46.820418 J-177.637487
|
G02 X127.992363 Y78.503646 Z-0.100000 I25.153027 J-71.849106
|
||||||
G02 X77.586835 Y155.850497 Z-0.100000 I44.960072 J-199.202994
|
G02 X131.764395 Y79.500062 Z-0.100000 I20.181063 J-68.759565
|
||||||
G02 X84.378744 Y157.056719 Z-0.100000 I46.254865 J-240.723707
|
G02 X135.224685 Y80.214984 Z-0.100000 I14.823846 J-63.017244
|
||||||
G02 X98.134017 Y158.945187 Z-0.100000 I44.256544 J-271.317302
|
G02 X138.719390 Y80.736201 Z-0.100000 I10.923189 J-61.262385
|
||||||
G02 X112.255639 Y160.217127 Z-0.100000 I36.838985 J-329.973901
|
G02 X141.957129 Y81.035094 Z-0.100000 I7.031183 J-58.479198
|
||||||
G02 X126.425918 Y160.894096 Z-0.100000 I23.405641 J-341.281719
|
G02 X145.206983 Y81.153633 Z-0.100000 I3.741895 J-57.979350
|
||||||
G02 X139.435338 Y160.976811 Z-0.100000 I8.507921 J-315.023673
|
G02 X148.252179 Y81.099633 Z-0.100000 I0.492298 J-58.128277
|
||||||
G02 X152.452978 Y160.486372 Z-0.100000 I-3.981081 J-278.676949
|
G02 X151.291365 Y80.887398 Z-0.100000 I-2.594382 J-59.017970
|
||||||
G02 X162.773882 Y159.552821 Z-0.100000 I-10.832870 J-177.281484
|
G02 X154.172321 Y80.544259 Z-0.100000 I-6.004970 J-62.682596
|
||||||
G02 X167.868820 Y158.845212 Z-0.100000 I-16.454201 J-137.170051
|
G02 X157.036011 Y80.071812 Z-0.100000 I-9.343840 J-65.551964
|
||||||
G02 X172.020233 Y158.089777 Z-0.100000 I-14.075692 J-89.135966
|
G02 X159.780039 Y79.504629 Z-0.100000 I-14.036409 J-74.829451
|
||||||
G02 X176.124440 Y157.112858 Z-0.100000 I-14.065191 J-68.200025
|
G02 X162.503404 Y78.841104 Z-0.100000 I-18.436483 J-81.591141
|
||||||
G02 X179.127309 Y156.162209 Z-0.100000 I-9.644364 J-35.682199
|
G02 X165.137818 Y78.116401 Z-0.100000 I-27.191313 J-103.995462
|
||||||
G02 X181.999539 Y154.907314 Z-0.100000 I-8.558857 J-23.504143
|
G02 X167.755226 Y77.329975 Z-0.100000 I-35.376756 J-122.491044
|
||||||
G02 X183.702116 Y153.797249 Z-0.100000 I-4.509523 J-8.777248
|
G02 X170.308142 Y76.515232 Z-0.100000 I-63.095750 J-202.111153
|
||||||
G02 X184.969965 Y152.342594 Z-0.100000 I-3.529109 J-4.355745
|
G02 X172.852727 Y75.673769 Z-0.100000 I-100.985659 J-309.649100
|
||||||
G02 X185.351659 Y151.022027 Z-0.100000 I-2.265939 J-1.370388
|
G03 X175.353497 Y74.836779 Z-0.100000 I824.726160 J2459.974416
|
||||||
G02 X185.038181 Y149.681813 Z-0.100000 I-2.796666 J-0.052626
|
G03 X177.856967 Y74.008305 Z-0.100000 I145.131966 J434.360678
|
||||||
G02 X183.682942 Y147.863676 Z-0.100000 I-6.233159 J3.232032
|
G03 X180.336368 Y73.216701 Z-0.100000 I52.878481 J161.343222
|
||||||
G02 X181.831384 Y146.382057 Z-0.100000 I-8.852518 J9.165118
|
G03 X182.828867 Y72.469528 Z-0.100000 I38.111423 J122.605193
|
||||||
G02 X178.302970 Y144.349327 Z-0.100000 I-18.966475 J28.843345
|
G03 X185.319239 Y71.790655 Z-0.100000 I23.905804 J82.788507
|
||||||
G03 X170.928466 Y140.650922 Z-0.100000 I1526.290230 J-3052.576402
|
G03 X187.829219 Y71.193050 Z-0.100000 I18.410824 J71.756814
|
||||||
G03 X164.440169 Y137.333509 Z-0.100000 I249.035894 J-495.075649
|
G03 X190.364594 Y70.694298 Z-0.100000 I12.556310 J57.135618
|
||||||
G03 X158.009538 Y133.906624 Z-0.100000 I161.452019 J-310.715630
|
G03 X192.918913 Y70.313651 Z-0.100000 I9.134546 J52.536396
|
||||||
G03 X152.642644 Y130.843877 Z-0.100000 I79.851784 J-146.158965
|
G03 X195.534920 Y70.063287 Z-0.100000 I5.730078 J46.080297
|
||||||
G03 X147.422441 Y127.548628 Z-0.100000 I60.865266 J-102.202823
|
G03 X198.159586 Y69.965048 Z-0.100000 I2.965597 J44.121682
|
||||||
G03 X143.397120 Y124.617338 Z-0.100000 I34.264407 J-51.282217
|
G03 X200.892700 Y70.033280 Z-0.100000 I0.322653 J41.849195
|
||||||
G03 X139.691193 Y121.328139 Z-0.100000 I27.429682 J-34.637241
|
G03 X203.634685 Y70.214064 Z-0.100000 I-9.642083 J167.128071
|
||||||
G03 X137.190317 Y118.390799 Z-0.100000 I16.300280 J-16.411494
|
G03 X206.734190 Y70.468208 Z-0.100000 I-14.808021 J199.624135
|
||||||
G03 X136.147741 Y116.762747 Z-0.100000 I15.047170 J-10.783800
|
G03 X209.828711 Y70.768943 Z-0.100000 I-19.054664 J212.141427
|
||||||
G03 X135.378538 Y115.195314 Z-0.100000 I12.419279 J-7.067096
|
G03 X213.185728 Y71.144851 Z-0.100000 I-23.944887 J229.015273
|
||||||
G03 X134.818551 Y113.546449 Z-0.100000 I11.882467 J-4.955048
|
G03 X216.536369 Y71.569433 Z-0.100000 I-27.820491 J232.982259
|
||||||
G03 X134.508961 Y111.901168 Z-0.100000 I10.983562 J-2.918529
|
G03 X220.054927 Y72.068144 Z-0.100000 I-31.235128 J233.035128
|
||||||
G03 X134.446462 Y110.229975 Z-0.100000 I11.105406 J-1.252081
|
G03 X223.565116 Y72.620309 Z-0.100000 I-34.247524 J229.149691
|
||||||
G03 X134.642425 Y108.475476 Z-0.100000 I11.976148 J0.449444
|
G03 X227.149400 Y73.243018 Z-0.100000 I-35.615483 J215.627772
|
||||||
G03 X135.084854 Y106.763614 Z-0.100000 I12.795729 J2.393940
|
G03 X230.722353 Y73.926542 Z-0.100000 I-37.577673 J206.108108
|
||||||
G03 X135.839772 Y104.885352 Z-0.100000 I15.682336 J5.212257
|
G03 X234.276760 Y74.674407 Z-0.100000 I-36.862694 J184.019161
|
||||||
G03 X136.806014 Y103.101413 Z-0.100000 I17.313031 J8.223685
|
G03 X237.815350 Y75.493254 Z-0.100000 I-37.806210 J171.432212
|
||||||
G03 X138.161841 Y101.097907 Z-0.100000 I22.636570 J13.858273
|
G03 X241.244620 Y76.367245 Z-0.100000 I-35.310162 J145.710840
|
||||||
G03 X139.683381 Y99.212258 Z-0.100000 I25.292769 J18.852177
|
G03 X244.651119 Y77.325701 Z-0.100000 I-35.390941 J132.317698
|
||||||
G03 X141.669474 Y97.080257 Z-0.100000 I33.649979 J29.355966
|
G03 X247.860593 Y78.326465 Z-0.100000 I-31.591268 J106.960795
|
||||||
G03 X145.967245 Y93.175631 Z-0.100000 I40.638606 J40.412826
|
G03 X251.036164 Y79.429240 Z-0.100000 I-31.024541 J94.462390
|
||||||
G03 X152.484790 Y88.222790 Z-0.100000 I70.154427 J85.552944
|
G03 X253.932293 Y80.556999 Z-0.100000 I-26.474034 J72.268933
|
||||||
G02 X155.786747 Y85.783852 Z-0.100000 I-50.527300 J-71.861035
|
G03 X256.775961 Y81.809146 Z-0.100000 I-25.498067 J61.762086
|
||||||
G02 X158.272013 Y83.745413 Z-0.100000 I-35.961052 J-46.377969
|
G03 X259.267331 Y83.063781 Z-0.100000 I-20.772732 J44.350028
|
||||||
G02 X160.624685 Y81.561427 Z-0.100000 I-31.023158 J-35.778517
|
G03 X261.673924 Y84.469733 Z-0.100000 I-19.631861 J36.366877
|
||||||
G02 X162.291579 Y79.765445 Z-0.100000 I-21.312713 J-21.452369
|
G03 X263.673323 Y85.851744 Z-0.100000 I-15.307078 J24.282539
|
||||||
G02 X163.783343 Y77.829366 Z-0.100000 I-18.176492 J-15.547879
|
G03 X265.530243 Y87.411006 Z-0.100000 I-14.246357 J18.851271
|
||||||
G02 X164.735875 Y76.254112 Z-0.100000 I-12.308977 J-8.518667
|
G03 X266.957880 Y88.925821 Z-0.100000 I-10.886437 J11.690065
|
||||||
G02 X165.458550 Y74.570007 Z-0.100000 I-10.555749 J-5.526741
|
G03 X268.146784 Y90.619795 Z-0.100000 I-10.156820 J8.392689
|
||||||
G02 X165.797289 Y73.182637 Z-0.100000 I-7.613170 J-2.593859
|
G03 X268.928616 Y92.290945 Z-0.100000 I-8.308777 J4.905647
|
||||||
G02 X165.865693 Y71.761139 Z-0.100000 I-6.876266 J-1.043289
|
G03 X269.357297 Y94.072485 Z-0.100000 I-8.181325 J2.910968
|
||||||
G02 X165.668206 Y70.522244 Z-0.100000 I-6.052550 J0.329623
|
G03 X269.393144 Y95.952050 Z-0.100000 I-8.386143 J1.100063
|
||||||
G02 X165.220071 Y69.344543 Z-0.100000 I-5.985404 J1.603435
|
G03 X269.027656 Y97.799340 Z-0.100000 I-9.115328 J-0.843674
|
||||||
G02 X164.541014 Y68.244159 Z-0.100000 I-6.614812 J3.322342
|
G03 X268.159077 Y99.914069 Z-0.100000 I-11.976068 J-3.683172
|
||||||
G02 X162.714220 Y66.399179 Z-0.100000 I-7.455324 J5.554954
|
G03 X266.946743 Y101.867828 Z-0.100000 I-13.731658 J-7.167668
|
||||||
G02 X160.061850 Y64.719806 Z-0.100000 I-11.086716 J14.575914
|
G03 X265.034028 Y104.181934 Z-0.100000 I-19.881289 J-14.485266
|
||||||
G02 X157.151071 Y63.434187 Z-0.100000 I-11.691140 J22.532017
|
G03 X262.873021 Y106.280809 Z-0.100000 I-22.835912 J-21.349997
|
||||||
G02 X153.898891 Y62.379372 Z-0.100000 I-14.952321 J40.559713
|
G03 X259.825610 Y108.760580 Z-0.100000 I-32.852748 J-37.260623
|
||||||
G02 X150.566625 Y61.558271 Z-0.100000 I-14.300496 J50.863354
|
G03 X256.476576 Y110.709846 Z-0.100000 I-10.010231 J-13.346960
|
||||||
G02 X147.591231 Y60.992650 Z-0.100000 I-14.791279 J69.699412
|
G03 X252.773344 Y111.883993 Z-0.100000 I-7.493702 J-17.207922
|
||||||
G02 X144.574010 Y60.546979 Z-0.100000 I-12.674394 J75.370292
|
G03 X248.877241 Y112.327664 Z-0.100000 I-4.407126 J-21.372573
|
||||||
G02 X142.677966 Y60.329435 Z-0.100000 I-9.678879 J75.986377
|
G03 X244.450008 Y112.121603 Z-0.100000 I-0.742684 J-31.706144
|
||||||
G02 X141.579387 Y60.224555 Z-0.100000 I-8.496644 J83.193018
|
G03 X240.060530 Y111.353088 Z-0.100000 I4.553065 J-38.925229
|
||||||
G02 X140.698190 Y60.159520 Z-0.100000 I-2.620904 J29.509849
|
G03 X235.163093 Y109.981508 Z-0.100000 I13.543583 J-57.788781
|
||||||
G01 X40.792992 Y80.926340 Z-0.100000
|
G03 X230.378159 Y108.229403 Z-0.100000 I22.565424 J-69.035121
|
||||||
|
G03 X225.220090 Y105.971807 Z-0.100000 I40.057628 J-98.543426
|
||||||
|
G03 X220.174534 Y103.464869 Z-0.100000 I54.183655 J-115.382898
|
||||||
|
G03 X214.928487 Y100.600598 Z-0.100000 I84.046615 J-160.171681
|
||||||
|
G03 X209.770717 Y97.577215 Z-0.100000 I106.036659 J-186.805411
|
||||||
|
G03 X204.595777 Y94.375981 Z-0.100000 I159.527010 J-263.666062
|
||||||
|
G03 X199.478162 Y91.081669 Z-0.100000 I201.070883 J-317.979798
|
||||||
|
G03 X194.529447 Y87.806053 Z-0.100000 I348.426084 J-531.768904
|
||||||
|
G03 X189.605017 Y84.491293 Z-0.100000 I534.035069 J-798.681601
|
||||||
|
G02 X185.036990 Y81.398913 Z-0.100000 I-3409.804231 J5032.001950
|
||||||
|
G02 X180.458155 Y78.318762 Z-0.100000 I-623.481769 J921.900652
|
||||||
|
G02 X176.425895 Y75.662661 Z-0.100000 I-186.252784 J278.363925
|
||||||
|
G02 X172.343973 Y73.079173 Z-0.100000 I-119.461839 J184.233742
|
||||||
|
G02 X169.003652 Y71.105394 Z-0.100000 I-52.095598 J84.350515
|
||||||
|
G02 X165.571823 Y69.298462 Z-0.100000 I-32.343612 J57.266406
|
||||||
|
G02 X163.077751 Y68.235212 Z-0.100000 I-11.428252 J23.350514
|
||||||
|
G02 X160.502116 Y67.547415 Z-0.100000 I-5.104505 J13.948698
|
||||||
|
G02 X158.955683 Y67.560212 Z-0.100000 I-0.737926 J4.270941
|
||||||
|
G02 X157.731476 Y68.200123 Z-0.100000 I0.444587 J2.341498
|
||||||
|
G02 X156.944937 Y69.588495 Z-0.100000 I2.023651 J2.063417
|
||||||
|
G02 X156.801982 Y71.348238 Z-0.100000 I5.571122 J1.338259
|
||||||
|
G02 X157.353005 Y74.828158 Z-0.100000 I21.087233 J-1.555446
|
||||||
|
G02 X158.370785 Y78.264326 Z-0.100000 I36.642233 J-8.984475
|
||||||
|
G02 X160.487376 Y83.787300 Z-0.100000 I91.589403 J-31.933101
|
||||||
|
G02 X162.889369 Y89.212416 Z-0.100000 I134.487773 J-56.300725
|
||||||
|
G02 X166.655540 Y96.974020 Z-0.100000 I267.631027 J-125.068347
|
||||||
|
G03 X170.453824 Y104.728830 Z-0.100000 I-353.386875 J177.895474
|
||||||
|
G03 X173.157092 Y110.620878 Z-0.100000 I-203.339069 J96.858011
|
||||||
|
G03 X175.655698 Y116.592772 Z-0.100000 I-151.906226 J67.065324
|
||||||
|
G03 X177.230787 Y120.906722 Z-0.100000 I-80.003800 J31.655140
|
||||||
|
G03 X178.518148 Y125.298438 Z-0.100000 I-56.752677 J19.020677
|
||||||
|
G03 X179.092855 Y128.259078 Z-0.100000 I-26.514778 J6.683036
|
||||||
|
G03 X179.249550 Y131.234152 Z-0.100000 I-17.602420 J2.418768
|
||||||
|
G03 X178.959525 Y133.105472 Z-0.100000 I-7.748214 J-0.242714
|
||||||
|
G03 X178.164821 Y134.770613 Z-0.100000 I-5.274347 J-1.495021
|
||||||
|
G03 X177.047028 Y135.873431 Z-0.100000 I-3.627994 J-2.559367
|
||||||
|
G03 X175.594363 Y136.576383 Z-0.100000 I-3.048814 J-4.447978
|
||||||
|
G03 X173.571592 Y136.990480 Z-0.100000 I-3.105214 J-10.020832
|
||||||
|
G03 X171.471477 Y137.068245 Z-0.100000 I-1.635210 J-15.763692
|
||||||
|
G03 X168.749449 Y136.884146 Z-0.100000 I1.048042 J-35.711634
|
||||||
|
G03 X166.037085 Y136.527390 Z-0.100000 I5.761018 J-54.289385
|
||||||
|
G03 X162.796828 Y135.981956 Z-0.100000 I23.329119 J-148.488603
|
||||||
|
G03 X159.565658 Y135.385276 Z-0.100000 I59.156603 J-329.394985
|
||||||
|
G02 X155.929958 Y134.711435 Z-0.100000 I-80.995633 J426.866156
|
||||||
|
G02 X152.288355 Y134.082554 Z-0.100000 I-41.132700 J227.325234
|
||||||
|
G02 X148.365069 Y133.500111 Z-0.100000 I-20.596158 J125.229171
|
||||||
|
G02 X144.427460 Y133.053734 Z-0.100000 I-13.792412 J104.075983
|
||||||
|
G02 X140.318392 Y132.775508 Z-0.100000 I-7.322865 J77.668032
|
||||||
|
G02 X136.205438 Y132.728765 Z-0.100000 I-2.839383 J68.865364
|
||||||
|
G02 X132.006156 Y132.965154 Z-0.100000 I1.029488 J55.704941
|
||||||
|
G02 X127.846119 Y133.531548 Z-0.100000 I4.767945 J50.579969
|
||||||
|
G02 X123.644591 Y134.496575 Z-0.100000 I7.714789 J43.217395
|
||||||
|
G02 X119.569924 Y135.877058 Z-0.100000 I11.283147 J40.007304
|
||||||
|
G02 X115.449927 Y137.797297 Z-0.100000 I14.557774 J36.614621
|
||||||
|
G02 X111.583891 Y140.175584 Z-0.100000 I18.672319 J34.684253
|
||||||
|
G02 X107.638393 Y143.294847 Z-0.100000 I24.065426 J34.494836
|
||||||
|
G02 X104.081169 Y146.849471 Z-0.100000 I29.795594 J33.374617
|
||||||
|
G02 X100.426220 Y151.416750 Z-0.100000 I39.923690 J35.694859
|
||||||
|
G03 X96.861751 Y156.067796 Z-0.100000 I-70.859008 J-50.613537
|
||||||
|
G03 X93.897268 Y159.392445 Z-0.100000 I-42.365964 J-34.792383
|
||||||
|
G03 X90.647615 Y162.421331 Z-0.100000 I-30.882655 J-29.875911
|
||||||
|
G03 X87.974250 Y164.392723 Z-0.100000 I-16.928804 J-20.158463
|
||||||
|
G03 X85.062213 Y165.954787 Z-0.100000 I-11.208750 J-17.400236
|
||||||
|
G03 X82.631681 Y166.757136 Z-0.100000 I-5.489126 J-12.545506
|
||||||
|
G03 X80.100449 Y167.054290 Z-0.100000 I-2.630925 J-11.481487
|
||||||
|
G03 X77.844074 Y166.825240 Z-0.100000 I-0.087721 J-10.364200
|
||||||
|
G03 X75.677709 Y166.114652 Z-0.100000 I2.251124 J-10.520571
|
||||||
|
G03 X73.585940 Y164.936589 Z-0.100000 I5.495451 J-12.203832
|
||||||
|
G03 X71.703619 Y163.417209 Z-0.100000 I8.984648 J-13.056514
|
||||||
|
G03 X69.831793 Y161.430738 Z-0.100000 I15.706928 J-16.675572
|
||||||
|
G03 X68.181100 Y159.244563 Z-0.100000 I21.305085 J-17.802887
|
||||||
|
G03 X66.556147 Y156.647241 Z-0.100000 I33.052975 J-22.485788
|
||||||
|
G03 X65.116782 Y153.938128 Z-0.100000 I41.144863 J-23.597379
|
||||||
|
G03 X63.733513 Y150.925653 Z-0.100000 I58.201905 J-28.548995
|
||||||
|
G03 X62.495117 Y147.849036 Z-0.100000 I68.612114 J-29.405211
|
||||||
|
G03 X61.338406 Y144.605528 Z-0.100000 I90.031382 J-33.935324
|
||||||
|
G03 X60.292015 Y141.323793 Z-0.100000 I101.989494 J-34.327319
|
||||||
|
G03 X59.345337 Y138.026420 Z-0.100000 I125.607517 J-37.846608
|
||||||
|
G03 X58.481449 Y134.705405 Z-0.100000 I137.732403 J-37.600881
|
||||||
|
G03 X57.728820 Y131.527885 Z-0.100000 I160.170234 J-39.615880
|
||||||
|
G03 X57.037175 Y128.335124 Z-0.100000 I170.460702 J-38.598048
|
||||||
|
G03 X56.463368 Y125.449476 Z-0.100000 I187.118800 J-38.708174
|
||||||
|
G03 X55.428496 Y119.545207 Z-0.100000 I195.277299 J-37.270122
|
||||||
|
G03 X54.883711 Y115.911257 Z-0.100000 I188.415983 J-30.104235
|
||||||
|
G03 X54.641709 Y114.113864 Z-0.100000 I168.111543 J-23.549653
|
||||||
|
G03 X54.518532 Y113.130555 Z-0.100000 I126.811802 J-16.384825
|
||||||
|
G03 X54.451092 Y112.564881 Z-0.100000 I135.732881 J-16.469000
|
||||||
|
G03 X54.402469 Y112.128198 Z-0.100000 I38.359439 J-4.492203
|
||||||
G00 Z4.000000
|
G00 Z4.000000
|
||||||
|
|
||||||
(End cutting path id: path1471)
|
(End cutting path id: path686)
|
||||||
|
|
||||||
|
|
||||||
(Footer)
|
(Footer)
|
||||||
|
|||||||
2188
test/test_arc.svg
2188
test/test_arc.svg
File diff suppressed because it is too large
Load Diff
|
Before Width: | Height: | Size: 100 KiB After Width: | Height: | Size: 14 KiB |
1561
test/test_hatch_fill.gcode
Normal file
1561
test/test_hatch_fill.gcode
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,6 @@
|
|||||||
import pygame
|
import pygame
|
||||||
|
import sys
|
||||||
|
from colorama import Fore, Style
|
||||||
|
|
||||||
class Visualizer:
|
class Visualizer:
|
||||||
def __init__(self, positions : list[tuple[float, float, float]], screen_dimensions : tuple[int, int], gcode_size : tuple[float, float]):
|
def __init__(self, positions : list[tuple[float, float, float]], screen_dimensions : tuple[int, int], gcode_size : tuple[float, float]):
|
||||||
@@ -30,6 +32,26 @@ class Visualizer:
|
|||||||
self.screen = pygame.display.set_mode(self.screen_dimensions)
|
self.screen = pygame.display.set_mode(self.screen_dimensions)
|
||||||
self.clock = pygame.time.Clock()
|
self.clock = pygame.time.Clock()
|
||||||
|
|
||||||
|
def _print_status(self) -> None:
|
||||||
|
normalized_x = self.prev_x / self.screen.get_width()
|
||||||
|
normalized_y = self.prev_y / self.screen.get_height()
|
||||||
|
pen_active = self.prev_z < 0
|
||||||
|
|
||||||
|
# Clear the terminal with ANSI code
|
||||||
|
print("\033c", end="")
|
||||||
|
|
||||||
|
# X-axis bar
|
||||||
|
x_bar = f"{Fore.GREEN}{'#'*int(normalized_x*100)}{Style.RESET_ALL}{' '*int((1.0-normalized_x)*100)}"
|
||||||
|
print(f"X: |{x_bar}| {(normalized_x*100):.2f}%")
|
||||||
|
|
||||||
|
# Y-axis bar
|
||||||
|
y_bar = f"{Fore.BLUE}{'#'*int(normalized_y*100)}{Style.RESET_ALL}{' '*int((1.0-normalized_y)*100)}"
|
||||||
|
print(f"Y: |{y_bar}| {(normalized_y*100):.2f}%")
|
||||||
|
|
||||||
|
# Pen status
|
||||||
|
pen_status = f"{Fore.GREEN}Active{Style.RESET_ALL}" if pen_active else f"{Fore.RED}Inactive{Style.RESET_ALL}"
|
||||||
|
print(f"Pen: {pen_status}")
|
||||||
|
|
||||||
def visualize(self) -> None:
|
def visualize(self) -> None:
|
||||||
running = True
|
running = True
|
||||||
while running:
|
while running:
|
||||||
@@ -61,5 +83,7 @@ class Visualizer:
|
|||||||
x1, y1, x2, y2 = drawn_line
|
x1, y1, x2, y2 = drawn_line
|
||||||
pygame.draw.line(self.screen, (255, 255, 255), (int(x1), int(y1)), (int(x2), int(y2)), 2)
|
pygame.draw.line(self.screen, (255, 255, 255), (int(x1), int(y1)), (int(x2), int(y2)), 2)
|
||||||
|
|
||||||
|
self._print_status()
|
||||||
|
|
||||||
pygame.display.flip()
|
pygame.display.flip()
|
||||||
self.clock.tick(60)
|
self.clock.tick(10)
|
||||||
Reference in New Issue
Block a user