- Tool Drilling - added new feature to drill the slots
This commit is contained in:
parent
494963ed04
commit
391a28282e
|
@ -14,6 +14,7 @@ CHANGELOG for FlatCAM beta
|
||||||
- CNCJob object - now it is possible for CNCJob objects originated from Excellon objects, to toggle the plot for a selection of tools
|
- CNCJob object - now it is possible for CNCJob objects originated from Excellon objects, to toggle the plot for a selection of tools
|
||||||
- working in cleaning up the Excellon UI (Selected Tab)
|
- working in cleaning up the Excellon UI (Selected Tab)
|
||||||
- finished the clean-up in Excellon UI
|
- finished the clean-up in Excellon UI
|
||||||
|
- Tool Drilling - added new feature to drill the slots
|
||||||
|
|
||||||
8.07.2020
|
8.07.2020
|
||||||
|
|
||||||
|
|
|
@ -1533,8 +1533,26 @@ class ToolDrilling(AppTool, Excellon):
|
||||||
self.t_ui.exclusion_table.selectAll()
|
self.t_ui.exclusion_table.selectAll()
|
||||||
self.draw_sel_shape()
|
self.draw_sel_shape()
|
||||||
|
|
||||||
def process_slots_as_drills(self):
|
def process_slot_as_drills(self, slot, overlap, add_last_pt=False):
|
||||||
pass
|
|
||||||
|
drills_list = []
|
||||||
|
start_pt = slot[0]
|
||||||
|
stop_pt = slot[1]
|
||||||
|
slot_line = LineString([start_pt, stop_pt])
|
||||||
|
drills_list.append(start_pt)
|
||||||
|
|
||||||
|
ii = 0
|
||||||
|
while True:
|
||||||
|
ii += 1
|
||||||
|
target = overlap * ii
|
||||||
|
new_pt = slot_line.interpolate(target)
|
||||||
|
if new_pt.within(slot_line) is False:
|
||||||
|
break
|
||||||
|
drills_list.append(new_pt)
|
||||||
|
|
||||||
|
if add_last_pt and stop_pt.distance(drills_list[-1]) >= overlap/10:
|
||||||
|
drills_list.append(stop_pt)
|
||||||
|
return drills_list
|
||||||
|
|
||||||
def on_cnc_button_click(self):
|
def on_cnc_button_click(self):
|
||||||
obj_name = self.t_ui.object_combo.currentText()
|
obj_name = self.t_ui.object_combo.currentText()
|
||||||
|
@ -1551,12 +1569,22 @@ class ToolDrilling(AppTool, Excellon):
|
||||||
self.app.inform.emit('[ERROR_NOTCL] %s.' % _("Object not found"))
|
self.app.inform.emit('[ERROR_NOTCL] %s.' % _("Object not found"))
|
||||||
return
|
return
|
||||||
|
|
||||||
|
slots_as_drills = self.t_ui.drill_slots_cb.get_value()
|
||||||
|
|
||||||
has_drills = None
|
has_drills = None
|
||||||
for tool, tool_dict in obj.tools.items():
|
for tool_key, tool_dict in self.excellon_tools.items():
|
||||||
if 'drills' in tool_dict and tool_dict['drills']:
|
if 'drills' in tool_dict and tool_dict['drills']:
|
||||||
has_drills = True
|
has_drills = True
|
||||||
break
|
break
|
||||||
|
has_slots = None
|
||||||
|
for tool_key, tool_dict in self.excellon_tools.items():
|
||||||
|
if 'slots' in tool_dict and tool_dict['slots']:
|
||||||
|
has_slots = True
|
||||||
|
break
|
||||||
if not has_drills:
|
if not has_drills:
|
||||||
|
if slots_as_drills and has_slots:
|
||||||
|
pass
|
||||||
|
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 ...")
|
||||||
self.app.inform.emit('[ERROR_NOTCL] %s...' % _('The loaded Excellon file has no drills'))
|
self.app.inform.emit('[ERROR_NOTCL] %s...' % _('The loaded Excellon file has no drills'))
|
||||||
|
@ -1564,8 +1592,8 @@ class ToolDrilling(AppTool, Excellon):
|
||||||
|
|
||||||
# Get the tools from the Tool Table
|
# Get the tools from the Tool Table
|
||||||
selected_uid = set()
|
selected_uid = set()
|
||||||
for it in self.t_ui.tools_table.selectedItems():
|
for sel_it in self.t_ui.tools_table.selectedItems():
|
||||||
uid = int(self.t_ui.tools_table.item(it.row(), 3).text())
|
uid = int(self.t_ui.tools_table.item(sel_it.row(), 3).text())
|
||||||
selected_uid.add(uid)
|
selected_uid.add(uid)
|
||||||
selected_tools_id = list(selected_uid)
|
selected_tools_id = list(selected_uid)
|
||||||
|
|
||||||
|
@ -1580,9 +1608,6 @@ class ToolDrilling(AppTool, Excellon):
|
||||||
_("Please select one or more tools from the list and try again."))
|
_("Please select one or more tools from the list and try again."))
|
||||||
return
|
return
|
||||||
|
|
||||||
# add slots as drills
|
|
||||||
self.process_slots_as_drills()
|
|
||||||
|
|
||||||
xmin = obj.options['xmin']
|
xmin = obj.options['xmin']
|
||||||
ymin = obj.options['ymin']
|
ymin = obj.options['ymin']
|
||||||
xmax = obj.options['xmax']
|
xmax = obj.options['xmax']
|
||||||
|
@ -1599,7 +1624,7 @@ class ToolDrilling(AppTool, Excellon):
|
||||||
# #############################################################################################################
|
# #############################################################################################################
|
||||||
# #############################################################################################################
|
# #############################################################################################################
|
||||||
all_tools = []
|
all_tools = []
|
||||||
for tool_as_key, v in list(obj.tools.items()):
|
for tool_as_key, v in list(self.excellon_tools.items()):
|
||||||
all_tools.append((int(tool_as_key), float(v['tooldia'])))
|
all_tools.append((int(tool_as_key), float(v['tooldia'])))
|
||||||
|
|
||||||
order = self.t_ui.order_radio.get_value()
|
order = self.t_ui.order_radio.get_value()
|
||||||
|
@ -1625,8 +1650,8 @@ class ToolDrilling(AppTool, Excellon):
|
||||||
self.app.inform.emit(_("Creating a list of points to drill..."))
|
self.app.inform.emit(_("Creating a list of points to drill..."))
|
||||||
|
|
||||||
points = {}
|
points = {}
|
||||||
for tool, tl_dict in obj.tools.items():
|
for tool_key, tl_dict in self.excellon_tools.items():
|
||||||
if tool in sel_tools:
|
if tool_key in sel_tools:
|
||||||
if self.app.abort_flag:
|
if self.app.abort_flag:
|
||||||
# graceful abort requested by the user
|
# graceful abort requested by the user
|
||||||
raise grace
|
raise grace
|
||||||
|
@ -1634,17 +1659,46 @@ class ToolDrilling(AppTool, Excellon):
|
||||||
if 'drills' in tl_dict and tl_dict['drills']:
|
if 'drills' in tl_dict and tl_dict['drills']:
|
||||||
for drill_pt in tl_dict['drills']:
|
for drill_pt in tl_dict['drills']:
|
||||||
try:
|
try:
|
||||||
points[tool].append(drill_pt)
|
points[tool_key].append(drill_pt)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
points[tool] = [drill_pt]
|
points[tool_key] = [drill_pt]
|
||||||
log.debug("Found %d TOOLS with drills." % len(points))
|
log.debug("Found %d TOOLS with drills." % len(points))
|
||||||
|
|
||||||
|
# add slots as drills
|
||||||
|
should_add_last_pt = self.t_ui.last_drill_cb.get_value()
|
||||||
|
if slots_as_drills:
|
||||||
|
for tool_key, tl_dict in self.excellon_tools.items():
|
||||||
|
if tool_key in sel_tools:
|
||||||
|
if self.app.abort_flag:
|
||||||
|
# graceful abort requested by the user
|
||||||
|
raise grace
|
||||||
|
|
||||||
|
overlap = 1 - (self.t_ui.drill_overlap_entry.get_value() / 100.0)
|
||||||
|
drill_overlap = 0.0
|
||||||
|
for i in sorted_tools:
|
||||||
|
if i[0] == tool_key:
|
||||||
|
slot_tool_dia = i[1]
|
||||||
|
drill_overlap = overlap * slot_tool_dia
|
||||||
|
break
|
||||||
|
|
||||||
|
new_drills = []
|
||||||
|
if 'slots' in tl_dict and tl_dict['slots']:
|
||||||
|
for slot in tl_dict['slots']:
|
||||||
|
new_drills += self.process_slot_as_drills(slot=slot, overlap=drill_overlap,
|
||||||
|
add_last_pt=should_add_last_pt)
|
||||||
|
if new_drills:
|
||||||
|
try:
|
||||||
|
points[tool_key] += new_drills
|
||||||
|
except Exception:
|
||||||
|
points[tool_key] = new_drills
|
||||||
|
log.debug("Found %d TOOLS with drills after converting slots to drills." % len(points))
|
||||||
|
|
||||||
# check if there are drill points in the exclusion areas.
|
# check if there are drill points in the exclusion areas.
|
||||||
# If we find any within the exclusion areas return 'fail'
|
# If we find any within the exclusion areas return 'fail'
|
||||||
for tool in points:
|
for tool_key in points:
|
||||||
for pt in points[tool]:
|
for pt in points[tool_key]:
|
||||||
for area in self.app.exc_areas.exclusion_areas_storage:
|
for area in self.app.exc_areas.exclusion_areas_storage:
|
||||||
pt_buf = pt.buffer(self.exc_tools[tool]['tooldia'] / 2.0)
|
pt_buf = pt.buffer(self.exc_tools[tool_key]['tooldia'] / 2.0)
|
||||||
if pt_buf.within(area['shape']) or pt_buf.intersects(area['shape']):
|
if pt_buf.within(area['shape']) or pt_buf.intersects(area['shape']):
|
||||||
self.app.inform.emit("[ERROR_NOTCL] %s" % _("Failed. Drill points inside the exclusion zones."))
|
self.app.inform.emit("[ERROR_NOTCL] %s" % _("Failed. Drill points inside the exclusion zones."))
|
||||||
return 'fail'
|
return 'fail'
|
||||||
|
@ -1694,15 +1748,15 @@ class ToolDrilling(AppTool, Excellon):
|
||||||
sol_geo = []
|
sol_geo = []
|
||||||
|
|
||||||
drill_no = 0
|
drill_no = 0
|
||||||
if 'drills' in obj.tools[to_ol]:
|
if 'drills' in self.excellon_tools[to_ol]:
|
||||||
drill_no = len(obj.tools[to_ol]['drills'])
|
drill_no = len(self.excellon_tools[to_ol]['drills'])
|
||||||
for drill in obj.tools[to_ol]['drills']:
|
for drill in self.excellon_tools[to_ol]['drills']:
|
||||||
sol_geo.append(drill.buffer((it[1] / 2.0), resolution=job_obj.geo_steps_per_circle))
|
sol_geo.append(drill.buffer((it[1] / 2.0), resolution=job_obj.geo_steps_per_circle))
|
||||||
|
|
||||||
slot_no = 0
|
slot_no = 0
|
||||||
if 'slots' in obj.tools[to_ol]:
|
if 'slots' in self.excellon_tools[to_ol]:
|
||||||
slot_no = len(obj.tools[to_ol]['slots'])
|
slot_no = len(self.excellon_tools[to_ol]['slots'])
|
||||||
for slot in obj.tools[to_ol]['slots']:
|
for slot in self.excellon_tools[to_ol]['slots']:
|
||||||
start = (slot[0].x, slot[0].y)
|
start = (slot[0].x, slot[0].y)
|
||||||
stop = (slot[1].x, slot[1].y)
|
stop = (slot[1].x, slot[1].y)
|
||||||
sol_geo.append(
|
sol_geo.append(
|
||||||
|
@ -1711,13 +1765,13 @@ class ToolDrilling(AppTool, Excellon):
|
||||||
)
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
z_off = float(obj.tools[it[0]]['data']['offset']) * (-1)
|
z_off = float(self.excellon_tools[it[0]]['data']['offset']) * (-1)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
z_off = 0
|
z_off = 0
|
||||||
|
|
||||||
default_data = {}
|
default_data = {}
|
||||||
for k, v in list(obj.options.items()):
|
for kk, vv in list(obj.options.items()):
|
||||||
default_data[k] = deepcopy(v)
|
default_data[kk] = deepcopy(vv)
|
||||||
|
|
||||||
job_obj.exc_cnc_tools[it[1]] = {}
|
job_obj.exc_cnc_tools[it[1]] = {}
|
||||||
job_obj.exc_cnc_tools[it[1]]['tool'] = it[0]
|
job_obj.exc_cnc_tools[it[1]]['tool'] = it[0]
|
||||||
|
@ -1784,9 +1838,21 @@ class ToolDrilling(AppTool, Excellon):
|
||||||
add_start_gcode = True
|
add_start_gcode = True
|
||||||
for tool in sel_tools:
|
for tool in sel_tools:
|
||||||
tool_points = points[tool]
|
tool_points = points[tool]
|
||||||
used_tooldia = obj.tools[tool]['tooldia']
|
used_tooldia = self.excellon_tools[tool]['tooldia']
|
||||||
|
|
||||||
tool_gcode = job_obj.gcode_from_excellon_by_tool(tool, tool_points, obj.tools,
|
if slots_as_drills is True:
|
||||||
|
nr_drills = len(points[tool])
|
||||||
|
nr_slots = 0
|
||||||
|
job_obj.exc_cnc_tools[used_tooldia]['nr_drills'] = nr_drills
|
||||||
|
job_obj.exc_cnc_tools[used_tooldia]['nr_slots'] = nr_slots
|
||||||
|
|
||||||
|
for line in range(1, len(job_obj.options['Tools_in_use'])):
|
||||||
|
if float('%.*f' % (self.decimals, float(job_obj.options['Tools_in_use'][line][1]))) == \
|
||||||
|
float('%.*f' % (self.decimals, used_tooldia)):
|
||||||
|
job_obj.options['Tools_in_use'][line][2] = str(nr_drills)
|
||||||
|
job_obj.options['Tools_in_use'][line][3] = str(nr_slots)
|
||||||
|
|
||||||
|
tool_gcode = job_obj.gcode_from_excellon_by_tool(tool, tool_points, self.excellon_tools,
|
||||||
opt_type=used_excellon_optimization_type,
|
opt_type=used_excellon_optimization_type,
|
||||||
toolchange=True)
|
toolchange=True)
|
||||||
if add_start_gcode is True:
|
if add_start_gcode is True:
|
||||||
|
@ -1807,7 +1873,7 @@ class ToolDrilling(AppTool, Excellon):
|
||||||
tool_points += points[tool]
|
tool_points += points[tool]
|
||||||
|
|
||||||
used_tool = sel_tools[0]
|
used_tool = sel_tools[0]
|
||||||
used_tooldia = obj.tools[used_tool]['tooldia']
|
used_tooldia = self.excellon_tools[used_tool]['tooldia']
|
||||||
|
|
||||||
# those are used by the preprocessors to display data on the toolchange line
|
# those are used by the preprocessors to display data on the toolchange line
|
||||||
job_obj.tool = str(used_tool)
|
job_obj.tool = str(used_tool)
|
||||||
|
@ -1817,6 +1883,7 @@ class ToolDrilling(AppTool, Excellon):
|
||||||
# process all in one go with no toolchange and with only one tool
|
# process all in one go with no toolchange and with only one tool
|
||||||
nr_drills = 0
|
nr_drills = 0
|
||||||
nr_slots = 0
|
nr_slots = 0
|
||||||
|
if slots_as_drills is False:
|
||||||
for line in range(1, len(tool_table_items)):
|
for line in range(1, len(tool_table_items)):
|
||||||
# we may have exception ValueError if there are no drills/slots for the current tool/line
|
# we may have exception ValueError if there are no drills/slots for the current tool/line
|
||||||
try:
|
try:
|
||||||
|
@ -1827,6 +1894,15 @@ class ToolDrilling(AppTool, Excellon):
|
||||||
nr_slots += int(tool_table_items[line][3])
|
nr_slots += int(tool_table_items[line][3])
|
||||||
except ValueError:
|
except ValueError:
|
||||||
pass
|
pass
|
||||||
|
else:
|
||||||
|
# if the slots are converted to drills then make slots number = 0 and count the converted drills
|
||||||
|
for t in points:
|
||||||
|
nr_drills += len(points[t])
|
||||||
|
|
||||||
|
nr_slots = 0
|
||||||
|
job_obj.exc_cnc_tools[used_tooldia]['nr_drills'] = nr_drills
|
||||||
|
job_obj.exc_cnc_tools[used_tooldia]['nr_slots'] = nr_slots
|
||||||
|
|
||||||
tool_table_items.clear()
|
tool_table_items.clear()
|
||||||
tool_table_items = [[str(used_tool), str(used_tooldia), str(nr_drills), str(nr_slots)]]
|
tool_table_items = [[str(used_tool), str(used_tooldia), str(nr_drills), str(nr_slots)]]
|
||||||
tool_table_items.insert(0, [_("Tool_nr"), _("Diameter"), _("Drills_Nr"), _("Slots_Nr")])
|
tool_table_items.insert(0, [_("Tool_nr"), _("Diameter"), _("Drills_Nr"), _("Slots_Nr")])
|
||||||
|
@ -1836,7 +1912,7 @@ class ToolDrilling(AppTool, Excellon):
|
||||||
# TODO set the oldx and oldy to start values
|
# TODO set the oldx and oldy to start values
|
||||||
# add a Toolchange event here to load the first tool
|
# add a Toolchange event here to load the first tool
|
||||||
tool_gcode += job_obj.doformat(p.toolchange_code, toolchangexy=(job_obj.oldx, job_obj.oldy))
|
tool_gcode += job_obj.doformat(p.toolchange_code, toolchangexy=(job_obj.oldx, job_obj.oldy))
|
||||||
tool_gcode += job_obj.gcode_from_excellon_by_tool(used_tool, tool_points, obj.tools,
|
tool_gcode += job_obj.gcode_from_excellon_by_tool(used_tool, tool_points, self.excellon_tools,
|
||||||
opt_type=used_excellon_optimization_type,
|
opt_type=used_excellon_optimization_type,
|
||||||
toolchange=False)
|
toolchange=False)
|
||||||
job_obj.exc_cnc_tools[used_tooldia]['gcode'] = tool_gcode
|
job_obj.exc_cnc_tools[used_tooldia]['gcode'] = tool_gcode
|
||||||
|
@ -1874,6 +1950,7 @@ class ToolDrilling(AppTool, Excellon):
|
||||||
# #########################################################################################################
|
# #########################################################################################################
|
||||||
if job_obj.xy_end is None:
|
if job_obj.xy_end is None:
|
||||||
job_obj.xy_end = [job_obj.oldx, job_obj.oldy]
|
job_obj.xy_end = [job_obj.oldx, job_obj.oldy]
|
||||||
|
|
||||||
job_obj.measured_distance += abs(distance_euclidian(
|
job_obj.measured_distance += abs(distance_euclidian(
|
||||||
job_obj.oldx, job_obj.oldy, job_obj.xy_end[0], job_obj.xy_end[1])
|
job_obj.oldx, job_obj.oldy, job_obj.xy_end[0], job_obj.xy_end[1])
|
||||||
)
|
)
|
||||||
|
@ -1885,8 +1962,8 @@ class ToolDrilling(AppTool, Excellon):
|
||||||
# traveled_time because it is not always possible to determine the feedrate that the CNC machine uses
|
# traveled_time because it is not always possible to determine the feedrate that the CNC machine uses
|
||||||
# for G0 move (the fastest speed available to the CNC router). Although self.feedrate_rapids is used only
|
# for G0 move (the fastest speed available to the CNC router). Although self.feedrate_rapids is used only
|
||||||
# with Marlin preprocessor and derivatives.
|
# with Marlin preprocessor and derivatives.
|
||||||
job_obj.routing_time = (job_obj.measured_down_distance + job_obj.measured_up_to_zero_distance) / \
|
job_obj.routing_time = \
|
||||||
job_obj.feedrate
|
(job_obj.measured_down_distance + job_obj.measured_up_to_zero_distance) / job_obj.feedrate
|
||||||
lift_time = job_obj.measured_lift_distance / job_obj.feedrate_rapid
|
lift_time = job_obj.measured_lift_distance / job_obj.feedrate_rapid
|
||||||
traveled_time = job_obj.measured_distance / job_obj.feedrate_rapid
|
traveled_time = job_obj.measured_distance / job_obj.feedrate_rapid
|
||||||
job_obj.routing_time += lift_time + traveled_time
|
job_obj.routing_time += lift_time + traveled_time
|
||||||
|
@ -2242,7 +2319,7 @@ class DrillingUI:
|
||||||
|
|
||||||
self.drill_overlap_entry = FCDoubleSpinner(callback=self.confirmation_message)
|
self.drill_overlap_entry = FCDoubleSpinner(callback=self.confirmation_message)
|
||||||
self.drill_overlap_entry.set_precision(self.decimals)
|
self.drill_overlap_entry.set_precision(self.decimals)
|
||||||
self.drill_overlap_entry.set_range(0.0, 9999.9999)
|
self.drill_overlap_entry.set_range(0.0, 100.0000)
|
||||||
self.drill_overlap_entry.setSingleStep(0.1)
|
self.drill_overlap_entry.setSingleStep(0.1)
|
||||||
|
|
||||||
self.drill_overlap_entry.setObjectName("e_drill_slots_overlap")
|
self.drill_overlap_entry.setObjectName("e_drill_slots_overlap")
|
||||||
|
|
|
@ -2890,7 +2890,6 @@ class CNCjob(Geometry):
|
||||||
self.app.inform.emit('[WARNING] %s.' % _("The Cut Z parameter is zero. There will be no cut, aborting"))
|
self.app.inform.emit('[WARNING] %s.' % _("The Cut Z parameter is zero. There will be no cut, aborting"))
|
||||||
return 'fail'
|
return 'fail'
|
||||||
|
|
||||||
|
|
||||||
def gcode_from_excellon_by_tool(self, tool, points, tools, opt_type='T', toolchange=False):
|
def gcode_from_excellon_by_tool(self, tool, points, tools, opt_type='T', toolchange=False):
|
||||||
"""
|
"""
|
||||||
Creates Gcode for this object from an Excellon object
|
Creates Gcode for this object from an Excellon object
|
||||||
|
@ -2922,7 +2921,7 @@ class CNCjob(Geometry):
|
||||||
|
|
||||||
tool_dict = tools[tool]['data']
|
tool_dict = tools[tool]['data']
|
||||||
# check if it has drills
|
# check if it has drills
|
||||||
if not tools[tool]['drills']:
|
if not points:
|
||||||
log.debug("Failed. No drills for tool: %s" % str(tool))
|
log.debug("Failed. No drills for tool: %s" % str(tool))
|
||||||
return 'fail'
|
return 'fail'
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue