- Tool Drilling - remade the methods used to generate GCode from Excellon, to parse the GCode. Now the GCode and GCode_parsed are stored individually for each tool and also they are plotted individually
- Tool Drilling now works - I still need to add the method for converting slots to drill holes
This commit is contained in:
parent
a0fea17aed
commit
4216333645
|
@ -7,6 +7,11 @@ CHANGELOG for FlatCAM beta
|
|||
|
||||
=================================================
|
||||
|
||||
9.07.2020
|
||||
|
||||
- Tool Drilling - remade the methods used to generate GCode from Excellon, to parse the GCode. Now the GCode and GCode_parsed are stored individually for each tool and also they are plotted individually
|
||||
- Tool Drilling now works - I still need to add the method for converting slots to drill holes
|
||||
|
||||
8.07.2020
|
||||
|
||||
- Tool Drilling - working on the UI
|
||||
|
|
|
@ -283,7 +283,7 @@ class CNCJobObject(FlatCAMObj, CNCjob):
|
|||
dia_item = QtWidgets.QTableWidgetItem('%.*f' % (self.decimals, float(tooldia_key)))
|
||||
nr_drills_item = QtWidgets.QTableWidgetItem('%d' % int(dia_value['nr_drills']))
|
||||
nr_slots_item = QtWidgets.QTableWidgetItem('%d' % int(dia_value['nr_slots']))
|
||||
cutz_item = QtWidgets.QTableWidgetItem('%.*f' % (self.decimals, float(dia_value['offset_z']) + self.z_cut))
|
||||
cutz_item = QtWidgets.QTableWidgetItem('%.*f' % (self.decimals, float(dia_value['offset']) + self.z_cut))
|
||||
|
||||
t_id.setFlags(QtCore.Qt.ItemIsEnabled)
|
||||
dia_item.setFlags(QtCore.Qt.ItemIsEnabled)
|
||||
|
@ -876,11 +876,18 @@ class CNCJobObject(FlatCAMObj, CNCjob):
|
|||
|
||||
# detect if using multi-tool and make the Gcode summation correctly for each case
|
||||
if self.multitool is True:
|
||||
for tooluid_key in self.cnc_tools:
|
||||
for key, value in self.cnc_tools[tooluid_key].items():
|
||||
if key == 'gcode':
|
||||
gcode += value
|
||||
break
|
||||
if self.origin_kind == 'excellon':
|
||||
for tooluid_key in self.exc_cnc_tools:
|
||||
for key, value in self.exc_cnc_tools[tooluid_key].items():
|
||||
if key == 'gcode' and value:
|
||||
gcode += value
|
||||
break
|
||||
else:
|
||||
for tooluid_key in self.cnc_tools:
|
||||
for key, value in self.cnc_tools[tooluid_key].items():
|
||||
if key == 'gcode' and value:
|
||||
gcode += value
|
||||
break
|
||||
else:
|
||||
gcode += self.gcode
|
||||
|
||||
|
@ -1127,8 +1134,10 @@ class CNCJobObject(FlatCAMObj, CNCjob):
|
|||
if self.exc_cnc_tools:
|
||||
for tooldia_key in self.exc_cnc_tools:
|
||||
tooldia = float('%.*f' % (self.decimals, float(tooldia_key)))
|
||||
# gcode_parsed = self.exc_cnc_tools[tooldia_key]['gcode_parsed']
|
||||
gcode_parsed = self.gcode_parsed
|
||||
gcode_parsed = self.exc_cnc_tools[tooldia_key]['gcode_parsed']
|
||||
if not gcode_parsed:
|
||||
continue
|
||||
# gcode_parsed = self.gcode_parsed
|
||||
self.plot2(tooldia=tooldia, obj=self, visible=visible, gcode_parsed=gcode_parsed, kind=kind)
|
||||
|
||||
self.shapes.redraw()
|
||||
|
|
File diff suppressed because it is too large
Load Diff
463
camlib.py
463
camlib.py
|
@ -2574,6 +2574,11 @@ class CNCjob(Geometry):
|
|||
|
||||
self.tool = 0.0
|
||||
|
||||
self.measured_distance = 0.0
|
||||
self.measured_down_distance = 0.0
|
||||
self.measured_up_to_zero_distance = 0.0
|
||||
self.measured_lift_distance = 0.0
|
||||
|
||||
# here store the travelled distance
|
||||
self.travel_distance = 0.0
|
||||
# here store the routing time
|
||||
|
@ -2885,6 +2890,310 @@ class CNCjob(Geometry):
|
|||
self.app.inform.emit('[WARNING] %s.' % _("The Cut Z parameter is zero. There will be no cut, aborting"))
|
||||
return 'fail'
|
||||
|
||||
|
||||
def gcode_from_excellon_by_tool(self, tool, points, tools, opt_type='T', toolchange=False):
|
||||
"""
|
||||
Creates Gcode for this object from an Excellon object
|
||||
for the specified tools.
|
||||
|
||||
:return: Tool GCode
|
||||
:rtype: str
|
||||
"""
|
||||
log.debug("Creating CNC Job from Excellon for tool: %s" % str(tool))
|
||||
|
||||
self.exc_tools = deepcopy(tools)
|
||||
t_gcode = ''
|
||||
p = self.pp_excellon
|
||||
self.toolchange = toolchange
|
||||
|
||||
# #############################################################################################################
|
||||
# #############################################################################################################
|
||||
# ################################## DRILLING !!! #########################################################
|
||||
# #############################################################################################################
|
||||
# #############################################################################################################
|
||||
if opt_type == 'M':
|
||||
log.debug("Using OR-Tools Metaheuristic Guided Local Search drill path optimization.")
|
||||
elif opt_type == 'B':
|
||||
log.debug("Using OR-Tools Basic drill path optimization.")
|
||||
elif opt_type == 'T':
|
||||
log.debug("Using Travelling Salesman drill path optimization.")
|
||||
else:
|
||||
log.debug("Using no path optimization.")
|
||||
|
||||
tool_dict = tools[tool]['data']
|
||||
# check if it has drills
|
||||
if not tools[tool]['drills']:
|
||||
log.debug("Failed. No drills for tool: %s" % str(tool))
|
||||
return 'fail'
|
||||
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise grace
|
||||
|
||||
# #########################################################################################################
|
||||
# #########################################################################################################
|
||||
# ############# PARAMETERS ################################################################################
|
||||
# #########################################################################################################
|
||||
# #########################################################################################################
|
||||
self.tool = str(tool)
|
||||
self.tooldia = tools[tool]["tooldia"]
|
||||
self.postdata['toolC'] = self.tooldia
|
||||
|
||||
self.z_feedrate = tool_dict['feedrate_z']
|
||||
self.feedrate = tool_dict['feedrate']
|
||||
|
||||
t_gcode += self.doformat(p.z_feedrate_code)
|
||||
|
||||
# Z_cut parameter
|
||||
if self.machinist_setting == 0:
|
||||
self.z_cut = self.check_zcut(zcut=tool_dict["excellon_cutz"])
|
||||
if self.z_cut == 'fail':
|
||||
return 'fail'
|
||||
|
||||
self.z_cut = tool_dict['cutz']
|
||||
# multidepth use this
|
||||
old_zcut = tool_dict["cutz"]
|
||||
|
||||
self.z_move = tool_dict['travelz']
|
||||
self.spindlespeed = tool_dict['spindlespeed']
|
||||
self.dwell = tool_dict['dwell']
|
||||
self.dwelltime = tool_dict['dwelltime']
|
||||
self.multidepth = tool_dict['multidepth']
|
||||
self.z_depthpercut = tool_dict['depthperpass']
|
||||
|
||||
# XY_toolchange parameter
|
||||
self.xy_toolchange = tool_dict["toolchangexy"]
|
||||
try:
|
||||
if self.xy_toolchange == '':
|
||||
self.xy_toolchange = None
|
||||
else:
|
||||
self.xy_toolchange = re.sub('[()\[\]]', '', str(self.xy_toolchange)) if self.xy_toolchange else None
|
||||
|
||||
if self.xy_toolchange:
|
||||
self.xy_toolchange = [
|
||||
float(eval(a)) for a in self.xy_toolchange.split(",")
|
||||
]
|
||||
|
||||
if self.xy_toolchange and len(self.xy_toolchange) != 2:
|
||||
self.app.inform.emit('[ERROR]%s' %
|
||||
_("The Toolchange X,Y field in Edit -> Preferences has to be "
|
||||
"in the format (x, y) \nbut now there is only one value, not two. "))
|
||||
return 'fail'
|
||||
except Exception as e:
|
||||
log.debug("camlib.CNCJob.generate_from_excellon_by_tool() --> %s" % str(e))
|
||||
pass
|
||||
|
||||
# XY_end parameter
|
||||
self.xy_end = tool_dict["endxy"]
|
||||
self.xy_end = re.sub('[()\[\]]', '', str(self.xy_end)) if self.xy_end else None
|
||||
if self.xy_end and self.xy_end != '':
|
||||
self.xy_end = [float(eval(a)) for a in self.xy_end.split(",")]
|
||||
if self.xy_end and len(self.xy_end) < 2:
|
||||
self.app.inform.emit(
|
||||
'[ERROR] %s' % _("The End Move X,Y field in Edit -> Preferences has to be "
|
||||
"in the format (x, y) but now there is only one value, not two."))
|
||||
return 'fail'
|
||||
# #########################################################################################################
|
||||
# #########################################################################################################
|
||||
|
||||
# #########################################################################################################
|
||||
# ############ Create the data. #################
|
||||
# #########################################################################################################
|
||||
locations = []
|
||||
altPoints = []
|
||||
optimized_path = []
|
||||
|
||||
if opt_type == 'M':
|
||||
locations = self.create_tool_data_array(points=points)
|
||||
# if there are no locations then go to the next tool
|
||||
if not locations:
|
||||
return 'fail'
|
||||
optimized_path = self.optimized_ortools_meta(locations=locations)
|
||||
elif opt_type == 'B':
|
||||
locations = self.create_tool_data_array(points=points)
|
||||
# if there are no locations then go to the next tool
|
||||
if not locations:
|
||||
return 'fail'
|
||||
optimized_path = self.optimized_ortools_basic(locations=locations)
|
||||
elif opt_type == 'T':
|
||||
for point in points:
|
||||
altPoints.append((point.coords.xy[0][0], point.coords.xy[1][0]))
|
||||
# if there are no locations then go to the next tool
|
||||
if not altPoints:
|
||||
return 'fail'
|
||||
optimized_path = self.optimized_travelling_salesman(altPoints)
|
||||
else:
|
||||
# it's actually not optimized path but here we build a list of (x,y) coordinates
|
||||
# out of the tool's drills
|
||||
for drill in tools[tool]['drills']:
|
||||
unoptimized_coords = (
|
||||
drill.x,
|
||||
drill.y
|
||||
)
|
||||
optimized_path.append(unoptimized_coords)
|
||||
# #########################################################################################################
|
||||
# #########################################################################################################
|
||||
|
||||
# Only if there are locations to drill
|
||||
if not optimized_path:
|
||||
return 'fail'
|
||||
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise grace
|
||||
|
||||
# Tool change sequence (optional)
|
||||
if toolchange:
|
||||
t_gcode += self.doformat(p.toolchange_code, toolchangexy=(self.oldx, self.oldy))
|
||||
else:
|
||||
if self.xy_toolchange is not None and isinstance(self.xy_toolchange, (tuple, list)):
|
||||
t_gcode += self.doformat(p.lift_code, x=self.xy_toolchange[0], y=self.xy_toolchange[1])
|
||||
t_gcode += self.doformat(p.startz_code, x=self.xy_toolchange[0], y=self.xy_toolchange[1])
|
||||
else:
|
||||
t_gcode += self.doformat(p.lift_code, x=0.0, y=0.0)
|
||||
t_gcode += self.doformat(p.startz_code, x=0.0, y=0.0)
|
||||
|
||||
# Spindle start
|
||||
t_gcode += self.doformat(p.spindle_code)
|
||||
# Dwell time
|
||||
if self.dwell is True:
|
||||
t_gcode += self.doformat(p.dwell_code)
|
||||
|
||||
current_tooldia = float('%.*f' % (self.decimals, float(tools[tool]["tooldia"])))
|
||||
|
||||
self.app.inform.emit(
|
||||
'%s: %s%s.' % (_("Starting G-Code for tool with diameter"),
|
||||
str(current_tooldia),
|
||||
str(self.units))
|
||||
)
|
||||
|
||||
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
# APPLY Offset only when using the appGUI, for TclCommand this will create an error
|
||||
# because the values for Z offset are created in build_tool_ui()
|
||||
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
try:
|
||||
z_offset = float(tool_dict['offset']) * (-1)
|
||||
except KeyError:
|
||||
z_offset = 0
|
||||
self.z_cut = z_offset + old_zcut
|
||||
|
||||
self.coordinates_type = self.app.defaults["cncjob_coords_type"]
|
||||
if self.coordinates_type == "G90":
|
||||
# Drillling! for Absolute coordinates type G90
|
||||
# variables to display the percentage of work done
|
||||
geo_len = len(optimized_path)
|
||||
|
||||
old_disp_number = 0
|
||||
log.warning("Number of drills for which to generate GCode: %s" % str(geo_len))
|
||||
|
||||
loc_nr = 0
|
||||
for point in optimized_path:
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise grace
|
||||
|
||||
if opt_type == 'T':
|
||||
locx = point[0]
|
||||
locy = point[1]
|
||||
else:
|
||||
locx = locations[point][0]
|
||||
locy = locations[point][1]
|
||||
|
||||
travels = self.app.exc_areas.travel_coordinates(start_point=(self.oldx, self.oldy),
|
||||
end_point=(locx, locy),
|
||||
tooldia=current_tooldia)
|
||||
prev_z = None
|
||||
for travel in travels:
|
||||
locx = travel[1][0]
|
||||
locy = travel[1][1]
|
||||
|
||||
if travel[0] is not None:
|
||||
# move to next point
|
||||
t_gcode += self.doformat(p.rapid_code, x=locx, y=locy)
|
||||
|
||||
# raise to safe Z (travel[0]) each time because safe Z may be different
|
||||
self.z_move = travel[0]
|
||||
t_gcode += self.doformat(p.lift_code, x=locx, y=locy)
|
||||
|
||||
# restore z_move
|
||||
self.z_move = tool_dict['travelz']
|
||||
else:
|
||||
if prev_z is not None:
|
||||
# move to next point
|
||||
t_gcode += self.doformat(p.rapid_code, x=locx, y=locy)
|
||||
|
||||
# we assume that previously the z_move was altered therefore raise to
|
||||
# the travel_z (z_move)
|
||||
self.z_move = tool_dict['travelz']
|
||||
t_gcode += self.doformat(p.lift_code, x=locx, y=locy)
|
||||
else:
|
||||
# move to next point
|
||||
t_gcode += self.doformat(p.rapid_code, x=locx, y=locy)
|
||||
|
||||
# store prev_z
|
||||
prev_z = travel[0]
|
||||
|
||||
# t_gcode += self.doformat(p.rapid_code, x=locx, y=locy)
|
||||
|
||||
if self.multidepth and abs(self.z_cut) > abs(self.z_depthpercut):
|
||||
doc = deepcopy(self.z_cut)
|
||||
self.z_cut = 0.0
|
||||
|
||||
while abs(self.z_cut) < abs(doc):
|
||||
|
||||
self.z_cut -= self.z_depthpercut
|
||||
if abs(doc) < abs(self.z_cut) < (abs(doc) + self.z_depthpercut):
|
||||
self.z_cut = doc
|
||||
t_gcode += self.doformat(p.down_code, x=locx, y=locy)
|
||||
|
||||
self.measured_down_distance += abs(self.z_cut) + abs(self.z_move)
|
||||
|
||||
if self.f_retract is False:
|
||||
t_gcode += self.doformat(p.up_to_zero_code, x=locx, y=locy)
|
||||
self.measured_up_to_zero_distance += abs(self.z_cut)
|
||||
self.measured_lift_distance += abs(self.z_move)
|
||||
else:
|
||||
self.measured_lift_distance += abs(self.z_cut) + abs(self.z_move)
|
||||
|
||||
t_gcode += self.doformat(p.lift_code, x=locx, y=locy)
|
||||
|
||||
else:
|
||||
t_gcode += self.doformat(p.down_code, x=locx, y=locy)
|
||||
|
||||
self.measured_down_distance += abs(self.z_cut) + abs(self.z_move)
|
||||
|
||||
if self.f_retract is False:
|
||||
t_gcode += self.doformat(p.up_to_zero_code, x=locx, y=locy)
|
||||
self.measured_up_to_zero_distance += abs(self.z_cut)
|
||||
self.measured_lift_distance += abs(self.z_move)
|
||||
else:
|
||||
self.measured_lift_distance += abs(self.z_cut) + abs(self.z_move)
|
||||
|
||||
t_gcode += self.doformat(p.lift_code, x=locx, y=locy)
|
||||
|
||||
self.measured_distance += abs(distance_euclidian(locx, locy, self.oldx, self.oldy))
|
||||
self.oldx = locx
|
||||
self.oldy = locy
|
||||
|
||||
loc_nr += 1
|
||||
disp_number = int(np.interp(loc_nr, [0, geo_len], [0, 100]))
|
||||
|
||||
if old_disp_number < disp_number <= 100:
|
||||
self.app.proc_container.update_view_text(' %d%%' % disp_number)
|
||||
old_disp_number = disp_number
|
||||
|
||||
else:
|
||||
self.app.inform.emit('[ERROR_NOTCL] %s...' % _('G91 coordinates not implemented'))
|
||||
return 'fail'
|
||||
self.z_cut = deepcopy(old_zcut)
|
||||
|
||||
t_gcode += self.doformat(p.spindle_stop_code)
|
||||
# Move to End position
|
||||
t_gcode += self.doformat(p.end_code, x=0, y=0)
|
||||
|
||||
self.app.inform.emit(_("Finished G-Code generation for tool: %s" % str(tool)))
|
||||
return t_gcode
|
||||
|
||||
def generate_from_excellon_by_tool(self, exobj, tools="all", order='fwd', use_ui=False):
|
||||
"""
|
||||
Creates Gcode for this object from an Excellon object
|
||||
|
@ -5571,6 +5880,160 @@ class CNCjob(Geometry):
|
|||
self.gcode_parsed = geometry
|
||||
return geometry
|
||||
|
||||
def excellon_tool_gcode_parse(self, dia, start_pt=(0, 0), force_parsing=None):
|
||||
"""
|
||||
G-Code parser (from self.exc_cnc_tools['tooldia']['gcode']). Generates dictionary with
|
||||
single-segment LineString's and "kind" indicating cut or travel,
|
||||
fast or feedrate speed.
|
||||
|
||||
Will return a list of dict in the format:
|
||||
{
|
||||
"geom": LineString(path),
|
||||
"kind": kind
|
||||
}
|
||||
where kind can be either ["C", "F"] # T=travel, C=cut, F=fast, S=slow
|
||||
|
||||
:param dia: the dia is a tool diameter which is the key in self.exc_cnc_tools dict
|
||||
:type dia: float
|
||||
:param start_pt: the point coordinates from where to start the parsing
|
||||
:type start_pt: tuple
|
||||
:param force_parsing:
|
||||
:type force_parsing: bool
|
||||
:return: list of dictionaries
|
||||
:rtype: list
|
||||
"""
|
||||
|
||||
kind = ["C", "F"] # T=travel, C=cut, F=fast, S=slow
|
||||
|
||||
# Results go here
|
||||
geometry = []
|
||||
|
||||
# Last known instruction
|
||||
current = {'X': 0.0, 'Y': 0.0, 'Z': 0.0, 'G': 0}
|
||||
|
||||
# Current path: temporary storage until tool is
|
||||
# lifted or lowered.
|
||||
pos_xy = start_pt
|
||||
|
||||
path = [pos_xy]
|
||||
# path = [(0, 0)]
|
||||
|
||||
gcode_lines_list = self.exc_cnc_tools[dia]['gcode'].splitlines()
|
||||
self.app.inform.emit(
|
||||
'%s: %s. %s: %d' % (_("Parsing GCode file for tool diameter"),
|
||||
str(dia), _("Number of lines"),
|
||||
len(gcode_lines_list))
|
||||
)
|
||||
|
||||
# Process every instruction
|
||||
for line in gcode_lines_list:
|
||||
if force_parsing is False or force_parsing is None:
|
||||
if '%MO' in line or '%' in line or 'MOIN' in line or 'MOMM' in line:
|
||||
return "fail"
|
||||
|
||||
gobj = self.codes_split(line)
|
||||
|
||||
# ## Units
|
||||
if 'G' in gobj and (gobj['G'] == 20.0 or gobj['G'] == 21.0):
|
||||
self.units = {20.0: "IN", 21.0: "MM"}[gobj['G']]
|
||||
continue
|
||||
|
||||
# TODO take into consideration the tools and update the travel line thickness
|
||||
if 'T' in gobj:
|
||||
pass
|
||||
|
||||
# ## Changing height
|
||||
if 'Z' in gobj:
|
||||
if 'Roland' in self.pp_excellon_name or 'Roland' in self.pp_geometry_name:
|
||||
pass
|
||||
elif 'hpgl' in self.pp_excellon_name or 'hpgl' in self.pp_geometry_name:
|
||||
pass
|
||||
elif 'laser' in self.pp_excellon_name or 'laser' in self.pp_geometry_name:
|
||||
pass
|
||||
elif ('X' in gobj or 'Y' in gobj) and gobj['Z'] != current['Z']:
|
||||
if self.pp_geometry_name == 'line_xyz' or self.pp_excellon_name == 'line_xyz':
|
||||
pass
|
||||
else:
|
||||
log.warning("Non-orthogonal motion: From %s" % str(current))
|
||||
log.warning(" To: %s" % str(gobj))
|
||||
|
||||
current['Z'] = gobj['Z']
|
||||
# Store the path into geometry and reset path
|
||||
if len(path) > 1:
|
||||
geometry.append({"geom": LineString(path),
|
||||
"kind": kind})
|
||||
path = [path[-1]] # Start with the last point of last path.
|
||||
|
||||
# create the geometry for the holes created when drilling Excellon drills
|
||||
if self.origin_kind == 'excellon':
|
||||
if current['Z'] < 0:
|
||||
current_drill_point_coords = (
|
||||
float('%.*f' % (self.decimals, current['X'])),
|
||||
float('%.*f' % (self.decimals, current['Y']))
|
||||
)
|
||||
|
||||
kind = ['C', 'F']
|
||||
geometry.append(
|
||||
{
|
||||
"geom": Point(current_drill_point_coords).buffer(dia/2.0).exterior,
|
||||
"kind": kind
|
||||
}
|
||||
)
|
||||
|
||||
if 'G' in gobj:
|
||||
current['G'] = int(gobj['G'])
|
||||
|
||||
if 'X' in gobj or 'Y' in gobj:
|
||||
if 'X' in gobj:
|
||||
x = gobj['X']
|
||||
# current['X'] = x
|
||||
else:
|
||||
x = current['X']
|
||||
|
||||
if 'Y' in gobj:
|
||||
y = gobj['Y']
|
||||
else:
|
||||
y = current['Y']
|
||||
|
||||
kind = ["C", "F"] # T=travel, C=cut, F=fast, S=slow
|
||||
|
||||
if current['Z'] > 0:
|
||||
kind[0] = 'T'
|
||||
if current['G'] > 0:
|
||||
kind[1] = 'S'
|
||||
|
||||
if current['G'] in [0, 1]: # line
|
||||
path.append((x, y))
|
||||
|
||||
arcdir = [None, None, "cw", "ccw"]
|
||||
if current['G'] in [2, 3]: # arc
|
||||
center = [gobj['I'] + current['X'], gobj['J'] + current['Y']]
|
||||
radius = np.sqrt(gobj['I'] ** 2 + gobj['J'] ** 2)
|
||||
start = np.arctan2(-gobj['J'], -gobj['I'])
|
||||
stop = np.arctan2(-center[1] + y, -center[0] + x)
|
||||
path += arc(center, radius, start, stop, arcdir[current['G']], int(self.steps_per_circle))
|
||||
|
||||
current['X'] = x
|
||||
current['Y'] = y
|
||||
|
||||
# Update current instruction
|
||||
for code in gobj:
|
||||
current[code] = gobj[code]
|
||||
|
||||
self.app.inform.emit('%s: %s' % (_("Creating Geometry from the parsed GCode file for tool diameter"), str(dia)))
|
||||
# There might not be a change in height at the
|
||||
# end, therefore, see here too if there is
|
||||
# a final path.
|
||||
if len(path) > 1:
|
||||
geometry.append(
|
||||
{
|
||||
"geom": LineString(path),
|
||||
"kind": kind
|
||||
}
|
||||
)
|
||||
|
||||
return geometry
|
||||
|
||||
# def plot(self, tooldia=None, dpi=75, margin=0.1,
|
||||
# color={"T": ["#F0E24D", "#B5AB3A"], "C": ["#5E6CFF", "#4650BD"]},
|
||||
# alpha={"T": 0.3, "C": 1.0}):
|
||||
|
|
Loading…
Reference in New Issue