- added support for G91 coordinates

- working in plotting the CNCjob generated with G91 coordinates
This commit is contained in:
Marius Stanciu 2019-09-04 17:41:17 +03:00
parent 28e31eb312
commit a2a3f1c1ed
4 changed files with 412 additions and 135 deletions

View File

@ -572,6 +572,7 @@ class App(QtCore.QObject):
"cncjob_annotation_fontcolor": self.ui.cncjob_defaults_form.cncjob_gen_group.annotation_fontcolor_entry, "cncjob_annotation_fontcolor": self.ui.cncjob_defaults_form.cncjob_gen_group.annotation_fontcolor_entry,
"cncjob_tooldia": self.ui.cncjob_defaults_form.cncjob_gen_group.tooldia_entry, "cncjob_tooldia": self.ui.cncjob_defaults_form.cncjob_gen_group.tooldia_entry,
"cncjob_coords_type": self.ui.cncjob_defaults_form.cncjob_gen_group.coords_type_radio,
"cncjob_coords_decimals": self.ui.cncjob_defaults_form.cncjob_gen_group.coords_dec_entry, "cncjob_coords_decimals": self.ui.cncjob_defaults_form.cncjob_gen_group.coords_dec_entry,
"cncjob_fr_decimals": self.ui.cncjob_defaults_form.cncjob_gen_group.fr_dec_entry, "cncjob_fr_decimals": self.ui.cncjob_defaults_form.cncjob_gen_group.fr_dec_entry,
"cncjob_steps_per_circle": self.ui.cncjob_defaults_form.cncjob_gen_group.steps_per_circle_entry, "cncjob_steps_per_circle": self.ui.cncjob_defaults_form.cncjob_gen_group.steps_per_circle_entry,
@ -961,6 +962,7 @@ class App(QtCore.QObject):
"cncjob_annotation_fontsize": 9, "cncjob_annotation_fontsize": 9,
"cncjob_annotation_fontcolor": '#990000', "cncjob_annotation_fontcolor": '#990000',
"cncjob_tooldia": 0.0393701, "cncjob_tooldia": 0.0393701,
"cncjob_coords_type": "G90",
"cncjob_coords_decimals": 4, "cncjob_coords_decimals": 4,
"cncjob_fr_decimals": 2, "cncjob_fr_decimals": 2,
"cncjob_steps_per_circle": 128, "cncjob_steps_per_circle": 128,

View File

@ -12,6 +12,8 @@ CAD program, and create G-Code for Isolation routing.
4.09.2019 4.09.2019
- started to work on support for G91 in Gcode (relative coordinates) - started to work on support for G91 in Gcode (relative coordinates)
- added support for G91 coordinates
- working in plotting the CNCjob generated with G91 coordinates
3.09.2019 3.09.2019

501
camlib.py
View File

@ -5039,8 +5039,9 @@ class CNCjob(Geometry):
self.unitcode = {"IN": "G20", "MM": "G21"} self.unitcode = {"IN": "G20", "MM": "G21"}
self.feedminutecode = "G94" self.feedminutecode = "G94"
self.absolutecode = "G90" # self.absolutecode = "G90"
self.relativecode = "G91" # self.incrementalcode = "G91"
self.coordinates_type = self.app.defaults["cncjob_coords_type"]
self.gcode = "" self.gcode = ""
self.gcode_parsed = None self.gcode_parsed = None
@ -5442,27 +5443,51 @@ class CNCjob(Geometry):
z_offset = 0 z_offset = 0
self.z_cut += z_offset self.z_cut += z_offset
# Drillling! self.coordinates_type = self.app.defaults["cncjob_coords_type"]
for k in node_list: if self.coordinates_type == "G90":
locx = locations[k][0] # Drillling! for Absolute coordinates type G90
locy = locations[k][1] for k in node_list:
locx = locations[k][0]
locy = locations[k][1]
gcode += self.doformat(p.rapid_code, x=locx, y=locy) gcode += self.doformat(p.rapid_code, x=locx, y=locy)
gcode += self.doformat(p.down_code, x=locx, y=locy) gcode += self.doformat(p.down_code, x=locx, y=locy)
measured_down_distance += abs(self.z_cut) + abs(self.z_move) measured_down_distance += abs(self.z_cut) + abs(self.z_move)
if self.f_retract is False: if self.f_retract is False:
gcode += self.doformat(p.up_to_zero_code, x=locx, y=locy) gcode += self.doformat(p.up_to_zero_code, x=locx, y=locy)
measured_up_to_zero_distance += abs(self.z_cut) measured_up_to_zero_distance += abs(self.z_cut)
measured_lift_distance += abs(self.z_move) measured_lift_distance += abs(self.z_move)
else: else:
measured_lift_distance += abs(self.z_cut) + abs(self.z_move) measured_lift_distance += abs(self.z_cut) + abs(self.z_move)
gcode += self.doformat(p.lift_code, x=locx, y=locy) gcode += self.doformat(p.lift_code, x=locx, y=locy)
measured_distance += abs(distance_euclidian(locx, locy, self.oldx, self.oldy)) measured_distance += abs(distance_euclidian(locx, locy, self.oldx, self.oldy))
self.oldx = locx self.oldx = locx
self.oldy = locy self.oldy = locy
else:
# Drillling! for Incremental coordinates type G91
for k in node_list:
locx = locations[k][0] - self.oldx
locy = locations[k][1] - self.oldy
gcode += self.doformat(p.rapid_code, x=locx, y=locy)
gcode += self.doformat(p.down_code, x=locx, y=locy)
measured_down_distance += abs(self.z_cut) + abs(self.z_move)
if self.f_retract is False:
gcode += self.doformat(p.up_to_zero_code, x=locx, y=locy)
measured_up_to_zero_distance += abs(self.z_cut)
measured_lift_distance += abs(self.z_move)
else:
measured_lift_distance += abs(self.z_cut) + abs(self.z_move)
gcode += self.doformat(p.lift_code, x=locx, y=locy)
measured_distance += abs(distance_euclidian(locx, locy, self.oldx, self.oldy))
self.oldx = locx
self.oldy = locy
else: else:
log.debug("camlib.CNCJob.generate_from_excellon_by_tool() --> " log.debug("camlib.CNCJob.generate_from_excellon_by_tool() --> "
"The loaded Excellon file has no drills ...") "The loaded Excellon file has no drills ...")
@ -5548,27 +5573,51 @@ class CNCjob(Geometry):
z_offset = 0 z_offset = 0
self.z_cut += z_offset self.z_cut += z_offset
# Drillling! self.coordinates_type = self.app.defaults["cncjob_coords_type"]
for k in node_list: if self.coordinates_type == "G90":
locx = locations[k][0] # Drillling! for Absolute coordinates type G90
locy = locations[k][1] for k in node_list:
locx = locations[k][0]
locy = locations[k][1]
gcode += self.doformat(p.rapid_code, x=locx, y=locy) gcode += self.doformat(p.rapid_code, x=locx, y=locy)
gcode += self.doformat(p.down_code, x=locx, y=locy) gcode += self.doformat(p.down_code, x=locx, y=locy)
measured_down_distance += abs(self.z_cut) + abs(self.z_move) measured_down_distance += abs(self.z_cut) + abs(self.z_move)
if self.f_retract is False: if self.f_retract is False:
gcode += self.doformat(p.up_to_zero_code, x=locx, y=locy) gcode += self.doformat(p.up_to_zero_code, x=locx, y=locy)
measured_up_to_zero_distance += abs(self.z_cut) measured_up_to_zero_distance += abs(self.z_cut)
measured_lift_distance += abs(self.z_move) measured_lift_distance += abs(self.z_move)
else: else:
measured_lift_distance += abs(self.z_cut) + abs(self.z_move) measured_lift_distance += abs(self.z_cut) + abs(self.z_move)
gcode += self.doformat(p.lift_code, x=locx, y=locy) gcode += self.doformat(p.lift_code, x=locx, y=locy)
measured_distance += abs(distance_euclidian(locx, locy, self.oldx, self.oldy)) measured_distance += abs(distance_euclidian(locx, locy, self.oldx, self.oldy))
self.oldx = locx self.oldx = locx
self.oldy = locy self.oldy = locy
else:
# Drillling! for Incremental coordinates type G91
for k in node_list:
locx = locations[k][0] - self.oldx
locy = locations[k][1] - self.oldy
gcode += self.doformat(p.rapid_code, x=locx, y=locy)
gcode += self.doformat(p.down_code, x=locx, y=locy)
measured_down_distance += abs(self.z_cut) + abs(self.z_move)
if self.f_retract is False:
gcode += self.doformat(p.up_to_zero_code, x=locx, y=locy)
measured_up_to_zero_distance += abs(self.z_cut)
measured_lift_distance += abs(self.z_move)
else:
measured_lift_distance += abs(self.z_cut) + abs(self.z_move)
gcode += self.doformat(p.lift_code, x=locx, y=locy)
measured_distance += abs(distance_euclidian(locx, locy, self.oldx, self.oldy))
self.oldx = locx
self.oldy = locy
else: else:
log.debug("camlib.CNCJob.generate_from_excellon_by_tool() --> " log.debug("camlib.CNCJob.generate_from_excellon_by_tool() --> "
"The loaded Excellon file has no drills ...") "The loaded Excellon file has no drills ...")
@ -5613,28 +5662,56 @@ class CNCjob(Geometry):
z_offset = 0 z_offset = 0
self.z_cut += z_offset self.z_cut += z_offset
# Drillling! self.coordinates_type = self.app.defaults["cncjob_coords_type"]
altPoints = [] if self.coordinates_type == "G90":
for point in points[tool]: # Drillling! for Absolute coordinates type G90
altPoints.append((point.coords.xy[0][0], point.coords.xy[1][0])) altPoints = []
for point in points[tool]:
altPoints.append((point.coords.xy[0][0], point.coords.xy[1][0]))
for point in self.optimized_travelling_salesman(altPoints): for point in self.optimized_travelling_salesman(altPoints):
gcode += self.doformat(p.rapid_code, x=point[0], y=point[1]) gcode += self.doformat(p.rapid_code, x=point[0], y=point[1])
gcode += self.doformat(p.down_code, x=point[0], y=point[1]) gcode += self.doformat(p.down_code, x=point[0], y=point[1])
measured_down_distance += abs(self.z_cut) + abs(self.z_move) measured_down_distance += abs(self.z_cut) + abs(self.z_move)
if self.f_retract is False: if self.f_retract is False:
gcode += self.doformat(p.up_to_zero_code, x=point[0], y=point[1]) gcode += self.doformat(p.up_to_zero_code, x=point[0], y=point[1])
measured_up_to_zero_distance += abs(self.z_cut) measured_up_to_zero_distance += abs(self.z_cut)
measured_lift_distance += abs(self.z_move) measured_lift_distance += abs(self.z_move)
else: else:
measured_lift_distance += abs(self.z_cut) + abs(self.z_move) measured_lift_distance += abs(self.z_cut) + abs(self.z_move)
gcode += self.doformat(p.lift_code, x=point[0], y=point[1]) gcode += self.doformat(p.lift_code, x=point[0], y=point[1])
measured_distance += abs(distance_euclidian(point[0], point[1], self.oldx, self.oldy)) measured_distance += abs(distance_euclidian(point[0], point[1], self.oldx, self.oldy))
self.oldx = point[0] self.oldx = point[0]
self.oldy = point[1] self.oldy = point[1]
else:
# Drillling! for Incremental coordinates type G91
altPoints = []
for point in points[tool]:
altPoints.append((point.coords.xy[0][0], point.coords.xy[1][0]))
for point in self.optimized_travelling_salesman(altPoints):
point[0] = point[0] - self.oldx
point[1] = point[1] - self.oldy
gcode += self.doformat(p.rapid_code, x=point[0], y=point[1])
gcode += self.doformat(p.down_code, x=point[0], y=point[1])
measured_down_distance += abs(self.z_cut) + abs(self.z_move)
if self.f_retract is False:
gcode += self.doformat(p.up_to_zero_code, x=point[0], y=point[1])
measured_up_to_zero_distance += abs(self.z_cut)
measured_lift_distance += abs(self.z_move)
else:
measured_lift_distance += abs(self.z_cut) + abs(self.z_move)
gcode += self.doformat(p.lift_code, x=point[0], y=point[1])
measured_distance += abs(distance_euclidian(point[0], point[1], self.oldx, self.oldy))
self.oldx = point[0]
self.oldy = point[1]
else: else:
log.debug("camlib.CNCJob.generate_from_excellon_by_tool() --> " log.debug("camlib.CNCJob.generate_from_excellon_by_tool() --> "
"The loaded Excellon file has no drills ...") "The loaded Excellon file has no drills ...")
@ -5864,7 +5941,7 @@ class CNCjob(Geometry):
# calculate the cut distance # calculate the cut distance
total_cut = total_cut + geo.length total_cut = total_cut + geo.length
self.gcode += self.create_gcode_single_pass(geo, extracut, tolerance) self.gcode += self.create_gcode_single_pass(geo, extracut, tolerance, old_point=current_pt)
# --------- Multi-pass --------- # --------- Multi-pass ---------
else: else:
@ -5879,7 +5956,7 @@ class CNCjob(Geometry):
total_cut += (geo.length * nr_cuts) total_cut += (geo.length * nr_cuts)
self.gcode += self.create_gcode_multi_pass(geo, extracut, tolerance, self.gcode += self.create_gcode_multi_pass(geo, extracut, tolerance,
postproc=p, current_point=current_pt) postproc=p, old_point=current_pt)
# calculate the total distance # calculate the total distance
total_travel = total_travel + abs(distance(pt1=current_pt, pt2=pt)) total_travel = total_travel + abs(distance(pt1=current_pt, pt2=pt))
@ -6157,7 +6234,7 @@ class CNCjob(Geometry):
if not multidepth: if not multidepth:
# calculate the cut distance # calculate the cut distance
total_cut += geo.length total_cut += geo.length
self.gcode += self.create_gcode_single_pass(geo, extracut, tolerance) self.gcode += self.create_gcode_single_pass(geo, extracut, tolerance, old_point=current_pt)
# --------- Multi-pass --------- # --------- Multi-pass ---------
else: else:
@ -6172,7 +6249,7 @@ class CNCjob(Geometry):
total_cut += (geo.length * nr_cuts) total_cut += (geo.length * nr_cuts)
self.gcode += self.create_gcode_multi_pass(geo, extracut, tolerance, self.gcode += self.create_gcode_multi_pass(geo, extracut, tolerance,
postproc=p, current_point=current_pt) postproc=p, old_point=current_pt)
# calculate the travel distance # calculate the travel distance
total_travel += abs(distance(pt1=current_pt, pt2=pt)) total_travel += abs(distance(pt1=current_pt, pt2=pt))
@ -6283,7 +6360,7 @@ class CNCjob(Geometry):
if pt != geo.coords[0] and pt == geo.coords[-1]: if pt != geo.coords[0] and pt == geo.coords[-1]:
geo.coords = list(geo.coords)[::-1] geo.coords = list(geo.coords)[::-1]
self.gcode += self.create_soldepaste_gcode(geo, p=p) self.gcode += self.create_soldepaste_gcode(geo, p=p, old_point=current_pt)
current_pt = geo.coords[-1] current_pt = geo.coords[-1]
pt, geo = storage.nearest(current_pt) # Next pt, geo = storage.nearest(current_pt) # Next
@ -6298,13 +6375,23 @@ class CNCjob(Geometry):
return self.gcode return self.gcode
def create_soldepaste_gcode(self, geometry, p): def create_soldepaste_gcode(self, geometry, p, old_point=(0, 0)):
gcode = '' gcode = ''
path = geometry.coords path = geometry.coords
self.coordinates_type = self.app.defaults["cncjob_coords_type"]
if self.coordinates_type == "G90":
# For Absolute coordinates type G90
first_x = path[0][0]
first_y = path[0][1]
else:
# For Incremental coordinates type G91
first_x = path[0][0] - old_point[0]
first_y = path[0][1] - old_point[1]
if type(geometry) == LineString or type(geometry) == LinearRing: if type(geometry) == LineString or type(geometry) == LinearRing:
# Move fast to 1st point # Move fast to 1st point
gcode += self.doformat(p.rapid_code, x=path[0][0], y=path[0][1]) # Move to first point gcode += self.doformat(p.rapid_code, x=first_x, y=first_y) # Move to first point
# Move down to cutting depth # Move down to cutting depth
gcode += self.doformat(p.z_feedrate_code) gcode += self.doformat(p.z_feedrate_code)
@ -6316,8 +6403,20 @@ class CNCjob(Geometry):
gcode += self.doformat(p.feedrate_xy_code) gcode += self.doformat(p.feedrate_xy_code)
# Cutting... # Cutting...
prev_x = first_x
prev_y = first_y
for pt in path[1:]: for pt in path[1:]:
gcode += self.doformat(p.linear_code, x=pt[0], y=pt[1]) # Linear motion to point if self.coordinates_type == "G90":
# For Absolute coordinates type G90
next_x = pt[0]
next_y = pt[1]
else:
# For Incremental coordinates type G91
next_x = pt[0] - prev_x
next_y = pt[1] - prev_y
gcode += self.doformat(p.linear_code, x=next_x, y=next_y) # Linear motion to point
prev_x = next_x
prev_y = next_y
# Up to travelling height. # Up to travelling height.
gcode += self.doformat(p.spindle_off_code) # Stop dispensing gcode += self.doformat(p.spindle_off_code) # Stop dispensing
@ -6328,7 +6427,7 @@ class CNCjob(Geometry):
gcode += self.doformat(p.z_feedrate_code) gcode += self.doformat(p.z_feedrate_code)
gcode += self.doformat(p.lift_code) gcode += self.doformat(p.lift_code)
elif type(geometry) == Point: elif type(geometry) == Point:
gcode += self.doformat(p.linear_code, x=path[0][0], y=path[0][1]) # Move to first point gcode += self.doformat(p.linear_code, x=first_x, y=first_y) # Move to first point
gcode += self.doformat(p.feedrate_z_dispense_code) gcode += self.doformat(p.feedrate_z_dispense_code)
gcode += self.doformat(p.down_z_start_code) gcode += self.doformat(p.down_z_start_code)
@ -6345,18 +6444,18 @@ class CNCjob(Geometry):
gcode += self.doformat(p.lift_code) gcode += self.doformat(p.lift_code)
return gcode return gcode
def create_gcode_single_pass(self, geometry, extracut, tolerance): def create_gcode_single_pass(self, geometry, extracut, tolerance, old_point=(0, 0)):
# G-code. Note: self.linear2gcode() and self.point2gcode() will lower and raise the tool every time. # G-code. Note: self.linear2gcode() and self.point2gcode() will lower and raise the tool every time.
gcode_single_pass = '' gcode_single_pass = ''
if type(geometry) == LineString or type(geometry) == LinearRing: if type(geometry) == LineString or type(geometry) == LinearRing:
if extracut is False: if extracut is False:
gcode_single_pass = self.linear2gcode(geometry, tolerance=tolerance) gcode_single_pass = self.linear2gcode(geometry, tolerance=tolerance, old_point=old_point)
else: else:
if geometry.is_ring: if geometry.is_ring:
gcode_single_pass = self.linear2gcode_extra(geometry, tolerance=tolerance) gcode_single_pass = self.linear2gcode_extra(geometry, tolerance=tolerance, old_point=old_point)
else: else:
gcode_single_pass = self.linear2gcode(geometry, tolerance=tolerance) gcode_single_pass = self.linear2gcode(geometry, tolerance=tolerance, old_point=old_point)
elif type(geometry) == Point: elif type(geometry) == Point:
gcode_single_pass = self.point2gcode(geometry) gcode_single_pass = self.point2gcode(geometry)
else: else:
@ -6365,7 +6464,7 @@ class CNCjob(Geometry):
return gcode_single_pass return gcode_single_pass
def create_gcode_multi_pass(self, geometry, extracut, tolerance, postproc, current_point): def create_gcode_multi_pass(self, geometry, extracut, tolerance, postproc, old_point=(0, 0)):
gcode_multi_pass = '' gcode_multi_pass = ''
@ -6394,17 +6493,19 @@ class CNCjob(Geometry):
# is inconsequential. # is inconsequential.
if type(geometry) == LineString or type(geometry) == LinearRing: if type(geometry) == LineString or type(geometry) == LinearRing:
if extracut is False: if extracut is False:
gcode_multi_pass += self.linear2gcode(geometry, tolerance=tolerance, z_cut=depth, up=False) gcode_multi_pass += self.linear2gcode(geometry, tolerance=tolerance, z_cut=depth, up=False,
old_point=old_point)
else: else:
if geometry.is_ring: if geometry.is_ring:
gcode_multi_pass += self.linear2gcode_extra(geometry, tolerance=tolerance, z_cut=depth, gcode_multi_pass += self.linear2gcode_extra(geometry, tolerance=tolerance, z_cut=depth,
up=False) up=False, old_point=old_point)
else: else:
gcode_multi_pass += self.linear2gcode(geometry, tolerance=tolerance, z_cut=depth, up=False) gcode_multi_pass += self.linear2gcode(geometry, tolerance=tolerance, z_cut=depth, up=False,
old_point=old_point)
# Ignore multi-pass for points. # Ignore multi-pass for points.
elif type(geometry) == Point: elif type(geometry) == Point:
gcode_multi_pass += self.point2gcode(geometry) gcode_multi_pass += self.point2gcode(geometry, old_point=old_point)
break # Ignoring ... break # Ignoring ...
else: else:
log.warning("G-code generation not implemented for %s" % (str(type(geometry)))) log.warning("G-code generation not implemented for %s" % (str(type(geometry))))
@ -6420,7 +6521,7 @@ class CNCjob(Geometry):
geometry.coords = list(geometry.coords)[::-1] geometry.coords = list(geometry.coords)[::-1]
# Lift the tool # Lift the tool
gcode_multi_pass += self.doformat(postproc.lift_code, x=current_point[0], y=current_point[1]) gcode_multi_pass += self.doformat(postproc.lift_code, x=old_point[0], y=old_point[1])
return gcode_multi_pass return gcode_multi_pass
def codes_split(self, gline): def codes_split(self, gline):
@ -6692,43 +6793,134 @@ class CNCjob(Geometry):
else: else:
text = [] text = []
pos = [] pos = []
for geo in gcode_parsed: self.coordinates_type = self.app.defaults["cncjob_coords_type"]
if geo['kind'][0] == 'T': if self.coordinates_type == "G90":
current_position = geo['geom'].coords[0] # For Absolute coordinates type G90
if current_position not in pos: for geo in gcode_parsed:
pos.append(current_position) if geo['kind'][0] == 'T':
path_num += 1 current_position = geo['geom'].coords[0]
text.append(str(path_num)) if current_position not in pos:
current_position = geo['geom'].coords[-1] pos.append(current_position)
if current_position not in pos: path_num += 1
pos.append(current_position) text.append(str(path_num))
path_num += 1
text.append(str(path_num))
# plot the geometry of Excellon objects current_position = geo['geom'].coords[-1]
if self.origin_kind == 'excellon': if current_position not in pos:
try: pos.append(current_position)
poly = Polygon(geo['geom']) path_num += 1
except ValueError: text.append(str(path_num))
# if the geos are travel lines it will enter into Exception
# plot the geometry of Excellon objects
if self.origin_kind == 'excellon':
try:
poly = Polygon(geo['geom'])
except ValueError:
# if the geos are travel lines it will enter into Exception
poly = geo['geom'].buffer(distance=(tooldia / 1.99999999), resolution=self.steps_per_circle)
poly = poly.simplify(tool_tolerance)
else:
# plot the geometry of any objects other than Excellon
poly = geo['geom'].buffer(distance=(tooldia / 1.99999999), resolution=self.steps_per_circle) poly = geo['geom'].buffer(distance=(tooldia / 1.99999999), resolution=self.steps_per_circle)
poly = poly.simplify(tool_tolerance) poly = poly.simplify(tool_tolerance)
else:
# plot the geometry of any objects other than Excellon
poly = geo['geom'].buffer(distance=(tooldia / 1.99999999), resolution=self.steps_per_circle)
poly = poly.simplify(tool_tolerance)
if kind == 'all': if kind == 'all':
obj.add_shape(shape=poly, color=color[geo['kind'][0]][1], face_color=color[geo['kind'][0]][0], obj.add_shape(shape=poly, color=color[geo['kind'][0]][1], face_color=color[geo['kind'][0]][0],
visible=visible, layer=1 if geo['kind'][0] == 'C' else 2) visible=visible, layer=1 if geo['kind'][0] == 'C' else 2)
elif kind == 'travel': elif kind == 'travel':
if geo['kind'][0] == 'T':
obj.add_shape(shape=poly, color=color['T'][1], face_color=color['T'][0],
visible=visible, layer=2)
elif kind == 'cut':
if geo['kind'][0] == 'C':
obj.add_shape(shape=poly, color=color['C'][1], face_color=color['C'][0],
visible=visible, layer=1)
else:
# For Incremental coordinates type G91
current_x = gcode_parsed[0]['geom'].coords[0][0]
current_y = gcode_parsed[0]['geom'].coords[0][1]
old_pos = (
current_x,
current_y
)
for geo in gcode_parsed:
print(list(geo['geom'].coordsner))
if geo['kind'][0] == 'T': if geo['kind'][0] == 'T':
obj.add_shape(shape=poly, color=color['T'][1], face_color=color['T'][0], current_position = (
visible=visible, layer=2) geo['geom'].coords[0][0] + old_pos[0],
elif kind == 'cut': geo['geom'].coords[0][1] + old_pos[1]
if geo['kind'][0] == 'C': )
obj.add_shape(shape=poly, color=color['C'][1], face_color=color['C'][0], if current_position not in pos:
visible=visible, layer=1) pos.append(current_position)
path_num += 1
text.append(str(path_num))
delta = (
geo['geom'].coords[-1][0] - geo['geom'].coords[0][0],
geo['geom'].coords[-1][1] - geo['geom'].coords[0][1]
)
current_position = (
current_position[0] + geo['geom'].coords[-1][0],
current_position[1] + geo['geom'].coords[-1][1]
)
if current_position not in pos:
pos.append(current_position)
path_num += 1
text.append(str(path_num))
# plot the geometry of Excellon objects
if self.origin_kind == 'excellon':
if isinstance(geo['geom'], Point):
# if geo is Point
current_position = (
current_position[0] + geo['geom'].x,
current_position[1] + geo['geom'].y
)
poly = Polygon(Point(current_position))
elif isinstance(geo['geom'], LineString):
# if the geos are travel lines (LineStrings)
new_line_pts = []
old_line_pos = deepcopy(current_position)
for p in list(geo['geom'].coords):
current_position = (
current_position[0] + p[0],
current_position[1] + p[1]
)
new_line_pts.append(current_position)
old_line_pos = p
new_line = LineString(new_line_pts)
poly = new_line.buffer(distance=(tooldia / 1.99999999), resolution=self.steps_per_circle)
poly = poly.simplify(tool_tolerance)
else:
# plot the geometry of any objects other than Excellon
new_line_pts = []
old_line_pos = deepcopy(current_position)
for p in list(geo['geom'].coords):
current_position = (
current_position[0] + p[0],
current_position[1] + p[1]
)
new_line_pts.append(current_position)
old_line_pos = p
new_line = LineString(new_line_pts)
poly = new_line.buffer(distance=(tooldia / 1.99999999), resolution=self.steps_per_circle)
poly = poly.simplify(tool_tolerance)
old_pos = deepcopy(current_position)
if kind == 'all':
obj.add_shape(shape=poly, color=color[geo['kind'][0]][1], face_color=color[geo['kind'][0]][0],
visible=visible, layer=1 if geo['kind'][0] == 'C' else 2)
elif kind == 'travel':
if geo['kind'][0] == 'T':
obj.add_shape(shape=poly, color=color['T'][1], face_color=color['T'][0],
visible=visible, layer=2)
elif kind == 'cut':
if geo['kind'][0] == 'C':
obj.add_shape(shape=poly, color=color['C'][1], face_color=color['C'][0],
visible=visible, layer=1)
try: try:
obj.annotation.set(text=text, pos=pos, visible=obj.options['plot'], obj.annotation.set(text=text, pos=pos, visible=obj.options['plot'],
font_size=self.app.defaults["cncjob_annotation_fontsize"], font_size=self.app.defaults["cncjob_annotation_fontsize"],
@ -6798,7 +6990,7 @@ class CNCjob(Geometry):
def linear2gcode(self, linear, tolerance=0, down=True, up=True, def linear2gcode(self, linear, tolerance=0, down=True, up=True,
z_cut=None, z_move=None, zdownrate=None, z_cut=None, z_move=None, zdownrate=None,
feedrate=None, feedrate_z=None, feedrate_rapid=None, cont=False): feedrate=None, feedrate_z=None, feedrate_rapid=None, cont=False, old_point=(0, 0)):
""" """
Generates G-code to cut along the linear feature. Generates G-code to cut along the linear feature.
@ -6845,30 +7037,51 @@ class CNCjob(Geometry):
p = self.pp_geometry p = self.pp_geometry
self.coordinates_type = self.app.defaults["cncjob_coords_type"]
if self.coordinates_type == "G90":
# For Absolute coordinates type G90
first_x = path[0][0]
first_y = path[0][1]
else:
# For Incremental coordinates type G91
first_x = path[0][0] - old_point[0]
first_y = path[0][1] - old_point[1]
# Move fast to 1st point # Move fast to 1st point
if not cont: if not cont:
gcode += self.doformat(p.rapid_code, x=path[0][0], y=path[0][1]) # Move to first point gcode += self.doformat(p.rapid_code, x=first_x, y=first_y) # Move to first point
# Move down to cutting depth # Move down to cutting depth
if down: if down:
# Different feedrate for vertical cut? # Different feedrate for vertical cut?
gcode += self.doformat(p.z_feedrate_code) gcode += self.doformat(p.z_feedrate_code)
# gcode += self.doformat(p.feedrate_code) # gcode += self.doformat(p.feedrate_code)
gcode += self.doformat(p.down_code, x=path[0][0], y=path[0][1], z_cut=z_cut) gcode += self.doformat(p.down_code, x=first_x, y=first_y, z_cut=z_cut)
gcode += self.doformat(p.feedrate_code, feedrate=feedrate) gcode += self.doformat(p.feedrate_code, feedrate=feedrate)
# Cutting... # Cutting...
prev_x = first_x
prev_y = first_y
for pt in path[1:]: for pt in path[1:]:
gcode += self.doformat(p.linear_code, x=pt[0], y=pt[1], z=z_cut) # Linear motion to point if self.coordinates_type == "G90":
# For Absolute coordinates type G90
next_x = pt[0]
next_y = pt[1]
else:
# For Incremental coordinates type G91
next_x = pt[0] - prev_x
next_y = pt[1] - prev_y
gcode += self.doformat(p.linear_code, x=next_x, y=next_y, z=z_cut) # Linear motion to point
prev_x = pt[0]
prev_y = pt[1]
# Up to travelling height. # Up to travelling height.
if up: if up:
gcode += self.doformat(p.lift_code, x=pt[0], y=pt[1], z_move=z_move) # Stop cutting gcode += self.doformat(p.lift_code, x=prev_x, y=prev_y, z_move=z_move) # Stop cutting
return gcode return gcode
def linear2gcode_extra(self, linear, tolerance=0, down=True, up=True, def linear2gcode_extra(self, linear, tolerance=0, down=True, up=True,
z_cut=None, z_move=None, zdownrate=None, z_cut=None, z_move=None, zdownrate=None,
feedrate=None, feedrate_z=None, feedrate_rapid=None, cont=False): feedrate=None, feedrate_z=None, feedrate_rapid=None, cont=False, old_point=(0, 0)):
""" """
Generates G-code to cut along the linear feature. Generates G-code to cut along the linear feature.
@ -6913,9 +7126,19 @@ class CNCjob(Geometry):
path = list(target_linear.coords) path = list(target_linear.coords)
p = self.pp_geometry p = self.pp_geometry
self.coordinates_type = self.app.defaults["cncjob_coords_type"]
if self.coordinates_type == "G90":
# For Absolute coordinates type G90
first_x = path[0][0]
first_y = path[0][1]
else:
# For Incremental coordinates type G91
first_x = path[0][0] - old_point[0]
first_y = path[0][1] - old_point[1]
# Move fast to 1st point # Move fast to 1st point
if not cont: if not cont:
gcode += self.doformat(p.rapid_code, x=path[0][0], y=path[0][1]) # Move to first point gcode += self.doformat(p.rapid_code, x=first_x, y=first_y) # Move to first point
# Move down to cutting depth # Move down to cutting depth
if down: if down:
@ -6923,40 +7146,72 @@ class CNCjob(Geometry):
if self.z_feedrate is not None: if self.z_feedrate is not None:
gcode += self.doformat(p.z_feedrate_code) gcode += self.doformat(p.z_feedrate_code)
# gcode += self.doformat(p.feedrate_code) # gcode += self.doformat(p.feedrate_code)
gcode += self.doformat(p.down_code, x=path[0][0], y=path[0][1], z_cut=z_cut) gcode += self.doformat(p.down_code, x=first_x, y=first_y, z_cut=z_cut)
gcode += self.doformat(p.feedrate_code, feedrate=feedrate) gcode += self.doformat(p.feedrate_code, feedrate=feedrate)
else: else:
gcode += self.doformat(p.down_code, x=path[0][0], y=path[0][1], z_cut=z_cut) # Start cutting gcode += self.doformat(p.down_code, x=first_x, y=first_y, z_cut=z_cut) # Start cutting
# Cutting... # Cutting...
prev_x = first_x
prev_y = first_y
for pt in path[1:]: for pt in path[1:]:
gcode += self.doformat(p.linear_code, x=pt[0], y=pt[1], z=z_cut) # Linear motion to point if self.coordinates_type == "G90":
# For Absolute coordinates type G90
next_x = pt[0]
next_y = pt[1]
else:
# For Incremental coordinates type G91
next_x = pt[0] - prev_x
next_y = pt[1] - prev_y
gcode += self.doformat(p.linear_code, x=next_x, y=next_y, z=z_cut) # Linear motion to point
prev_x = pt[0]
prev_y = pt[1]
# this line is added to create an extra cut over the first point in patch # this line is added to create an extra cut over the first point in patch
# to make sure that we remove the copper leftovers # to make sure that we remove the copper leftovers
gcode += self.doformat(p.linear_code, x=path[1][0], y=path[1][1]) # Linear motion to the 1st point in the cut path # Linear motion to the 1st point in the cut path
if self.coordinates_type == "G90":
# For Absolute coordinates type G90
last_x = path[1][0]
last_y = path[1][1]
else:
# For Incremental coordinates type G91
last_x = path[1][0] - first_x
last_y = path[1][1] - first_y
gcode += self.doformat(p.linear_code, x=last_x, y=last_y)
# Up to travelling height. # Up to travelling height.
if up: if up:
gcode += self.doformat(p.lift_code, x=path[1][0], y=path[1][1], z_move=z_move) # Stop cutting gcode += self.doformat(p.lift_code, x=last_x, y=last_y, z_move=z_move) # Stop cutting
return gcode return gcode
def point2gcode(self, point): def point2gcode(self, point, old_point=(0, 0)):
gcode = "" gcode = ""
path = list(point.coords) path = list(point.coords)
p = self.pp_geometry p = self.pp_geometry
gcode += self.doformat(p.linear_code, x=path[0][0], y=path[0][1]) # Move to first point
self.coordinates_type = self.app.defaults["cncjob_coords_type"]
if self.coordinates_type == "G90":
# For Absolute coordinates type G90
first_x = path[0][0]
first_y = path[0][1]
else:
# For Incremental coordinates type G91
first_x = path[0][0] - old_point[0]
first_y = path[0][1] - old_point[1]
gcode += self.doformat(p.linear_code, x=first_x, y=first_y) # Move to first point
if self.z_feedrate is not None: if self.z_feedrate is not None:
gcode += self.doformat(p.z_feedrate_code) gcode += self.doformat(p.z_feedrate_code)
gcode += self.doformat(p.down_code, x=path[0][0], y=path[0][1], z_cut = self.z_cut) gcode += self.doformat(p.down_code, x=first_x, y=first_y, z_cut = self.z_cut)
gcode += self.doformat(p.feedrate_code) gcode += self.doformat(p.feedrate_code)
else: else:
gcode += self.doformat(p.down_code, x=path[0][0], y=path[0][1], z_cut = self.z_cut) # Start cutting gcode += self.doformat(p.down_code, x=first_x, y=first_y, z_cut = self.z_cut) # Start cutting
gcode += self.doformat(p.lift_code, x=path[0][0], y=path[0][1]) # Stop cutting gcode += self.doformat(p.lift_code, x=first_x, y=first_y) # Stop cutting
return gcode return gcode
def export_svg(self, scale_factor=0.00): def export_svg(self, scale_factor=0.00):

View File

@ -6119,8 +6119,8 @@ class CNCJobGenPrefGroupUI(OptionsGroupUI):
grid0 = QtWidgets.QGridLayout() grid0 = QtWidgets.QGridLayout()
self.layout.addLayout(grid0) self.layout.addLayout(grid0)
grid0.setColumnStretch(1, 1) # grid0.setColumnStretch(1, 1)
grid0.setColumnStretch(2, 1) # grid0.setColumnStretch(2, 1)
# Plot CB # Plot CB
# self.plot_cb = QtWidgets.QCheckBox('Plot') # self.plot_cb = QtWidgets.QCheckBox('Plot')
@ -6129,7 +6129,7 @@ class CNCJobGenPrefGroupUI(OptionsGroupUI):
grid0.addWidget(self.plot_cb, 0, 0) grid0.addWidget(self.plot_cb, 0, 0)
# Plot Kind # Plot Kind
self.cncplot_method_label = QtWidgets.QLabel('%s:' % _("Plot kind:")) self.cncplot_method_label = QtWidgets.QLabel('%s:' % _("Plot kind"))
self.cncplot_method_label.setToolTip( self.cncplot_method_label.setToolTip(
_("This selects the kind of geometries on the canvas to plot.\n" _("This selects the kind of geometries on the canvas to plot.\n"
"Those can be either of type 'Travel' which means the moves\n" "Those can be either of type 'Travel' which means the moves\n"
@ -6205,34 +6205,52 @@ class CNCJobGenPrefGroupUI(OptionsGroupUI):
grid0.addWidget(self.steps_per_circle_entry, 5, 1) grid0.addWidget(self.steps_per_circle_entry, 5, 1)
# Tool dia for plot # Tool dia for plot
tdlabel = QtWidgets.QLabel('%s:' % _('Tool dia')) tdlabel = QtWidgets.QLabel('%s:' % _('Travel dia'))
tdlabel.setToolTip( tdlabel.setToolTip(
_("Diameter of the tool to be\n" _("The width of the travel lines to be\n"
"rendered in the plot.") "rendered in the plot.")
) )
grid0.addWidget(tdlabel, 6, 0)
self.tooldia_entry = LengthEntry() self.tooldia_entry = LengthEntry()
grid0.addWidget(tdlabel, 6, 0)
grid0.addWidget(self.tooldia_entry, 6, 1) grid0.addWidget(self.tooldia_entry, 6, 1)
# add a space
grid0.addWidget(QtWidgets.QLabel(''), 7, 0)
# Number of decimals to use in GCODE coordinates # Number of decimals to use in GCODE coordinates
cdeclabel = QtWidgets.QLabel('%s:' % _('Coords dec.')) cdeclabel = QtWidgets.QLabel('%s:' % _('Coordinates decimals'))
cdeclabel.setToolTip( cdeclabel.setToolTip(
_("The number of decimals to be used for \n" _("The number of decimals to be used for \n"
"the X, Y, Z coordinates in CNC code (GCODE, etc.)") "the X, Y, Z coordinates in CNC code (GCODE, etc.)")
) )
grid0.addWidget(cdeclabel, 7, 0)
self.coords_dec_entry = IntEntry() self.coords_dec_entry = IntEntry()
grid0.addWidget(self.coords_dec_entry, 7, 1) grid0.addWidget(cdeclabel, 8, 0)
grid0.addWidget(self.coords_dec_entry, 8, 1)
# Number of decimals to use in GCODE feedrate # Number of decimals to use in GCODE feedrate
frdeclabel = QtWidgets.QLabel('%s:' % _('Feedrate dec.')) frdeclabel = QtWidgets.QLabel('%s:' % _('Feedrate decimals'))
frdeclabel.setToolTip( frdeclabel.setToolTip(
_("The number of decimals to be used for \n" _("The number of decimals to be used for \n"
"the Feedrate parameter in CNC code (GCODE, etc.)") "the Feedrate parameter in CNC code (GCODE, etc.)")
) )
grid0.addWidget(frdeclabel, 8, 0)
self.fr_dec_entry = IntEntry() self.fr_dec_entry = IntEntry()
grid0.addWidget(self.fr_dec_entry, 8, 1) grid0.addWidget(frdeclabel, 9, 0)
grid0.addWidget(self.fr_dec_entry, 9, 1)
# The type of coordinates used in the Gcode: Absolute or Incremental
coords_type_label = QtWidgets.QLabel('%s:' % _('Coordinates type'))
coords_type_label.setToolTip(
_("The type of coordinates to be used in Gcode.\n"
"Can be:\n"
"- Absolute G90 -> the reference is the origin x=0, y=0\n"
"- Incremental G91 -> the reference is the previous position")
)
self.coords_type_radio = RadioSet([
{"label": _("Absolute G90"), "value": "G90"},
{"label": _("Incremental G91"), "value": "G91"}
], orientation='vertical', stretch=False)
grid0.addWidget(coords_type_label, 10, 0)
grid0.addWidget(self.coords_type_radio, 10, 1)
self.layout.addStretch() self.layout.addStretch()