From 949c26537834bc95b18fa6a86c215ad62dde9752 Mon Sep 17 00:00:00 2001 From: Marius Stanciu Date: Tue, 16 Jun 2020 03:47:26 +0300 Subject: [PATCH] - changed the data structure for the Excellon object; modified the Excellon parser and the Excellon object class - fixed partially the Excellon Editor to work with the new data structure - fixed Excellon export to work with the new data structure - fixed all transformations in the Excellon object attributes; still need to fix the App Tools that creates or use Exellon objects --- CHANGELOG.md | 7 + appEditors/AppExcEditor.py | 134 ++++--- appGUI/GUIElements.py | 2 +- appObjects/FlatCAMExcellon.py | 336 +++++++---------- appParsers/ParseExcellon.py | 482 +++++++++++++----------- appTools/ToolDblSided.py | 17 +- appTools/ToolDrilling.py | 91 ++--- appTools/ToolExtractDrills.py | 4 +- appTools/ToolProperties.py | 12 +- appTools/ToolPunchGerber.py | 2 +- app_Main.py | 47 ++- camlib.py | 204 +++++----- preprocessors/Berta_CNC.py | 2 +- preprocessors/ISEL_CNC.py | 2 +- preprocessors/ISEL_ICP_CNC.py | 2 +- preprocessors/Marlin.py | 2 +- preprocessors/Repetier.py | 2 +- preprocessors/Toolchange_Custom.py | 2 +- preprocessors/Toolchange_Manual.py | 2 +- preprocessors/Toolchange_Probe_MACH3.py | 2 +- preprocessors/default.py | 2 +- preprocessors/grbl_11.py | 2 +- preprocessors/line_xyz.py | 2 +- tclCommands/TclCommandDrillcncjob.py | 14 +- 24 files changed, 691 insertions(+), 683 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b23bf1d0..f9d2433d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,13 @@ CHANGELOG for FlatCAM beta ================================================= +16.06.2020 + +- changed the data structure for the Excellon object; modified the Excellon parser and the Excellon object class +- fixed partially the Excellon Editor to work with the new data structure +- fixed Excellon export to work with the new data structure +- fixed all transformations in the Excellon object attributes; still need to fix the App Tools that creates or use Exellon objects + 15.06.2020 - in Paint Tool and NCC Tool updated the way the selected tools were processed and made sure that the Tools Table rows are counted only once in the processing diff --git a/appEditors/AppExcEditor.py b/appEditors/AppExcEditor.py index dc251c0c..26b80931 100644 --- a/appEditors/AppExcEditor.py +++ b/appEditors/AppExcEditor.py @@ -390,8 +390,7 @@ class FCSlot(FCShapeTool): item = self.draw_app.tools_table_exc.item((self.draw_app.last_tool_selected - 1), 1) self.draw_app.tools_table_exc.setCurrentItem(item) except KeyError: - self.draw_app.app.inform.emit('[WARNING_NOTCL] %s' % - _("To add a slot first select a tool")) + self.draw_app.app.inform.emit('[WARNING_NOTCL] %s' % _("To add a slot first select a tool")) self.draw_app.select_tool("drill_select") return @@ -2059,9 +2058,7 @@ class AppExcEditor(QtCore.QObject): self.sorted_diameters = [] - self.new_drills = [] self.new_tools = {} - self.new_slots = [] # dictionary to store the tool_row and diameters in Tool_table # it will be updated everytime self.build_ui() is called @@ -2261,30 +2258,33 @@ class AppExcEditor(QtCore.QObject): self.tool2tooldia.clear() # build the self.points_edit dict {dimaters: [point_list]} - for drill in self.exc_obj.drills: - if drill['tool'] in self.exc_obj.tools: - tool_dia = float('%.*f' % (self.decimals, self.exc_obj.tools[drill['tool']]['C'])) + for tool, tool_dict in self.exc_obj.tools.items(): + tool_dia = float('%.*f' % (self.decimals, self.exc_obj.tools[tool]['tooldia'])) - try: - self.points_edit[tool_dia].append(drill['point']) - except KeyError: - self.points_edit[tool_dia] = [drill['point']] + if 'drills' in tool_dict and tool_dict['drills']: + for drill in tool_dict['drills']: + try: + self.points_edit[tool_dia].append(drill) + except KeyError: + self.points_edit[tool_dia] = [drill] # build the self.slot_points_edit dict {dimaters: {"start": Point, "stop": Point}} - for slot in self.exc_obj.slots: - if slot['tool'] in self.exc_obj.tools: - tool_dia = float('%.*f' % (self.decimals, self.exc_obj.tools[slot['tool']]['C'])) + for tool, tool_dict in self.exc_obj.tools.items(): + tool_dia = float('%.*f' % (self.decimals, self.exc_obj.tools[tool]['tooldia'])) + + if 'slots' in tool_dict and tool_dict['slots']: + for slot in tool_dict['slots']: + try: + self.slot_points_edit[tool_dia].append({ + "start": slot[0], + "stop": slot[1] + }) + except KeyError: + self.slot_points_edit[tool_dia] = [{ + "start": slot[0], + "stop": slot[1] + }] - try: - self.slot_points_edit[tool_dia].append({ - "start": slot["start"], - "stop": slot["stop"] - }) - except KeyError: - self.slot_points_edit[tool_dia] = [{ - "start": slot["start"], - "stop": slot["stop"] - }] # update the olddia_newdia dict to make sure we have an updated state of the tool_table for key in self.points_edit: @@ -2309,7 +2309,7 @@ class AppExcEditor(QtCore.QObject): # Excellon file has no tool diameter information. In this case do not order the diameter in the table # but use the real order found in the exc_obj.tools for k, v in self.exc_obj.tools.items(): - tool_dia = float('%.*f' % (self.decimals, v['C'])) + tool_dia = float('%.*f' % (self.decimals, v['tooldia'])) self.tool2tooldia[int(k)] = tool_dia # Init appGUI @@ -2385,21 +2385,27 @@ class AppExcEditor(QtCore.QObject): self.tot_drill_cnt += drill_cnt - try: - # Find no of slots for the current tool - for slot in self.slot_points_edit: - if slot['tool'] == tool_no: - slot_cnt += 1 + # try: + # # Find no of slots for the current tool + # for slot in self.slot_points_edit: + # if float(slot) == tool_no: + # slot_cnt += 1 + # + # self.tot_slot_cnt += slot_cnt + # except AttributeError: + # # log.debug("No slots in the Excellon file") + # # Find no of slots for the current tool + # for tool_dia in self.slot_points_edit: + # if float(tool_dia) == tool_no: + # slot_cnt = len(self.slot_points_edit[tool_dia]) + # + # self.tot_slot_cnt += slot_cnt - self.tot_slot_cnt += slot_cnt - except AttributeError: - # log.debug("No slots in the Excellon file") - # Find no of slots for the current tool - for tool_dia in self.slot_points_edit: - if float(tool_dia) == tool_no: - slot_cnt = len(self.slot_points_edit[tool_dia]) + for tool_dia in self.slot_points_edit: + if float(tool_dia) == tool_no: + slot_cnt = len(self.slot_points_edit[tool_dia]) - self.tot_slot_cnt += slot_cnt + self.tot_slot_cnt += slot_cnt idd = QtWidgets.QTableWidgetItem('%d' % int(tool_id)) idd.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) @@ -3141,6 +3147,10 @@ class AppExcEditor(QtCore.QObject): poly = x.geo poly = poly.buffer(-radius) + if not poly.is_valid or poly.is_empty: + print("Polygon not valid: %s" % str(poly.wkt)) + continue + xmin, ymin, xmax, ymax = poly.bounds line_one = LineString([(xmin, ymin), (xmax, ymax)]).intersection(poly).length line_two = LineString([(xmin, ymax), (xmax, ymin)]).intersection(poly).length @@ -3197,59 +3207,61 @@ class AppExcEditor(QtCore.QObject): current_tool += 1 # create the self.tools for the new Excellon object (the one with edited content) - name = str(current_tool) - spec = {"C": float(tool_dia[0])} - self.new_tools[name] = spec + if current_tool not in self.new_tools: + self.new_tools[current_tool] = {} + self.new_tools[current_tool]['tooldia'] = float(tool_dia[0]) # add in self.tools the 'solid_geometry' key, the value (a list) is populated below - self.new_tools[name]['solid_geometry'] = [] + self.new_tools[current_tool]['solid_geometry'] = [] # create the self.drills for the new Excellon object (the one with edited content) for point in tool_dia[1]: - self.new_drills.append( - { - 'point': Point(point), - 'tool': str(current_tool) - } - ) + try: + self.new_tools[current_tool]['drills'].append(Point(point)) + except KeyError: + self.new_tools[current_tool]['drills'] = [Point(point)] + # repopulate the 'solid_geometry' for each tool poly = Point(point).buffer(float(tool_dia[0]) / 2.0, int(int(exc_obj.geo_steps_per_circle) / 4)) - self.new_tools[name]['solid_geometry'].append(poly) + self.new_tools[current_tool]['solid_geometry'].append(poly) ordered_edited_slot_points = sorted(zip(edited_slot_points.keys(), edited_slot_points.values())) for tool_dia in ordered_edited_slot_points: tool_exist_flag = False for tool in self.new_tools: - if tool_dia[0] == self.new_tools[tool]["C"]: + if tool_dia[0] == self.new_tools[tool]["tooldia"]: current_tool = tool tool_exist_flag = True break if tool_exist_flag is False: current_tool += 1 + # create the self.tools for the new Excellon object (the one with edited content) - name = str(current_tool) - spec = {"C": float(tool_dia[0])} - self.new_tools[name] = spec + if current_tool not in self.new_tools: + self.new_tools[current_tool] = {} + self.new_tools[current_tool]['tooldia'] = float(tool_dia[0]) # add in self.tools the 'solid_geometry' key, the value (a list) is populated below - self.new_tools[name]['solid_geometry'] = [] + self.new_tools[current_tool]['solid_geometry'] = [] # create the self.slots for the new Excellon object (the one with edited content) for coord_dict in tool_dia[1]: - self.new_slots.append( - { - 'start': Point(coord_dict['start']), - 'stop': Point(coord_dict['stop']), - 'tool': str(current_tool) - } + slot = ( + Point(coord_dict['start']), + Point(coord_dict['stop']) ) + try: + self.new_tools[current_tool]['slots'].append(slot) + except KeyError: + self.new_tools[current_tool]['slots'] = [slot] + # repopulate the 'solid_geometry' for each tool poly = LineString([coord_dict['start'], coord_dict['stop']]).buffer( float(tool_dia[0]) / 2.0, int(int(exc_obj.geo_steps_per_circle) / 4) ) - self.new_tools[str(current_tool)]['solid_geometry'].append(poly) + self.new_tools[current_tool]['solid_geometry'].append(poly) if self.is_modified is True: if "_edit" in self.edited_obj_name: diff --git a/appGUI/GUIElements.py b/appGUI/GUIElements.py index d717e9a3..684b970a 100644 --- a/appGUI/GUIElements.py +++ b/appGUI/GUIElements.py @@ -682,7 +682,7 @@ class NumericalEvalEntry(EvalEntry): return evaled -class NumericalEvalTupleEntry(FCEntry): +class NumericalEvalTupleEntry(EvalEntry): """ Will return a text value. Accepts only float numbers and formulas using the operators: /,*,+,-,% """ diff --git a/appObjects/FlatCAMExcellon.py b/appObjects/FlatCAMExcellon.py index bd3636a5..6b33d477 100644 --- a/appObjects/FlatCAMExcellon.py +++ b/appObjects/FlatCAMExcellon.py @@ -138,7 +138,7 @@ class ExcellonObject(FlatCAMObj, Excellon): self.ser_attrs += ['options', 'kind'] @staticmethod - def merge(exc_list, exc_final, decimals=None): + def merge(exc_list, exc_final, decimals=None, fuse_tools=True): """ Merge Excellon objects found in exc_list parameter into exc_final object. Options are always copied from source . @@ -153,31 +153,31 @@ class ExcellonObject(FlatCAMObj, Excellon): :type exc_list: list :param exc_final: Destination ExcellonObject object. :type exc_final: class + :param decimals: The number of decimals to be used for diameters + :type decimals: int + :param fuse_tools: If True will try to fuse tools of the same diameter for the Excellon objects + :type fuse_tools: bool :return: None """ + if exc_final.tools is None: + exc_final.tools = {} + if decimals is None: decimals = 4 decimals_exc = decimals - # flag to signal that we need to reorder the tools dictionary and drills and slots lists - flag_order = False - try: flattened_list = list(itertools.chain(*exc_list)) except TypeError: flattened_list = exc_list - # this dict will hold the unique tool diameters found in the exc_list objects as the dict keys and the dict - # values will be list of Shapely Points; for drills - custom_dict_drills = defaultdict(list) - - # this dict will hold the unique tool diameters found in the exc_list objects as the dict keys and the dict - # values will be list of Shapely Points; for slots - custom_dict_slots = defaultdict(list) - + new_tools = {} + total_geo = [] + toolid = 0 for exc in flattened_list: # copy options of the current excellon obj to the final excellon obj + # only the last object options will survive for option in exc.options: if option != 'name': try: @@ -185,129 +185,47 @@ class ExcellonObject(FlatCAMObj, Excellon): except Exception: exc.app.log.warning("Failed to copy option.", option) - for drill in exc.drills: - exc_tool_dia = float('%.*f' % (decimals_exc, exc.tools[drill['tool']]['C'])) - custom_dict_drills[exc_tool_dia].append(drill['point']) - - for slot in exc.slots: - exc_tool_dia = float('%.*f' % (decimals_exc, exc.tools[slot['tool']]['C'])) - custom_dict_slots[exc_tool_dia].append([slot['start'], slot['stop']]) + for tool in exc.tools: + toolid += 1 + new_tools[toolid] = exc.tools[tool] + exc_final.tools = deepcopy(new_tools) # add the zeros and units to the exc_final object exc_final.zeros = exc.zeros exc_final.units = exc.units + total_geo += exc.solid_geometry - # ########################################## - # Here we add data to the exc_final object # - # ########################################## + exc_final.solid_geometry = total_geo - # variable to make tool_name for the tools - current_tool = 0 - # The tools diameter are now the keys in the drill_dia dict and the values are the Shapely Points in case of - # drills - for tool_dia in custom_dict_drills: - # we create a tool name for each key in the drill_dia dict (the key is a unique drill diameter) - current_tool += 1 + fused_tools_dict = {} + if exc_final.tools and fuse_tools: + toolid = 0 + for tool, tool_dict in exc_final.tools.items(): + current_tooldia = float('%.*f' % (decimals_exc, tool_dict['tooldia'])) + toolid += 1 - tool_name = str(current_tool) - spec = {"C": float(tool_dia)} - exc_final.tools[tool_name] = spec + # calculate all diameters in fused_tools_dict + all_dia = [] + if fused_tools_dict: + for f_tool in fused_tools_dict: + all_dia.append(float('%.*f' % (decimals_exc, fused_tools_dict[f_tool]['tooldia']))) - # rebuild the drills list of dict's that belong to the exc_final object - for point in custom_dict_drills[tool_dia]: - exc_final.drills.append( - { - "point": point, - "tool": str(current_tool) - } - ) - - # The tools diameter are now the keys in the drill_dia dict and the values are a list ([start, stop]) - # of two Shapely Points in case of slots - for tool_dia in custom_dict_slots: - # we create a tool name for each key in the slot_dia dict (the key is a unique slot diameter) - # but only if there are no drills - if not exc_final.tools: - current_tool += 1 - tool_name = str(current_tool) - spec = {"C": float(tool_dia)} - exc_final.tools[tool_name] = spec - else: - dia_list = [] - for v in exc_final.tools.values(): - dia_list.append(float(v["C"])) - - if tool_dia not in dia_list: - flag_order = True - - current_tool = len(dia_list) + 1 - tool_name = str(current_tool) - spec = {"C": float(tool_dia)} - exc_final.tools[tool_name] = spec - - else: - for k, v in exc_final.tools.items(): - if v["C"] == tool_dia: - current_tool = int(k) + if current_tooldia in all_dia: + # find tool for current_tooldia in fuse_tools + t = None + for f_tool in fused_tools_dict: + if fused_tools_dict[f_tool]['tooldia'] == current_tooldia: + t = f_tool break + if t: + fused_tools_dict[t]['drills'] += tool_dict['drills'] + fused_tools_dict[t]['slots'] += tool_dict['slots'] + fused_tools_dict[t]['solid_geometry'] += tool_dict['solid_geometry'] + else: + fused_tools_dict[toolid] = tool_dict + fused_tools_dict[toolid]['tooldia'] = current_tooldia - # rebuild the slots list of dict's that belong to the exc_final object - for point in custom_dict_slots[tool_dia]: - exc_final.slots.append( - { - "start": point[0], - "stop": point[1], - "tool": str(current_tool) - } - ) - - # flag_order == True means that there was an slot diameter not in the tools and we also have drills - # and the new tool was added to self.tools therefore we need to reorder the tools and drills and slots - current_tool = 0 - if flag_order is True: - dia_list = [] - temp_drills = [] - temp_slots = [] - temp_tools = {} - for v in exc_final.tools.values(): - dia_list.append(float(v["C"])) - dia_list.sort() - for ordered_dia in dia_list: - current_tool += 1 - tool_name_temp = str(current_tool) - spec_temp = {"C": float(ordered_dia)} - temp_tools[tool_name_temp] = spec_temp - - for drill in exc_final.drills: - exc_tool_dia = float('%.*f' % (decimals_exc, exc_final.tools[drill['tool']]['C'])) - if exc_tool_dia == ordered_dia: - temp_drills.append( - { - "point": drill["point"], - "tool": str(current_tool) - } - ) - - for slot in exc_final.slots: - slot_tool_dia = float('%.*f' % (decimals_exc, exc_final.tools[slot['tool']]['C'])) - if slot_tool_dia == ordered_dia: - temp_slots.append( - { - "start": slot["start"], - "stop": slot["stop"], - "tool": str(current_tool) - } - ) - - # delete the exc_final tools, drills and slots - exc_final.tools = {} - exc_final.drills[:] = [] - exc_final.slots[:] = [] - - # update the exc_final tools, drills and slots with the ordered values - exc_final.tools = temp_tools - exc_final.drills[:] = temp_drills - exc_final.slots[:] = temp_slots + exc_final.tools = fused_tools_dict # create the geometry for the exc_final object exc_final.create_geometry() @@ -351,7 +269,7 @@ class ExcellonObject(FlatCAMObj, Excellon): sort = [] for k, v in list(self.tools.items()): - sort.append((k, v.get('C'))) + sort.append((k, v['tooldia'])) sorted_tools = sorted(sort, key=lambda t1: t1[1]) tools = [i[0] for i in sorted_tools] @@ -370,23 +288,23 @@ class ExcellonObject(FlatCAMObj, Excellon): slot_cnt = 0 # variable to store the nr of slots per tool # Find no of drills for the current tool - for drill in self.drills: - if drill['tool'] == tool_no: - drill_cnt += 1 - + try: + drill_cnt = len(self.tools[tool_no]['drills']) + except KeyError: + drill_cnt = 0 self.tot_drill_cnt += drill_cnt # Find no of slots for the current tool - for slot in self.slots: - if slot['tool'] == tool_no: - slot_cnt += 1 - + try: + slot_cnt = len(self.tools[tool_no]['slots']) + except KeyError: + slot_cnt = 0 self.tot_slot_cnt += slot_cnt exc_id_item = QtWidgets.QTableWidgetItem('%d' % int(tool_no)) exc_id_item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) - dia_item = QtWidgets.QTableWidgetItem('%.*f' % (self.decimals, self.tools[tool_no]['C'])) + dia_item = QtWidgets.QTableWidgetItem('%.*f' % (self.decimals, self.tools[tool_no]['tooldia'])) dia_item.setFlags(QtCore.Qt.ItemIsEnabled) drill_count_item = QtWidgets.QTableWidgetItem('%d' % drill_cnt) @@ -508,14 +426,26 @@ class ExcellonObject(FlatCAMObj, Excellon): self.ui.tools_table.setMinimumHeight(self.ui.tools_table.getHeight()) self.ui.tools_table.setMaximumHeight(self.ui.tools_table.getHeight()) - if not self.drills: + # find if we have drills: + has_drills = None + for tt in self.tools: + if 'drills' in self.tools[tt] and self.tools[tt]['drills']: + has_drills = True + break + if has_drills is None: self.ui.tooldia_entry.hide() self.ui.generate_milling_button.hide() else: self.ui.tooldia_entry.show() self.ui.generate_milling_button.show() - if not self.slots: + # find if we have slots + has_slots = None + for tt in self.tools: + if 'slots' in self.tools[tt] and self.tools[tt]['slots']: + has_slots = True + break + if has_slots is None: self.ui.slot_tooldia_entry.hide() self.ui.generate_milling_slots_button.hide() else: @@ -962,7 +892,7 @@ class ExcellonObject(FlatCAMObj, Excellon): :rtype: list """ - return [str(x.text()) for x in self.ui.tools_table.selectedItems()] + return [x.text() for x in self.ui.tools_table.selectedItems()] def get_selected_tools_table_items(self): """ @@ -1017,23 +947,37 @@ class ExcellonObject(FlatCAMObj, Excellon): excellon_code = '' # store here if the file has slots, return 1 if any slots, 0 if only drills - has_slots = 0 + slots_in_file = 0 + + # find if we have drills: + has_drills = None + for tt in self.tools: + if 'drills' in self.tools[tt] and self.tools[tt]['drills']: + has_drills = True + break + # find if we have slots: + has_slots = None + for tt in self.tools: + if 'slots' in self.tools[tt] and self.tools[tt]['slots']: + has_slots = True + slots_in_file = 1 + break # drills processing try: - if self.drills: + if has_drills: length = whole + fract for tool in self.tools: excellon_code += 'T0%s\n' % str(tool) if int(tool) < 10 else 'T%s\n' % str(tool) - for drill in self.drills: - if form == 'dec' and tool == drill['tool']: - drill_x = drill['point'].x * factor - drill_y = drill['point'].y * factor + for drill in self.tools[tool]['drills']: + if form == 'dec': + drill_x = drill.x * factor + drill_y = drill.y * factor excellon_code += "X{:.{dec}f}Y{:.{dec}f}\n".format(drill_x, drill_y, dec=fract) - elif e_zeros == 'LZ' and tool == drill['tool']: - drill_x = drill['point'].x * factor - drill_y = drill['point'].y * factor + elif e_zeros == 'LZ': + drill_x = drill.x * factor + drill_y = drill.y * factor exc_x_formatted = "{:.{dec}f}".format(drill_x, dec=fract) exc_y_formatted = "{:.{dec}f}".format(drill_y, dec=fract) @@ -1053,9 +997,9 @@ class ExcellonObject(FlatCAMObj, Excellon): excellon_code += "X{xform}Y{yform}\n".format(xform=exc_x_formatted, yform=exc_y_formatted) - elif tool == drill['tool']: - drill_x = drill['point'].x * factor - drill_y = drill['point'].y * factor + else: + drill_x = drill.x * factor + drill_y = drill.y * factor exc_x_formatted = "{:.{dec}f}".format(drill_x, dec=fract).replace('.', '') exc_y_formatted = "{:.{dec}f}".format(drill_y, dec=fract).replace('.', '') @@ -1071,8 +1015,7 @@ class ExcellonObject(FlatCAMObj, Excellon): # slots processing try: - if self.slots: - has_slots = 1 + if has_slots: for tool in self.tools: excellon_code += 'G05\n' @@ -1081,12 +1024,12 @@ class ExcellonObject(FlatCAMObj, Excellon): else: excellon_code += 'T' + str(tool) + '\n' - for slot in self.slots: - if form == 'dec' and tool == slot['tool']: - start_slot_x = slot['start'].x * factor - start_slot_y = slot['start'].y * factor - stop_slot_x = slot['stop'].x * factor - stop_slot_y = slot['stop'].y * factor + for slot in self.tools[tool]['slots']: + if form == 'dec': + start_slot_x = slot.x * factor + start_slot_y = slot.y * factor + stop_slot_x = slot.x * factor + stop_slot_y = slot.y * factor if slot_type == 'routing': excellon_code += "G00X{:.{dec}f}Y{:.{dec}f}\nM15\n".format(start_slot_x, start_slot_y, @@ -1099,11 +1042,11 @@ class ExcellonObject(FlatCAMObj, Excellon): start_slot_x, start_slot_y, stop_slot_x, stop_slot_y, dec=fract ) - elif e_zeros == 'LZ' and tool == slot['tool']: - start_slot_x = slot['start'].x * factor - start_slot_y = slot['start'].y * factor - stop_slot_x = slot['stop'].x * factor - stop_slot_y = slot['stop'].y * factor + elif e_zeros == 'LZ': + start_slot_x = slot.x * factor + start_slot_y = slot.y * factor + stop_slot_x = slot.x * factor + stop_slot_y = slot.y * factor start_slot_x_formatted = "{:.{dec}f}".format(start_slot_x, dec=fract).replace('.', '') start_slot_y_formatted = "{:.{dec}f}".format(start_slot_y, dec=fract).replace('.', '') @@ -1139,11 +1082,11 @@ class ExcellonObject(FlatCAMObj, Excellon): xstart=start_slot_x_formatted, ystart=start_slot_y_formatted, xstop=stop_slot_x_formatted, ystop=stop_slot_y_formatted ) - elif tool == slot['tool']: - start_slot_x = slot['start'].x * factor - start_slot_y = slot['start'].y * factor - stop_slot_x = slot['stop'].x * factor - stop_slot_y = slot['stop'].y * factor + else: + start_slot_x = slot.x * factor + start_slot_y = slot.y * factor + stop_slot_x = slot.x * factor + stop_slot_y = slot.y * factor length = whole + fract start_slot_x_formatted = "{:.{dec}f}".format(start_slot_x, dec=fract).replace('.', '') @@ -1170,11 +1113,11 @@ class ExcellonObject(FlatCAMObj, Excellon): except Exception as e: log.debug(str(e)) - if not self.drills and not self.slots: + if not has_drills and not has_slots: log.debug("FlatCAMObj.ExcellonObject.export_excellon() --> Excellon Object is empty: no drills, no slots.") return 'fail' - return has_slots, excellon_code + return slots_in_file, excellon_code def generate_milling_drills(self, tools=None, outname=None, tooldia=None, plot=False, use_thread=False): """ @@ -1215,7 +1158,7 @@ class ExcellonObject(FlatCAMObj, Excellon): sort = [] for k, v in self.tools.items(): - sort.append((k, v.get('C'))) + sort.append((k, v['tooldia'])) sorted_tools = sorted(sort, key=lambda t1: t1[1]) if tools == "all": @@ -1223,19 +1166,15 @@ class ExcellonObject(FlatCAMObj, Excellon): log.debug("Tools 'all' and sorted are: %s" % str(tools)) if len(tools) == 0: - self.app.inform.emit('[ERROR_NOTCL] %s' % - _("Please select one or more tools from the list and try again.")) + self.app.inform.emit('[ERROR_NOTCL] %s' % _("Please select one or more tools from the list and try again.")) return False, "Error: No tools." for tool in tools: - if tooldia > self.tools[tool]["C"]: - self.app.inform.emit( - '[ERROR_NOTCL] %s %s: %s' % ( - _("Milling tool for DRILLS is larger than hole size. Cancelled."), - _("Tool"), - str(tool) - ) - ) + if tooldia > self.tools[tool]["tooldia"]: + mseg = '[ERROR_NOTCL] %s %s: %s' % (_("Milling tool for DRILLS is larger than hole size. Cancelled."), + _("Tool"), + str(tool)) + self.app.inform.emit(mseg) return False, "Error: Milling tool is larger than hole." def geo_init(geo_obj, app_obj): @@ -1266,15 +1205,13 @@ class ExcellonObject(FlatCAMObj, Excellon): # in case that the tool used has the same diameter with the hole, and since the maximum resolution # for FlatCAM is 6 decimals, # we add a tenth of the minimum value, meaning 0.0000001, which from our point of view is "almost zero" - for hole in self.drills: - if hole['tool'] in tools: - buffer_value = self.tools[hole['tool']]["C"] / 2 - tooldia / 2 + for tool in tools: + for drill in self.tools[tool]['drills']: + buffer_value = self.tools[tool]['tooldia'] / 2 - tooldia / 2 if buffer_value == 0: - geo_obj.solid_geometry.append( - Point(hole['point']).buffer(0.0000001).exterior) + geo_obj.solid_geometry.append(drill.buffer(0.0000001).exterior) else: - geo_obj.solid_geometry.append( - Point(hole['point']).buffer(buffer_value).exterior) + geo_obj.solid_geometry.append(drill.buffer(buffer_value).exterior) if use_thread: def geo_thread(a_obj): @@ -1329,7 +1266,7 @@ class ExcellonObject(FlatCAMObj, Excellon): sort = [] for k, v in self.tools.items(): - sort.append((k, v.get('C'))) + sort.append((k, v['tooldia'])) sorted_tools = sorted(sort, key=lambda t1: t1[1]) if tools == "all": @@ -1337,14 +1274,13 @@ class ExcellonObject(FlatCAMObj, Excellon): log.debug("Tools 'all' and sorted are: %s" % str(tools)) if len(tools) == 0: - self.app.inform.emit('[ERROR_NOTCL] %s' % - _("Please select one or more tools from the list and try again.")) + self.app.inform.emit('[ERROR_NOTCL] %s' % _("Please select one or more tools from the list and try again.")) return False, "Error: No tools." for tool in tools: # I add the 0.0001 value to account for the rounding error in converting from IN to MM and reverse adj_toolstable_tooldia = float('%.*f' % (self.decimals, float(tooldia))) - adj_file_tooldia = float('%.*f' % (self.decimals, float(self.tools[tool]["C"]))) + adj_file_tooldia = float('%.*f' % (self.decimals, float(self.tools[tool]["tooldia"]))) if adj_toolstable_tooldia > adj_file_tooldia + 0.0001: self.app.inform.emit('[ERROR_NOTCL] %s' % _("Milling tool for SLOTS is larger than hole size. Cancelled.")) @@ -1369,24 +1305,24 @@ class ExcellonObject(FlatCAMObj, Excellon): # in case that the tool used has the same diameter with the hole, and since the maximum resolution # for FlatCAM is 6 decimals, # we add a tenth of the minimum value, meaning 0.0000001, which from our point of view is "almost zero" - for slot in self.slots: - if slot['tool'] in tools: + for tool in tools: + for slot in self.tools[tool]['slots']: toolstable_tool = float('%.*f' % (self.decimals, float(tooldia))) - file_tool = float('%.*f' % (self.decimals, float(self.tools[tool]["C"]))) + file_tool = float('%.*f' % (self.decimals, float(self.tools[tool]["tooldia"]))) # I add the 0.0001 value to account for the rounding error in converting from IN to MM and reverse # for the file_tool (tooldia actually) buffer_value = float(file_tool / 2) - float(toolstable_tool / 2) + 0.0001 if buffer_value == 0: - start = slot['start'] - stop = slot['stop'] + start = slot[0] + stop = slot[1] lines_string = LineString([start, stop]) poly = lines_string.buffer(0.0000001, int(self.geo_steps_per_circle)).exterior geo_obj.solid_geometry.append(poly) else: - start = slot['start'] - stop = slot['stop'] + start = slot[0] + stop = slot[1] lines_string = LineString([start, stop]) poly = lines_string.buffer(buffer_value, int(self.geo_steps_per_circle)).exterior @@ -1522,7 +1458,7 @@ class ExcellonObject(FlatCAMObj, Excellon): # tool number) it means that there are 3 rows (1 tool and 2 totals). # in this case regardless of the selection status of that tool, use it. if self.ui.tools_table.rowCount() == 3: - tools.append(self.ui.tools_table.item(0, 0).text()) + tools.append(int(self.ui.tools_table.item(0, 0).text())) else: self.app.inform.emit('[ERROR_NOTCL] %s' % _("Please select one or more tools from the list and try again.")) diff --git a/appParsers/ParseExcellon.py b/appParsers/ParseExcellon.py index 0bbad87f..7c1fcdbf 100644 --- a/appParsers/ParseExcellon.py +++ b/appParsers/ParseExcellon.py @@ -40,30 +40,13 @@ class Excellon(Geometry): ================ ==================================== Key Value ================ ==================================== - C Diameter of the tool - solid_geometry Geometry list for each tool + tooldia Diameter of the tool + drills List that store the Shapely Points for drill points + slots List that store the Shapely Points for slots. Each is a tuple: (start_point, stop_point data dictionary which holds the options for each tool - Others Not supported (Ignored). + solid_geometry Geometry list for each tool ================ ==================================== - * ``drills`` (list): Each is a dictionary: - - ================ ==================================== - Key Value - ================ ==================================== - point (Shapely.Point) Where to drill - tool (str) A key in ``tools`` - ================ ==================================== - - * ``slots`` (list): Each is a dictionary - - ================ ==================================== - Key Value - ================ ==================================== - start (Shapely.Point) Start point of the slot - stop (Shapely.Point) Stop point of the slot - tool (str) A key in ``tools`` - ================ ==================================== """ defaults = { @@ -96,10 +79,6 @@ class Excellon(Geometry): # dictionary to store tools, see above for description self.tools = {} - # list to store the drills, see above for description - self.drills = [] - # self.slots (list) to store the slots; each is a dictionary - self.slots = [] self.source_file = '' @@ -110,9 +89,6 @@ class Excellon(Geometry): self.match_routing_start = None self.match_routing_stop = None - self.num_tools = [] # List for keeping the tools sorted - self.index_per_tool = {} # Dictionary to store the indexed points for each tool - # ## IN|MM -> Units are inherited from Geometry self.units = self.app.defaults['units'] self.units_found = self.app.defaults['units'] @@ -142,9 +118,8 @@ class Excellon(Geometry): # Attributes to be included in serialization # Always append to it because it carries contents # from Geometry. - self.ser_attrs += ['tools', 'drills', 'zeros', 'excellon_format_upper_mm', 'excellon_format_lower_mm', - 'excellon_format_upper_in', 'excellon_format_lower_in', 'excellon_units', 'slots', - 'source_file'] + self.ser_attrs += ['tools', 'zeros', 'excellon_format_upper_mm', 'excellon_format_lower_mm', + 'excellon_format_upper_in', 'excellon_format_lower_in', 'excellon_units', 'source_file'] # ### Patterns #### # Regex basics: @@ -346,14 +321,22 @@ class Excellon(Geometry): if match.group(2): name_tool += 1 + + # ---------- add a TOOL ------------ # + if name_tool not in self.tools: + self.tools[name_tool] = {} if line_units == 'MILS': - spec = {"C": (float(match.group(2)) / 1000)} - self.tools[str(name_tool)] = spec - log.debug("Tool definition: %s %s" % (name_tool, spec)) + spec = { + 'tooldia': (float(match.group(2)) / 1000) + } + self.tools[name_tool]['tooldia'] = (float(match.group(2)) / 1000) + log.debug("Tool definition: %d %s" % (name_tool, spec)) else: - spec = {"C": float(match.group(2))} - self.tools[str(name_tool)] = spec - log.debug("Tool definition: %s %s" % (name_tool, spec)) + spec = { + 'tooldia': float(match.group(2)) + } + self.tools[name_tool]['tooldia'] = float(match.group(2)) + log.debug("Tool definition: %d %s" % (name_tool, spec)) spec['solid_geometry'] = [] continue # search for Altium Excellon Format / Sprint Layout who is included as a comment @@ -400,7 +383,7 @@ class Excellon(Geometry): lower_tools = set() if not self.excellon_units_found and self.tools: for tool in self.tools: - tool_dia = float(self.tools[tool]['C']) + tool_dia = float(self.tools[tool]['tooldia']) lower_tools.add(tool_dia) if tool_dia <= 0.1 else greater_tools.add(tool_dia) assumed_units = "IN" if len(lower_tools) > len(greater_tools) else "MM" @@ -434,12 +417,12 @@ class Excellon(Geometry): # ## Tool change ### match = self.toolsel_re.search(eline) if match: - current_tool = str(int(match.group(1))) + current_tool = int(match.group(1)) log.debug("Tool change: %s" % current_tool) if bool(headerless): match = self.toolset_hl_re.search(eline) if match: - name = str(int(match.group(1))) + name = int(match.group(1)) try: diam = float(match.group(2)) except Exception: @@ -467,8 +450,13 @@ class Excellon(Geometry): else: diam = (self.toolless_diam + (int(current_tool) - 1) / 100) / 25.4 - spec = {"C": diam, 'solid_geometry': []} - self.tools[name] = spec + # ---------- add a TOOL ------------ # + spec = {"tooldia": diam, 'solid_geometry': []} + if name not in self.tools: + self.tools[name] = {} + self.tools[name]['tooldia'] = diam + self.tools[name]['solid_geometry'] = [] + log.debug("Tool definition out of header: %s %s" % (name, spec)) continue @@ -479,8 +467,8 @@ class Excellon(Geometry): match1 = self.stop_re.search(eline) if match or match1: name_tool += 1 - current_tool = str(name_tool) - log.debug("Tool change for Allegro type of Excellon: %s" % current_tool) + current_tool = name_tool + log.debug("Tool change for Allegro type of Excellon: %d" % current_tool) continue # ## Slots parsing for drilled slots (contain G85) @@ -546,7 +534,7 @@ class Excellon(Geometry): # store current tool diameter as slot diameter slot_dia = 0.05 try: - slot_dia = float(self.tools[current_tool]['C']) + slot_dia = float(self.tools[current_tool]['tooldia']) except Exception: pass log.debug( @@ -556,13 +544,17 @@ class Excellon(Geometry): ) ) - self.slots.append( - { - 'start': Point(slot_start_x, slot_start_y), - 'stop': Point(slot_stop_x, slot_stop_y), - 'tool': current_tool - } + # ---------- add a slot ------------ # + slot = ( + Point(slot_start_x, slot_start_y), + Point(slot_stop_x, slot_stop_y) ) + if current_tool not in self.tools: + self.tools[current_tool] = {} + if 'slots' in self.tools[current_tool]: + self.tools[current_tool]['slots'].apend(slot) + else: + self.tools[current_tool]['slots'] = [slot] continue # Slot coordinates with period: Use literally. ### @@ -616,7 +608,7 @@ class Excellon(Geometry): # store current tool diameter as slot diameter slot_dia = 0.05 try: - slot_dia = float(self.tools[current_tool]['C']) + slot_dia = float(self.tools[current_tool]['tooldia']) except Exception: pass log.debug( @@ -626,13 +618,17 @@ class Excellon(Geometry): ) ) - self.slots.append( - { - 'start': Point(slot_start_x, slot_start_y), - 'stop': Point(slot_stop_x, slot_stop_y), - 'tool': current_tool - } + # ---------- add a Slot ------------ # + slot = ( + Point(slot_start_x, slot_start_y), + Point(slot_stop_x, slot_stop_y) ) + if current_tool not in self.tools: + self.tools[current_tool] = {} + if 'slots' in self.tools[current_tool]: + self.tools[current_tool]['slots'].apend(slot) + else: + self.tools[current_tool]['slots'] = [slot] continue # ## Coordinates without period # ## @@ -660,7 +656,14 @@ class Excellon(Geometry): coordx += repeating_x if repeating_y: coordy += repeating_y - self.drills.append({'point': Point((coordx, coordy)), 'tool': current_tool}) + + # ---------- add a Drill ------------ # + if current_tool not in self.tools: + self.tools[current_tool] = {} + if 'drills' in self.tools[current_tool]: + self.tools[current_tool]['drills'].append(Point((coordx, coordy))) + else: + self.tools[current_tool]['drills'] = [Point((coordx, coordy))] repeat -= 1 current_x = coordx @@ -710,19 +713,31 @@ class Excellon(Geometry): self.routing_flag = 1 slot_stop_x = x slot_stop_y = y - self.slots.append( - { - 'start': Point(slot_start_x, slot_start_y), - 'stop': Point(slot_stop_x, slot_stop_y), - 'tool': current_tool - } + + # ---------- add a Slot ------------ # + slot = ( + Point(slot_start_x, slot_start_y), + Point(slot_stop_x, slot_stop_y) ) + if current_tool not in self.tools: + self.tools[current_tool] = {} + if 'slots' in self.tools[current_tool]: + self.tools[current_tool]['slots'].apend(slot) + else: + self.tools[current_tool]['slots'] = [slot] continue if self.match_routing_start is None and self.match_routing_stop is None: # signal that there are drill operations self.defaults['excellon_drills'] = True - self.drills.append({'point': Point((x, y)), 'tool': current_tool}) + + # ---------- add a Drill ------------ # + if current_tool not in self.tools: + self.tools[current_tool] = {} + if 'drills' in self.tools[current_tool]: + self.tools[current_tool]['drills'].append(Point((x, y))) + else: + self.tools[current_tool]['drills'] = [Point((x, y))] # log.debug("{:15} {:8} {:8}".format(eline, x, y)) continue @@ -778,13 +793,18 @@ class Excellon(Geometry): self.routing_flag = 1 slot_stop_x = x slot_stop_y = y - self.slots.append( - { - 'start': Point(slot_start_x, slot_start_y), - 'stop': Point(slot_stop_x, slot_stop_y), - 'tool': current_tool - } + + # ---------- add a Slot ------------ # + slot = ( + Point(slot_start_x, slot_start_y), + Point(slot_stop_x, slot_stop_y) ) + if current_tool not in self.tools: + self.tools[current_tool] = {} + if 'slots' in self.tools[current_tool]: + self.tools[current_tool]['slots'].apend(slot) + else: + self.tools[current_tool]['slots'] = [slot] continue if self.match_routing_start is None and self.match_routing_stop is None: @@ -792,7 +812,14 @@ class Excellon(Geometry): if repeat == 0: # signal that there are drill operations self.defaults['excellon_drills'] = True - self.drills.append({'point': Point((x, y)), 'tool': current_tool}) + + # ---------- add a Drill ------------ # + if current_tool not in self.tools: + self.tools[current_tool] = {} + if 'drills' in self.tools[current_tool]: + self.tools[current_tool]['drills'].append(Point((x, y))) + else: + self.tools[current_tool]['drills'] = [Point((x, y))] else: coordx = x coordy = y @@ -801,7 +828,15 @@ class Excellon(Geometry): coordx = (repeat * x) + repeating_x if repeating_y: coordy = (repeat * y) + repeating_y - self.drills.append({'point': Point((coordx, coordy)), 'tool': current_tool}) + + # ---------- add a Drill ------------ # + if current_tool not in self.tools: + self.tools[current_tool] = {} + if 'drills' in self.tools[current_tool]: + self.tools[current_tool]['drills'].append(Point((coordx, coordy))) + else: + self.tools[current_tool]['drills'] = [Point((coordx, coordy))] + repeat -= 1 repeating_x = repeating_y = 0 # log.debug("{:15} {:8} {:8}".format(eline, x, y)) @@ -813,9 +848,14 @@ class Excellon(Geometry): # ## Tool definitions # ## match = self.toolset_re.search(eline) if match: - name = str(int(match.group(1))) + # ---------- add a TOOL ------------ # + name = int(match.group(1)) spec = {"C": float(match.group(2)), 'solid_geometry': []} - self.tools[name] = spec + if name not in self.tools: + self.tools[name] = {} + self.tools[name]['tooldia'] = float(match.group(2)) + self.tools[name]['solid_geometry'] = [] + log.debug("Tool definition: %s %s" % (name, spec)) continue @@ -977,8 +1017,9 @@ class Excellon(Geometry): def create_geometry(self): """ Creates circles of the tool diameter at every point - specified in ``self.drills``. Also creates geometries (polygons) - for the slots as specified in ``self.slots`` + specified in self.tools[tool]['drills']. + Also creates geometries (polygons) + for the slots as specified in self.tools[tool]['slots'] All the resulting geometry is stored into self.solid_geometry list. The list self.solid_geometry has 2 elements: first is a dict with the drills geometry, and second element is another similar dict that contain the slots geometry. @@ -1001,36 +1042,35 @@ class Excellon(Geometry): self.tools[tool]['solid_geometry'] = [] self.tools[tool]['data'] = {} - for drill in self.drills: - # poly = drill['point'].buffer(self.tools[drill['tool']]["C"]/2.0) - if drill['tool'] == '': - self.app.inform.emit('[WARNING] %s' % - _("Excellon.create_geometry() -> a drill location was skipped " - "due of not having a tool associated.\n" - "Check the resulting GCode.")) - log.debug("appParsers.ParseExcellon.Excellon.create_geometry() -> a drill location was skipped " - "due of not having a tool associated") - continue - tooldia = self.tools[drill['tool']]['C'] - poly = drill['point'].buffer(tooldia / 2.0, int(int(self.geo_steps_per_circle) / 4)) - self.solid_geometry.append(poly) + for tool in self.tools: + tooldia = self.tools[tool]['tooldia'] - tool_in_drills = drill['tool'] - self.tools[tool_in_drills]['solid_geometry'].append(poly) - self.tools[tool_in_drills]['data'] = deepcopy(self.default_data) + if 'drills' in self.tools[tool]: + for drill in self.tools[tool]['drills']: + poly = drill.buffer(tooldia / 2.0, int(int(self.geo_steps_per_circle) / 4)) - for slot in self.slots: - slot_tooldia = self.tools[slot['tool']]['C'] - start = slot['start'] - stop = slot['stop'] + # add poly in the tools geometry + self.tools[tool]['solid_geometry'].append(poly) + self.tools[tool]['data'] = deepcopy(self.default_data) - lines_string = LineString([start, stop]) - poly = lines_string.buffer(slot_tooldia / 2.0, int(int(self.geo_steps_per_circle) / 4)) - self.solid_geometry.append(poly) + # add poly to the total solid geometry + self.solid_geometry.append(poly) + + if 'slots' in self.tools[tool]: + for slot in self.tools[tool]['slots']: + start = slot[0] + stop = slot[1] + + lines_string = LineString([start, stop]) + poly = lines_string.buffer(tooldia / 2.0, int(int(self.geo_steps_per_circle) / 4)) + + # add poly in the tools geometry + self.tools[tool]['solid_geometry'].append(poly) + self.tools[tool]['data'] = deepcopy(self.default_data) + + # add poly to the total solid geometry + self.solid_geometry.append(poly) - tool_in_slots = slot['tool'] - self.tools[tool_in_slots]['solid_geometry'].append(poly) - self.tools[tool_in_slots]['data'] = deepcopy(self.default_data) except Exception as e: log.debug("appParsers.ParseExcellon.Excellon.create_geometry() -> " "Excellon geometry creation failed due of ERROR: %s" % str(e)) @@ -1126,7 +1166,7 @@ class Excellon(Geometry): # Tools for tname in self.tools: - self.tools[tname]["C"] *= factor + self.tools[tname]["tooldia"] *= factor self.create_geometry() return factor @@ -1173,31 +1213,39 @@ class Excellon(Geometry): # variables to display the percentage of work done self.geo_len = 0 try: - self.geo_len = len(self.drills) + self.geo_len = len(self.tools) except TypeError: self.geo_len = 1 self.old_disp_number = 0 self.el_count = 0 - # Drills - for drill in self.drills: - drill['point'] = affinity.scale(drill['point'], xfactor, yfactor, origin=(px, py)) + for tool in self.tools: + # Scale Drills + if 'drills' in self.tools[tool]: + new_drills = [] + for drill in self.tools[tool]['drills']: + new_drills.append(affinity.scale(drill, xfactor, yfactor, origin=(px, py))) + self.tools[tool]['drills'] = new_drills + # Scale Slots + if 'slots' in self.tools[tool]: + new_slots = [] + for slot in self.tools[tool]['slots']: + new_start = affinity.scale(slot[0], xfactor, yfactor, origin=(px, py)) + new_stop = affinity.scale(slot[1], xfactor, yfactor, origin=(px, py)) + new_slot = (new_start, new_stop) + new_slots.append(new_slot) + + # Scale solid_geometry + self.tools[tool]['solid_geometry'] = scale_geom(self.tools[tool]['solid_geometry']) + + # update status display self.el_count += 1 disp_number = int(np.interp(self.el_count, [0, self.geo_len], [0, 100])) if self.old_disp_number < disp_number <= 100: self.app.proc_container.update_view_text(' %d%%' % disp_number) self.old_disp_number = disp_number - # scale solid_geometry - for tool in self.tools: - self.tools[tool]['solid_geometry'] = scale_geom(self.tools[tool]['solid_geometry']) - - # Slots - for slot in self.slots: - slot['stop'] = affinity.scale(slot['stop'], xfactor, yfactor, origin=(px, py)) - slot['start'] = affinity.scale(slot['start'], xfactor, yfactor, origin=(px, py)) - self.create_geometry() self.app.proc_container.new_text = '' @@ -1231,31 +1279,39 @@ class Excellon(Geometry): # variables to display the percentage of work done self.geo_len = 0 try: - self.geo_len = len(self.drills) + self.geo_len = len(self.tools) except TypeError: self.geo_len = 1 self.old_disp_number = 0 self.el_count = 0 - # Drills - for drill in self.drills: - drill['point'] = affinity.translate(drill['point'], xoff=dx, yoff=dy) + for tool in self.tools: + # Offset Drills + if 'drills' in self.tools[tool]: + new_drills = [] + for drill in self.tools[tool]['drills']: + new_drills.append(affinity.translate(drill, xoff=dx, yoff=dy)) + self.tools[tool]['drills'] = new_drills + # Offset Slots + if 'slots' in self.tools[tool]: + new_slots = [] + for slot in self.tools[tool]['slots']: + new_start = affinity.translate(slot[0], xoff=dx, yoff=dy) + new_stop = affinity.translate(slot[1], xoff=dx, yoff=dy) + new_slot = (new_start, new_stop) + new_slots.append(new_slot) + + # Offset solid_geometry + self.tools[tool]['solid_geometry'] = offset_geom(self.tools[tool]['solid_geometry']) + + # update status display self.el_count += 1 disp_number = int(np.interp(self.el_count, [0, self.geo_len], [0, 100])) if self.old_disp_number < disp_number <= 100: self.app.proc_container.update_view_text(' %d%%' % disp_number) self.old_disp_number = disp_number - # offset solid_geometry - for tool in self.tools: - self.tools[tool]['solid_geometry'] = offset_geom(self.tools[tool]['solid_geometry']) - - # Slots - for slot in self.slots: - slot['stop'] = affinity.translate(slot['stop'], xoff=dx, yoff=dy) - slot['start'] = affinity.translate(slot['start'], xoff=dx, yoff=dy) - # Recreate geometry self.create_geometry() self.app.proc_container.new_text = '' @@ -1291,31 +1347,39 @@ class Excellon(Geometry): # variables to display the percentage of work done self.geo_len = 0 try: - self.geo_len = len(self.drills) + self.geo_len = len(self.tools) except TypeError: self.geo_len = 1 self.old_disp_number = 0 self.el_count = 0 - # Drills - for drill in self.drills: - drill['point'] = affinity.scale(drill['point'], xscale, yscale, origin=(px, py)) + for tool in self.tools: + # Offset Drills + if 'drills' in self.tools[tool]: + new_drills = [] + for drill in self.tools[tool]['drills']: + new_drills.append(affinity.scale(drill, xscale, yscale, origin=(px, py))) + self.tools[tool]['drills'] = new_drills + # Offset Slots + if 'slots' in self.tools[tool]: + new_slots = [] + for slot in self.tools[tool]['slots']: + new_start = affinity.scale(slot[0], xscale, yscale, origin=(px, py)) + new_stop = affinity.scale(slot[1], xscale, yscale, origin=(px, py)) + new_slot = (new_start, new_stop) + new_slots.append(new_slot) + + # Offset solid_geometry + self.tools[tool]['solid_geometry'] = mirror_geom(self.tools[tool]['solid_geometry']) + + # update status display self.el_count += 1 disp_number = int(np.interp(self.el_count, [0, self.geo_len], [0, 100])) if self.old_disp_number < disp_number <= 100: self.app.proc_container.update_view_text(' %d%%' % disp_number) self.old_disp_number = disp_number - # mirror solid_geometry - for tool in self.tools: - self.tools[tool]['solid_geometry'] = mirror_geom(self.tools[tool]['solid_geometry']) - - # Slots - for slot in self.slots: - slot['stop'] = affinity.scale(slot['stop'], xscale, yscale, origin=(px, py)) - slot['start'] = affinity.scale(slot['start'], xscale, yscale, origin=(px, py)) - # Recreate geometry self.create_geometry() self.app.proc_container.new_text = '' @@ -1361,7 +1425,7 @@ class Excellon(Geometry): # variables to display the percentage of work done self.geo_len = 0 try: - self.geo_len = len(self.drills) + self.geo_len = len(self.tools) except TypeError: self.geo_len = 1 self.old_disp_number = 0 @@ -1369,47 +1433,35 @@ class Excellon(Geometry): if point is None: px, py = 0, 0 - - # Drills - for drill in self.drills: - drill['point'] = affinity.skew(drill['point'], angle_x, angle_y, - origin=(px, py)) - - self.el_count += 1 - disp_number = int(np.interp(self.el_count, [0, self.geo_len], [0, 100])) - if self.old_disp_number < disp_number <= 100: - self.app.proc_container.update_view_text(' %d%%' % disp_number) - self.old_disp_number = disp_number - - # skew solid_geometry - for tool in self.tools: - self.tools[tool]['solid_geometry'] = skew_geom(self.tools[tool]['solid_geometry']) - - # Slots - for slot in self.slots: - slot['stop'] = affinity.skew(slot['stop'], angle_x, angle_y, origin=(px, py)) - slot['start'] = affinity.skew(slot['start'], angle_x, angle_y, origin=(px, py)) else: px, py = point - # Drills - for drill in self.drills: - drill['point'] = affinity.skew(drill['point'], angle_x, angle_y, - origin=(px, py)) - self.el_count += 1 - disp_number = int(np.interp(self.el_count, [0, self.geo_len], [0, 100])) - if self.old_disp_number < disp_number <= 100: - self.app.proc_container.update_view_text(' %d%%' % disp_number) - self.old_disp_number = disp_number + for tool in self.tools: + # Offset Drills + if 'drills' in self.tools[tool]: + new_drills = [] + for drill in self.tools[tool]['drills']: + new_drills.append(affinity.skew(drill, angle_x, angle_y, origin=(px, py))) + self.tools[tool]['drills'] = new_drills - # skew solid_geometry - for tool in self.tools: - self.tools[tool]['solid_geometry'] = skew_geom(self.tools[tool]['solid_geometry']) + # Offset Slots + if 'slots' in self.tools[tool]: + new_slots = [] + for slot in self.tools[tool]['slots']: + new_start = affinity.skew(slot[0], angle_x, angle_y, origin=(px, py)) + new_stop = affinity.skew(slot[1], angle_x, angle_y, origin=(px, py)) + new_slot = (new_start, new_stop) + new_slots.append(new_slot) - # Slots - for slot in self.slots: - slot['stop'] = affinity.skew(slot['stop'], angle_x, angle_y, origin=(px, py)) - slot['start'] = affinity.skew(slot['start'], angle_x, angle_y, origin=(px, py)) + # Offset solid_geometry + self.tools[tool]['solid_geometry'] = skew_geom(self.tools[tool]['solid_geometry']) + + # update status display + self.el_count += 1 + disp_number = int(np.interp(self.el_count, [0, self.geo_len], [0, 100])) + if self.old_disp_number < disp_number <= 100: + self.app.proc_container.update_view_text(' %d%%' % disp_number) + self.old_disp_number = disp_number self.create_geometry() self.app.proc_container.new_text = '' @@ -1441,58 +1493,50 @@ class Excellon(Geometry): return obj else: try: - return affinity.rotate(obj, angle, origin=(px, py)) + return affinity.rotate(obj, angle, origin=orig) except AttributeError: return obj # variables to display the percentage of work done self.geo_len = 0 try: - self.geo_len = len(self.drills) + self.geo_len = len(self.tools) except TypeError: self.geo_len = 1 self.old_disp_number = 0 self.el_count = 0 if point is None: - # Drills - for drill in self.drills: - drill['point'] = affinity.rotate(drill['point'], angle, origin='center') - - # rotate solid_geometry - for tool in self.tools: - self.tools[tool]['solid_geometry'] = rotate_geom(self.tools[tool]['solid_geometry'], origin='center') - - self.el_count += 1 - disp_number = int(np.interp(self.el_count, [0, self.geo_len], [0, 100])) - if self.old_disp_number < disp_number <= 100: - self.app.proc_container.update_view_text(' %d%%' % disp_number) - self.old_disp_number = disp_number - - # Slots - for slot in self.slots: - slot['stop'] = affinity.rotate(slot['stop'], angle, origin='center') - slot['start'] = affinity.rotate(slot['start'], angle, origin='center') + orig = 'center' else: - px, py = point - # Drills - for drill in self.drills: - drill['point'] = affinity.rotate(drill['point'], angle, origin=(px, py)) + orig = point - self.el_count += 1 - disp_number = int(np.interp(self.el_count, [0, self.geo_len], [0, 100])) - if self.old_disp_number < disp_number <= 100: - self.app.proc_container.update_view_text(' %d%%' % disp_number) - self.old_disp_number = disp_number + for tool in self.tools: + # Offset Drills + if 'drills' in self.tools[tool]: + new_drills = [] + for drill in self.tools[tool]['drills']: + new_drills.append(affinity.rotate(drill, angle, origin=orig)) + self.tools[tool]['drills'] = new_drills - # rotate solid_geometry - for tool in self.tools: - self.tools[tool]['solid_geometry'] = rotate_geom(self.tools[tool]['solid_geometry']) + # Offset Slots + if 'slots' in self.tools[tool]: + new_slots = [] + for slot in self.tools[tool]['slots']: + new_start = affinity.rotate(slot[0], angle, origin=orig) + new_stop = affinity.rotate(slot[1], angle, origin=orig) + new_slot = (new_start, new_stop) + new_slots.append(new_slot) - # Slots - for slot in self.slots: - slot['stop'] = affinity.rotate(slot['stop'], angle, origin=(px, py)) - slot['start'] = affinity.rotate(slot['start'], angle, origin=(px, py)) + # Offset solid_geometry + self.tools[tool]['solid_geometry'] = rotate_geom(self.tools[tool]['solid_geometry'], origin=orig) + + # update status display + self.el_count += 1 + disp_number = int(np.interp(self.el_count, [0, self.geo_len], [0, 100])) + if self.old_disp_number < disp_number <= 100: + self.app.proc_container.update_view_text(' %d%%' % disp_number) + self.old_disp_number = disp_number self.create_geometry() self.app.proc_container.new_text = '' @@ -1534,8 +1578,8 @@ class Excellon(Geometry): except TypeError: self.tools[tool]['solid_geometry'] = [res] if factor is None: - self.tools[tool]['C'] += distance + self.tools[tool]['tooldia'] += distance else: - self.tools[tool]['C'] *= distance + self.tools[tool]['tooldia'] *= distance self.create_geometry() diff --git a/appTools/ToolDblSided.py b/appTools/ToolDblSided.py index 48f750ff..6f869acd 100644 --- a/appTools/ToolDblSided.py +++ b/appTools/ToolDblSided.py @@ -613,9 +613,9 @@ class DblSidedTool(AppTool): return tools = {} - tools["1"] = {} - tools["1"]["C"] = dia - tools["1"]['solid_geometry'] = [] + tools[1] = {} + tools[1]["tooldia"] = dia + tools[1]['solid_geometry'] = [] # holes = self.alignment_holes.get_value() holes = eval('[{}]'.format(self.alignment_holes.text())) @@ -624,21 +624,16 @@ class DblSidedTool(AppTool): "Add them and retry.")) return - drills = [] - for hole in holes: point = Point(hole) point_mirror = affinity.scale(point, xscale, yscale, origin=(px, py)) - drills.append({"point": point, "tool": "1"}) - drills.append({"point": point_mirror, "tool": "1"}) - - tools["1"]['solid_geometry'].append(point) - tools["1"]['solid_geometry'].append(point_mirror) + tools[1]['drills'] = [point, point_mirror] + tools[1]['solid_geometry'].append(point) + tools[1]['solid_geometry'].append(point_mirror) def obj_init(obj_inst, app_inst): obj_inst.tools = tools - obj_inst.drills = drills obj_inst.create_geometry() obj_inst.source_file = app_inst.export_excellon(obj_name=obj_inst.options['name'], local_use=obj_inst, filename=None, use_thread=False) diff --git a/appTools/ToolDrilling.py b/appTools/ToolDrilling.py index a192fa0c..660ef02f 100644 --- a/appTools/ToolDrilling.py +++ b/appTools/ToolDrilling.py @@ -172,7 +172,6 @@ class ToolDrilling(AppTool, Excellon): # ############################ SIGNALS ######################################## # ############################################################################# - self.ui.object_combo.currentIndexChanged.connect(self.on_object_changed) self.ui.apply_param_to_all.clicked.connect(self.on_apply_param_to_all_clicked) self.ui.generate_cnc_button.clicked.connect(self.on_cnc_button_click) self.ui.tools_table.drag_drop_sig.connect(self.rebuild_ui) @@ -365,8 +364,6 @@ class ToolDrilling(AppTool, Excellon): if opt_key.find('geometry_') == 0: self.default_data[opt_key] = deepcopy(opt_val) - self.on_object_changed() - self.obj_name = "" self.excellon_obj = None @@ -382,6 +379,16 @@ class ToolDrilling(AppTool, Excellon): self.ui.operation_radio.set_value("drill") self.ui.operation_radio.setEnabled(False) + self.on_object_changed() + if self.excellon_obj: + self.build_ui() + + try: + self.ui.object_combo.currentIndexChanged.disconnect() + except (AttributeError, TypeError): + pass + self.ui.object_combo.currentIndexChanged.connect(self.on_object_changed) + def rebuild_ui(self): # read the table tools uid current_uid_list = [] @@ -419,17 +426,8 @@ class ToolDrilling(AppTool, Excellon): if self.excellon_obj: self.ui.exc_param_frame.setDisabled(False) - sort = [] - for k, v in list(self.excellon_obj.tools.items()): - sort.append((k, float('%.*f' % (self.decimals, float(v.get('C')))))) - order = self.ui.order_radio.get_value() - if order == 'fwd': - sorted_tools = sorted(sort, key=lambda t1: t1[1]) - elif order == 'rev': - sorted_tools = sorted(sort, key=lambda t1: t1[1], reverse=True) - else: - sorted_tools = sort - tools = [i[0] for i in sorted_tools] + tools = [k for k in self.excellon_tools] + else: tools = [] @@ -438,30 +436,23 @@ class ToolDrilling(AppTool, Excellon): self.ui.tools_table.setRowCount(n + 2) self.tool_row = 0 - new_options = {} - if self.excellon_obj: - for opt in self.excellon_obj.options: - new_options[opt] = self.excellon_obj.options[opt] - for tool_no in tools: - # add the data dictionary for each tool with the default values - self.tools[tool_no]['data'] = deepcopy(new_options) drill_cnt = 0 # variable to store the nr of drills per tool slot_cnt = 0 # variable to store the nr of slots per tool # Find no of drills for the current tool - for drill in self.drills: - if drill['tool'] == tool_no: - drill_cnt += 1 - + try: + drill_cnt = len(self.excellon_tools[tool_no]["drills"]) + except KeyError: + drill_cnt = 0 self.tot_drill_cnt += drill_cnt # Find no of slots for the current tool - for slot in self.slots: - if slot['tool'] == tool_no: - slot_cnt += 1 - + try: + slot_cnt = len(self.excellon_tools[tool_no]["slots"]) + except KeyError: + slot_cnt = 0 self.tot_slot_cnt += slot_cnt # Tool name/id @@ -470,7 +461,7 @@ class ToolDrilling(AppTool, Excellon): self.ui.tools_table.setItem(self.tool_row, 0, exc_id_item) # Tool Diameter - dia_item = QtWidgets.QTableWidgetItem('%.*f' % (self.decimals, self.tools[tool_no]['C'])) + dia_item = QtWidgets.QTableWidgetItem('%.*f' % (self.decimals, self.excellon_tools[tool_no]['tooldia'])) dia_item.setFlags(QtCore.Qt.ItemIsEnabled) self.ui.tools_table.setItem(self.tool_row, 1, dia_item) @@ -496,6 +487,8 @@ class ToolDrilling(AppTool, Excellon): # add a last row with the Total number of drills empty_1 = QtWidgets.QTableWidgetItem('') empty_1.setFlags(~QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) + empty_1_1 = QtWidgets.QTableWidgetItem('') + empty_1_1.setFlags(~QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) label_tot_drill_count = QtWidgets.QTableWidgetItem(_('Total Drills')) label_tot_drill_count.setFlags(QtCore.Qt.ItemIsEnabled) @@ -506,6 +499,7 @@ class ToolDrilling(AppTool, Excellon): self.ui.tools_table.setItem(self.tool_row, 0, empty_1) self.ui.tools_table.setItem(self.tool_row, 1, label_tot_drill_count) self.ui.tools_table.setItem(self.tool_row, 2, tot_drill_count) # Total number of drills + self.ui.tools_table.setItem(self.tool_row, 4, empty_1_1) font = QtGui.QFont() font.setBold(True) @@ -642,35 +636,15 @@ class ToolDrilling(AppTool, Excellon): self.excellon_obj = self.app.collection.get_by_name(self.obj_name) except Exception as e: self.app.inform.emit('[ERROR_NOTCL] %s: %s' % (_("Could not retrieve object"), str(self.obj_name))) - return "Could not retrieve object: %s with error: %s" % (self.obj_name, str(e)) + return if self.excellon_obj is None: self.ui.exc_param_frame.setDisabled(True) else: self.ui.exc_param_frame.setDisabled(False) - sort = [] - for k, v in list(self.excellon_obj.tools.items()): - sort.append((k, float('%.*f' % (self.decimals, float(v.get('C')))))) - dias = [i[0] for i in sort] + self.excellon_tools = self.excellon_obj.tools - if not dias: - log.error("At least one tool diameter needed. Excellon object might be empty.") - return - - tooluid = 0 - - self.excellon_tools.clear() - for tool_dia in dias: - tooluid += 1 - self.excellon_tools.update({ - int(tooluid): { - 'tooldia': float('%.*f' % (self.decimals, tool_dia)), - - 'data': deepcopy(self.default_data), - 'solid_geometry': [] - } - }) - self.build_ui() + self.build_ui() def ui_connect(self): @@ -809,7 +783,7 @@ class ToolDrilling(AppTool, Excellon): item = self.ui.tools_table.item(c_row, 3) if type(item) is not None: tooluid = item.text() - self.storage_to_form(self.drilling_tools[str(tooluid)]['data']) + self.storage_to_form(self.excellon_tools[str(tooluid)]['data']) else: self.blockSignals(False) return @@ -845,8 +819,9 @@ class ToolDrilling(AppTool, Excellon): :return: None :rtype: """ - if self.ui.tools_table.rowCount() == 0: + if self.ui.tools_table.rowCount() == 2: # there is no tool in tool table so we can't save the GUI elements values to storage + # Excellon Tool Table has 2 rows by default return self.blockSignals(True) @@ -862,7 +837,7 @@ class ToolDrilling(AppTool, Excellon): row = 0 tooluid_item = int(self.ui.tools_table.item(row, 3).text()) - for tooluid_key, tooluid_val in self.iso_tools.items(): + for tooluid_key, tooluid_val in self.excellon_tools.items(): if int(tooluid_key) == tooluid_item: new_option_value = self.form_fields[option_changed].get_value() if option_changed in tooluid_val: @@ -1034,7 +1009,7 @@ class ToolDrilling(AppTool, Excellon): sort = [] for k, v in self.tools.items(): - sort.append((k, v.get('C'))) + sort.append((k, v.get('tooldia'))) sorted_tools = sorted(sort, key=lambda t1: t1[1]) if tools == "all": @@ -1150,7 +1125,7 @@ class ToolDrilling(AppTool, Excellon): sort = [] for k, v in self.tools.items(): - sort.append((k, v.get('C'))) + sort.append((k, v.get('tooldia'))) sorted_tools = sorted(sort, key=lambda t1: t1[1]) if tools == "all": diff --git a/appTools/ToolExtractDrills.py b/appTools/ToolExtractDrills.py index 2fd6ca78..9927ef38 100644 --- a/appTools/ToolExtractDrills.py +++ b/appTools/ToolExtractDrills.py @@ -530,7 +530,7 @@ class ToolExtractDrills(AppTool): tool_in_drills = False for tool, tool_val in tools.items(): - if abs(float('%.*f' % (self.decimals, tool_val["C"])) - float('%.*f' % (self.decimals, dia))) < \ + if abs(float('%.*f' % (self.decimals, tool_val["tooldia"])) - float('%.*f' % (self.decimals, dia))) < \ (10 ** -self.decimals): tool_in_drills = tool @@ -615,7 +615,7 @@ class ToolExtractDrills(AppTool): tool_in_drills = False for tool, tool_val in tools.items(): - if abs(float('%.*f' % (self.decimals, tool_val["C"])) - float('%.*f' % (self.decimals, dia))) < \ + if abs(float('%.*f' % (self.decimals, tool_val["tooldia"])) - float('%.*f' % (self.decimals, dia))) < \ (10 ** -self.decimals): tool_in_drills = tool diff --git a/appTools/ToolProperties.py b/appTools/ToolProperties.py index 77d9065c..ab860b93 100644 --- a/appTools/ToolProperties.py +++ b/appTools/ToolProperties.py @@ -397,16 +397,14 @@ class Properties(AppTool): slot_cnt = 0 # variable to store the nr of slots per tool # Find no of drills for the current tool - for drill in obj.drills: - if drill['tool'] == tool: - drill_cnt += 1 + if 'drills' in value and value['drills']: + drill_cnt = len(value['drills']) tot_drill_cnt += drill_cnt # Find no of slots for the current tool - for slot in obj.slots: - if slot['tool'] == tool: - slot_cnt += 1 + if 'slots' in value and value['slots']: + slot_cnt = len(value['slots']) tot_slot_cnt += slot_cnt @@ -414,7 +412,7 @@ class Properties(AppTool): toolid, [ _('Diameter'), - '%.*f %s' % (self.decimals, value['C'], self.app.defaults['units'].lower()) + '%.*f %s' % (self.decimals, value['tooldia'], self.app.defaults['units'].lower()) ], True ) diff --git a/appTools/ToolPunchGerber.py b/appTools/ToolPunchGerber.py index 3c9f8fde..15a69618 100644 --- a/appTools/ToolPunchGerber.py +++ b/appTools/ToolPunchGerber.py @@ -558,7 +558,7 @@ class ToolPunchGerber(AppTool): # make it work only for Gerber Flashes who are Points in 'follow' if 'solid' in elem and isinstance(elem['follow'], Point): for drill in exc_obj.drills: - clear_apid_size = exc_obj.tools[drill['tool']]['C'] + clear_apid_size = exc_obj.tools[drill['tool']]['tooldia'] # since there may be drills that do not drill into a pad we test only for drills in a pad if drill['point'].within(elem['solid']): diff --git a/app_Main.py b/app_Main.py index 8f667566..1bc08be4 100644 --- a/app_Main.py +++ b/app_Main.py @@ -2314,7 +2314,20 @@ class App(QtCore.QObject): self.ui.tool_scroll_area.takeWidget() # delete the old object (the source object) if it was an empty one - if len(edited_obj.drills) == 0 and len(edited_obj.slots) == 0: + # find if we have drills: + has_drills = None + for tt in edited_obj.tools: + if 'drills' in edited_obj.tools[tt] and edited_obj.tools[tt]['drills']: + has_drills = True + break + # find if we have slots: + has_slots = None + for tt in edited_obj.tools: + if 'slots' in edited_obj.tools[tt] and edited_obj.tools[tt]['slots']: + has_slots = True + slots_in_file = 1 + break + if has_drills is None and has_slots is None: old_name = edited_obj.options['name'] self.collection.delete_by_name(name=old_name) self.inform.emit('[success] %s' % _("Editor exited. Editor content saved.")) @@ -8230,11 +8243,11 @@ class App(QtCore.QObject): for tool in obj.tools: if eunits == 'METRIC': - header += "T{tool}F00S00C{:.{dec}f}\n".format(float(obj.tools[tool]['C']) * factor, + header += "T{tool}F00S00C{:.{dec}f}\n".format(float(obj.tools[tool]['tooldia']) * factor, tool=str(tool), dec=2) else: - header += "T{tool}F00S00C{:.{dec}f}\n".format(float(obj.tools[tool]['C']) * factor, + header += "T{tool}F00S00C{:.{dec}f}\n".format(float(obj.tools[tool]['tooldia']) * factor, tool=str(tool), dec=4) else: @@ -8247,13 +8260,15 @@ class App(QtCore.QObject): for tool in obj.tools: if eunits == 'METRIC': - header += "T{tool}F00S00C{:.{dec}f}\n".format(float(obj.tools[tool]['C']) * factor, - tool=str(tool), - dec=2) + header += "T{tool}F00S00C{:.{dec}f}\n".format( + float(obj.tools[tool]['tooldia']) * factor, + tool=str(tool), + dec=2) else: - header += "T{tool}F00S00C{:.{dec}f}\n".format(float(obj.tools[tool]['C']) * factor, - tool=str(tool), - dec=4) + header += "T{tool}F00S00C{:.{dec}f}\n".format( + float(obj.tools[tool]['tooldia']) * factor, + tool=str(tool), + dec=4) else: has_slots, excellon_code = obj.export_excellon(ewhole, efract, form='ndec', e_zeros='TZ', factor=factor, @@ -8263,13 +8278,15 @@ class App(QtCore.QObject): for tool in obj.tools: if eunits == 'METRIC': - header += "T{tool}F00S00C{:.{dec}f}\n".format(float(obj.tools[tool]['C']) * factor, - tool=str(tool), - dec=2) + header += "T{tool}F00S00C{:.{dec}f}\n".format( + float(obj.tools[tool]['tooldia']) * factor, + tool=str(tool), + dec=2) else: - header += "T{tool}F00S00C{:.{dec}f}\n".format(float(obj.tools[tool]['C']) * factor, - tool=str(tool), - dec=4) + header += "T{tool}F00S00C{:.{dec}f}\n".format( + float(obj.tools[tool]['tooldia']) * factor, + tool=str(tool), + dec=4) header += '%\n' footer = 'M30\n' diff --git a/camlib.py b/camlib.py index b78f2f0f..29f09535 100644 --- a/camlib.py +++ b/camlib.py @@ -2555,8 +2555,6 @@ class CNCjob(Geometry): # here store the routing time self.routing_time = 0.0 - # used for creating drill CCode geometry; will be updated in the generate_from_excellon_by_tool() - self.exc_drills = None # store here the Excellon source object tools to be accessible locally self.exc_tools = None @@ -2710,8 +2708,7 @@ class CNCjob(Geometry): :rtype: None """ - # create a local copy of the exobj.drills so it can be used for creating drill CCode geometry - self.exc_drills = deepcopy(exobj.drills) + # create a local copy of the exobj.tools so it can be used for creating drill CCode geometry self.exc_tools = deepcopy(exobj.tools) # the Excellon GCode preprocessor will use this info in the start_code() method @@ -2774,8 +2771,8 @@ class CNCjob(Geometry): # sorted_tools = sorted(exobj.tools.items(), key=lambda t1: t1['C']) sort = [] - for k, v in list(exobj.tools.items()): - sort.append((k, v.get('C'))) + for k, v in list(self.exc_tools.items()): + sort.append((int(k), v['tooldia'])) sorted_tools = sorted(sort, key=lambda t1: t1[1]) if tools == "all": @@ -2783,7 +2780,7 @@ class CNCjob(Geometry): log.debug("Tools 'all' and sorted are: %s" % str(tools)) else: selected_tools = [x.strip() for x in tools.split(",")] # we strip spaces and also separate the tools by ',' - selected_tools = [t1 for t1 in selected_tools if t1 in selected_tools] + selected_tools = [int(t1) for t1 in selected_tools if t1 in selected_tools] # Create a sorted list of selected tools from the sorted_tools list tools = [i for i, j in sorted_tools for k in selected_tools if i == k] @@ -2803,18 +2800,20 @@ class CNCjob(Geometry): for it in sorted_tools: for to_ol in tools: if to_ol == it[0]: - drill_no = 0 sol_geo = [] - for dr in exobj.drills: - if dr['tool'] == it[0]: - drill_no += 1 - sol_geo.append(dr['point']) + + drill_no = 0 + if 'drills' in exobj.tools[to_ol]: + drill_no = len(exobj.tools[to_ol]['drills']) + for drill in exobj.tools[to_ol]['drills']: + sol_geo.append(drill.buffer((it[1] / 2.0), resolution=self.geo_steps_per_circle)) + slot_no = 0 - for dr in exobj.slots: - if dr['tool'] == it[0]: - slot_no += 1 - start = (dr['start'].x, dr['start'].y) - stop = (dr['stop'].x, dr['stop'].y) + if 'slots' in exobj.tools[to_ol]: + slot_no = len(exobj.tools[to_ol]['slots']) + for slot in exobj.tools[to_ol]['slots']: + start = (slot[0].x, slot[0].y) + stop = (slot[1].x, slot[1].y) sol_geo.append( LineString([start, stop]).buffer((it[1] / 2.0), resolution=self.geo_steps_per_circle) ) @@ -2850,25 +2849,26 @@ class CNCjob(Geometry): # Points (Group by tool): a dictionary of shapely Point geo elements grouped by tool number points = {} - for drill in exobj.drills: + for tool, tool_dict in self.exc_tools.items(): if self.app.abort_flag: # graceful abort requested by the user raise grace - if drill['tool'] in tools: - try: - points[drill['tool']].append(drill['point']) - except KeyError: - points[drill['tool']] = [drill['point']] + if 'drills' in tool_dict and tool_dict['drills']: + for drill_pt in tool_dict['drills']: + try: + points[tool].append(drill_pt) + except KeyError: + points[tool] = [drill_pt] - # log.debug("Found %d drills." % len(points)) + log.debug("Found %d TOOLS." % len(points)) # check if there are drill points in the exclusion areas. # If we find any within the exclusion areas return 'fail' for tool in points: for pt in points[tool]: for area in self.app.exc_areas.exclusion_areas_storage: - pt_buf = pt.buffer(exobj.tools[tool]['C'] / 2.0) + pt_buf = pt.buffer(self.exc_tools[tool]['tooldia'] / 2.0) 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.")) return 'fail' @@ -2954,22 +2954,28 @@ class CNCjob(Geometry): used_excellon_optimization_type = self.excellon_optimization_type if used_excellon_optimization_type == 'M': log.debug("Using OR-Tools Metaheuristic Guided Local Search drill path optimization.") - if exobj.drills: + + has_drills = None + for tool, tool_dict in self.exc_tools.items(): + if 'drills' in tool_dict and tool_dict['drills']: + has_drills = True + break + if has_drills: for tool in tools: if self.app.abort_flag: # graceful abort requested by the user raise grace self.tool = tool - self.postdata['toolC'] = exobj.tools[tool]["C"] - self.tooldia = exobj.tools[tool]["C"] + self.tooldia = self.exc_tools[tool]["tooldia"] + self.postdata['toolC'] = self.tooldia if self.use_ui: - self.z_feedrate = exobj.tools[tool]['data']['feedrate_z'] - self.feedrate = exobj.tools[tool]['data']['feedrate'] + self.z_feedrate = self.exc_tools[tool]['data']['feedrate_z'] + self.feedrate = self.exc_tools[tool]['data']['feedrate'] gcode += self.doformat(p.z_feedrate_code) - self.z_cut = exobj.tools[tool]['data']['cutz'] + self.z_cut = self.exc_tools[tool]['data']['cutz'] if self.machinist_setting == 0: if self.z_cut > 0: @@ -2991,12 +2997,12 @@ class CNCjob(Geometry): old_zcut = deepcopy(self.z_cut) - self.z_move = exobj.tools[tool]['data']['travelz'] - self.spindlespeed = exobj.tools[tool]['data']['spindlespeed'] - self.dwell = exobj.tools[tool]['data']['dwell'] - self.dwelltime = exobj.tools[tool]['data']['dwelltime'] - self.multidepth = exobj.tools[tool]['data']['multidepth'] - self.z_depthpercut = exobj.tools[tool]['data']['depthperpass'] + self.z_move = self.exc_tools[tool]['data']['travelz'] + self.spindlespeed = self.exc_tools[tool]['data']['spindlespeed'] + self.dwell = self.exc_tools[tool]['data']['dwell'] + self.dwelltime = self.exc_tools[tool]['data']['dwelltime'] + self.multidepth = self.exc_tools[tool]['data']['multidepth'] + self.z_depthpercut = self.exc_tools[tool]['data']['depthperpass'] else: old_zcut = deepcopy(self.z_cut) @@ -3085,7 +3091,7 @@ class CNCjob(Geometry): if self.dwell is True: gcode += self.doformat(p.dwell_code) # Dwell time - current_tooldia = float('%.*f' % (self.decimals, float(exobj.tools[tool]["C"]))) + current_tooldia = float('%.*f' % (self.decimals, float(self.exc_tools[tool]["tooldia"]))) self.app.inform.emit( '%s: %s%s.' % (_("Starting G-Code for tool with diameter"), @@ -3098,7 +3104,7 @@ class CNCjob(Geometry): # because the values for Z offset are created in build_ui() # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! try: - z_offset = float(exobj.tools[tool]['data']['offset']) * (-1) + z_offset = float(self.exc_tools[tool]['data']['offset']) * (-1) except KeyError: z_offset = 0 self.z_cut = z_offset + old_zcut @@ -3138,7 +3144,7 @@ class CNCjob(Geometry): gcode += self.doformat(p.lift_code, x=locx, y=locy) # restore z_move - self.z_move = exobj.tools[tool]['data']['travelz'] + self.z_move = self.exc_tools[tool]['data']['travelz'] else: if prev_z is not None: # move to next point @@ -3146,7 +3152,7 @@ class CNCjob(Geometry): # we assume that previously the z_move was altered therefore raise to # the travel_z (z_move) - self.z_move = exobj.tools[tool]['data']['travelz'] + self.z_move = self.exc_tools[tool]['data']['travelz'] gcode += self.doformat(p.lift_code, x=locx, y=locy) else: # move to next point @@ -3218,21 +3224,28 @@ class CNCjob(Geometry): if used_excellon_optimization_type == 'B': log.debug("Using OR-Tools Basic drill path optimization.") - if exobj.drills: + + has_drills = None + for tool, tool_dict in self.exc_tools.items(): + if 'drills' in tool_dict and tool_dict['drills']: + has_drills = True + break + + if has_drills: for tool in tools: if self.app.abort_flag: # graceful abort requested by the user raise grace self.tool = tool - self.postdata['toolC'] = exobj.tools[tool]["C"] - self.tooldia = exobj.tools[tool]["C"] + self.tooldia = self.exc_tools[tool]["tooldia"] + self.postdata['toolC'] = self.tooldia if self.use_ui: - self.z_feedrate = exobj.tools[tool]['data']['feedrate_z'] - self.feedrate = exobj.tools[tool]['data']['feedrate'] + self.z_feedrate = self.exc_tools[tool]['data']['feedrate_z'] + self.feedrate = self.exc_tools[tool]['data']['feedrate'] gcode += self.doformat(p.z_feedrate_code) - self.z_cut = exobj.tools[tool]['data']['cutz'] + self.z_cut = self.exc_tools[tool]['data']['cutz'] if self.machinist_setting == 0: if self.z_cut > 0: @@ -3254,13 +3267,13 @@ class CNCjob(Geometry): old_zcut = deepcopy(self.z_cut) - self.z_move = exobj.tools[tool]['data']['travelz'] + self.z_move = self.exc_tools[tool]['data']['travelz'] - self.spindlespeed = exobj.tools[tool]['data']['spindlespeed'] - self.dwell = exobj.tools[tool]['data']['dwell'] - self.dwelltime = exobj.tools[tool]['data']['dwelltime'] - self.multidepth = exobj.tools[tool]['data']['multidepth'] - self.z_depthpercut = exobj.tools[tool]['data']['depthperpass'] + self.spindlespeed = self.exc_tools[tool]['data']['spindlespeed'] + self.dwell = self.exc_tools[tool]['data']['dwell'] + self.dwelltime = self.exc_tools[tool]['data']['dwelltime'] + self.multidepth = self.exc_tools[tool]['data']['multidepth'] + self.z_depthpercut = self.exc_tools[tool]['data']['depthperpass'] else: old_zcut = deepcopy(self.z_cut) @@ -3338,7 +3351,7 @@ class CNCjob(Geometry): if self.dwell is True: gcode += self.doformat(p.dwell_code) # Dwell time - current_tooldia = float('%.*f' % (self.decimals, float(exobj.tools[tool]["C"]))) + current_tooldia = float('%.*f' % (self.decimals, float(self.exc_tools[tool]["tooldia"]))) self.app.inform.emit( '%s: %s%s.' % (_("Starting G-Code for tool with diameter"), @@ -3351,7 +3364,7 @@ class CNCjob(Geometry): # because the values for Z offset are created in build_ui() # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! try: - z_offset = float(exobj.tools[tool]['data']['offset']) * (-1) + z_offset = float(self.exc_tools[tool]['data']['offset']) * (-1) except KeyError: z_offset = 0 self.z_cut = z_offset + old_zcut @@ -3390,7 +3403,7 @@ class CNCjob(Geometry): gcode += self.doformat(p.lift_code, x=locx, y=locy) # restore z_move - self.z_move = exobj.tools[tool]['data']['travelz'] + self.z_move = self.exc_tools[tool]['data']['travelz'] else: if prev_z is not None: # move to next point @@ -3398,7 +3411,7 @@ class CNCjob(Geometry): # we assume that previously the z_move was altered therefore raise to # the travel_z (z_move) - self.z_move = exobj.tools[tool]['data']['travelz'] + self.z_move = self.exc_tools[tool]['data']['travelz'] gcode += self.doformat(p.lift_code, x=locx, y=locy) else: # move to next point @@ -3473,22 +3486,29 @@ class CNCjob(Geometry): if used_excellon_optimization_type == 'T': log.debug("Using Travelling Salesman drill path optimization.") + + has_drills = None + for tool, tool_dict in self.exc_tools.items(): + if 'drills' in tool_dict and tool_dict['drills']: + has_drills = True + break + for tool in tools: if self.app.abort_flag: # graceful abort requested by the user raise grace - if exobj.drills: + if has_drills: self.tool = tool - self.postdata['toolC'] = exobj.tools[tool]["C"] - self.tooldia = exobj.tools[tool]["C"] + self.tooldia = self.exc_tools[tool]["tooldia"] + self.postdata['toolC'] = self.tooldia if self.use_ui: - self.z_feedrate = exobj.tools[tool]['data']['feedrate_z'] - self.feedrate = exobj.tools[tool]['data']['feedrate'] + self.z_feedrate = self.exc_tools[tool]['data']['feedrate_z'] + self.feedrate = self.exc_tools[tool]['data']['feedrate'] gcode += self.doformat(p.z_feedrate_code) - self.z_cut = exobj.tools[tool]['data']['cutz'] + self.z_cut = self.exc_tools[tool]['data']['cutz'] if self.machinist_setting == 0: if self.z_cut > 0: @@ -3510,12 +3530,12 @@ class CNCjob(Geometry): old_zcut = deepcopy(self.z_cut) - self.z_move = exobj.tools[tool]['data']['travelz'] - self.spindlespeed = exobj.tools[tool]['data']['spindlespeed'] - self.dwell = exobj.tools[tool]['data']['dwell'] - self.dwelltime = exobj.tools[tool]['data']['dwelltime'] - self.multidepth = exobj.tools[tool]['data']['multidepth'] - self.z_depthpercut = exobj.tools[tool]['data']['depthperpass'] + self.z_move = self.exc_tools[tool]['data']['travelz'] + self.spindlespeed = self.exc_tools[tool]['data']['spindlespeed'] + self.dwell = self.exc_tools[tool]['data']['dwell'] + self.dwelltime = self.exc_tools[tool]['data']['dwelltime'] + self.multidepth = self.exc_tools[tool]['data']['multidepth'] + self.z_depthpercut = self.exc_tools[tool]['data']['depthperpass'] else: old_zcut = deepcopy(self.z_cut) @@ -3536,7 +3556,7 @@ class CNCjob(Geometry): if self.dwell is True: gcode += self.doformat(p.dwell_code) # Dwell time - current_tooldia = float('%.*f' % (self.decimals, float(exobj.tools[tool]["C"]))) + current_tooldia = float('%.*f' % (self.decimals, float(self.exc_tools[tool]["tooldia"]))) self.app.inform.emit( '%s: %s%s.' % (_("Starting G-Code for tool with diameter"), @@ -3549,7 +3569,7 @@ class CNCjob(Geometry): # because the values for Z offset are created in build_ui() # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! try: - z_offset = float(exobj.tools[tool]['data']['offset']) * (-1) + z_offset = float(self.exc_tools[tool]['data']['offset']) * (-1) except KeyError: z_offset = 0 self.z_cut = z_offset + old_zcut @@ -3593,7 +3613,7 @@ class CNCjob(Geometry): gcode += self.doformat(p.lift_code, x=locx, y=locy) # restore z_move - self.z_move = exobj.tools[tool]['data']['travelz'] + self.z_move = self.exc_tools[tool]['data']['travelz'] else: if prev_z is not None: # move to next point @@ -3601,7 +3621,7 @@ class CNCjob(Geometry): # we assume that previously the z_move was altered therefore raise to # the travel_z (z_move) - self.z_move = exobj.tools[tool]['data']['travelz'] + self.z_move = self.exc_tools[tool]['data']['travelz'] gcode += self.doformat(p.lift_code, x=locx, y=locy) else: # move to next point @@ -3687,6 +3707,7 @@ class CNCjob(Geometry): self.routing_time += lift_time + traveled_time self.gcode = gcode + self.app.inform.emit(_("Finished G-Code generation...")) return 'OK' @@ -4914,22 +4935,27 @@ class CNCjob(Geometry): ) # find the drill diameter knowing the drill coordinates - for pt_dict in self.exc_drills: - point_in_dict_coords = ( - float('%.*f' % (self.decimals, pt_dict['point'].x)), - float('%.*f' % (self.decimals, pt_dict['point'].y)) - ) - if point_in_dict_coords == current_drill_point_coords: - tool = pt_dict['tool'] - dia = self.exc_tools[tool]['C'] - kind = ['C', 'F'] - geometry.append( - { - "geom": Point(current_drill_point_coords).buffer(dia / 2.0).exterior, - "kind": kind - } - ) - break + break_loop = False + for tool, tool_dict in self.exc_tools.items(): + if 'drills' in tool_dict: + for drill_pt in tool_dict['drills']: + point_in_dict_coords = ( + float('%.*f' % (self.decimals, drill_pt.x)), + float('%.*f' % (self.decimals, drill_pt.y)) + ) + if point_in_dict_coords == current_drill_point_coords: + dia = self.exc_tools[tool]['tooldia'] + kind = ['C', 'F'] + geometry.append( + { + "geom": Point(current_drill_point_coords).buffer(dia / 2.0).exterior, + "kind": kind + } + ) + break_loop = True + break + if break_loop: + break if 'G' in gobj: current['G'] = int(gobj['G']) diff --git a/preprocessors/Berta_CNC.py b/preprocessors/Berta_CNC.py index 43c553e2..0ceb1dec 100644 --- a/preprocessors/Berta_CNC.py +++ b/preprocessors/Berta_CNC.py @@ -48,7 +48,7 @@ class Berta_CNC(PreProc): elif str(p['options']['type']) == 'Excellon' and p['use_ui'] is True: gcode += '\n(TOOLS DIAMETER: )\n' for tool, val in p['exc_tools'].items(): - gcode += '(Tool: %s -> ' % str(tool) + 'Dia: %s' % str(val["C"]) + ')\n' + gcode += '(Tool: %s -> ' % str(tool) + 'Dia: %s' % str(val["tooldia"]) + ')\n' gcode += '\n(FEEDRATE Z: )\n' for tool, val in p['exc_tools'].items(): diff --git a/preprocessors/ISEL_CNC.py b/preprocessors/ISEL_CNC.py index bf2ffd2e..6009577a 100644 --- a/preprocessors/ISEL_CNC.py +++ b/preprocessors/ISEL_CNC.py @@ -38,7 +38,7 @@ class ISEL_CNC(PreProc): elif str(p['options']['type']) == 'Excellon' and p['use_ui'] is True: gcode += '\n(TOOLS DIAMETER: )\n' for tool, val in p['exc_tools'].items(): - gcode += '(Tool: %s -> ' % str(tool) + 'Dia: %s' % str(val["C"]) + ')\n' + gcode += '(Tool: %s -> ' % str(tool) + 'Dia: %s' % str(val["tooldia"]) + ')\n' gcode += '\n(FEEDRATE Z: )\n' for tool, val in p['exc_tools'].items(): diff --git a/preprocessors/ISEL_ICP_CNC.py b/preprocessors/ISEL_ICP_CNC.py index 3732cd4e..122937bf 100644 --- a/preprocessors/ISEL_ICP_CNC.py +++ b/preprocessors/ISEL_ICP_CNC.py @@ -38,7 +38,7 @@ class ISEL_ICP_CNC(PreProc): elif str(p['options']['type']) == 'Excellon' and p['use_ui'] is True: gcode += '\n;TOOLS DIAMETER: \n' for tool, val in p['exc_tools'].items(): - gcode += ';Tool: %s -> ' % str(tool) + 'Dia: %s' % str(val["C"]) + '\n' + gcode += ';Tool: %s -> ' % str(tool) + 'Dia: %s' % str(val["tooldia"]) + '\n' gcode += '\n;FEEDRATE Z: \n' for tool, val in p['exc_tools'].items(): diff --git a/preprocessors/Marlin.py b/preprocessors/Marlin.py index aea09f12..7db58a95 100644 --- a/preprocessors/Marlin.py +++ b/preprocessors/Marlin.py @@ -40,7 +40,7 @@ class Marlin(PreProc): elif str(p['options']['type']) == 'Excellon' and p['use_ui'] is True: gcode += '\n;TOOLS DIAMETER: \n' for tool, val in p['exc_tools'].items(): - gcode += ';Tool: %s -> ' % str(tool) + 'Dia: %s' % str(val["C"]) + '\n' + gcode += ';Tool: %s -> ' % str(tool) + 'Dia: %s' % str(val["tooldia"]) + '\n' gcode += '\n;FEEDRATE Z: \n' for tool, val in p['exc_tools'].items(): diff --git a/preprocessors/Repetier.py b/preprocessors/Repetier.py index 71d5daea..b0657692 100644 --- a/preprocessors/Repetier.py +++ b/preprocessors/Repetier.py @@ -40,7 +40,7 @@ class Repetier(PreProc): elif str(p['options']['type']) == 'Excellon' and p['use_ui'] is True: gcode += '\n;TOOLS DIAMETER: \n' for tool, val in p['exc_tools'].items(): - gcode += ';Tool: %s -> ' % str(tool) + 'Dia: %s' % str(val["C"]) + '\n' + gcode += ';Tool: %s -> ' % str(tool) + 'Dia: %s' % str(val["tooldia"]) + '\n' gcode += '\n;FEEDRATE Z: \n' for tool, val in p['exc_tools'].items(): diff --git a/preprocessors/Toolchange_Custom.py b/preprocessors/Toolchange_Custom.py index b2bd0067..94b6ab36 100644 --- a/preprocessors/Toolchange_Custom.py +++ b/preprocessors/Toolchange_Custom.py @@ -39,7 +39,7 @@ class Toolchange_Custom(PreProc): elif str(p['options']['type']) == 'Excellon' and p['use_ui'] is True: gcode += '\n(TOOLS DIAMETER: )\n' for tool, val in p['exc_tools'].items(): - gcode += '(Tool: %s -> ' % str(tool) + 'Dia: %s' % str(val["C"]) + ')\n' + gcode += '(Tool: %s -> ' % str(tool) + 'Dia: %s' % str(val["tooldia"]) + ')\n' gcode += '\n(FEEDRATE Z: )\n' for tool, val in p['exc_tools'].items(): diff --git a/preprocessors/Toolchange_Manual.py b/preprocessors/Toolchange_Manual.py index 7040c73f..96d05071 100644 --- a/preprocessors/Toolchange_Manual.py +++ b/preprocessors/Toolchange_Manual.py @@ -39,7 +39,7 @@ class Toolchange_Manual(PreProc): elif str(p['options']['type']) == 'Excellon' and p['use_ui'] is True: gcode += '\n(TOOLS DIAMETER: )\n' for tool, val in p['exc_tools'].items(): - gcode += '(Tool: %s -> ' % str(tool) + 'Dia: %s' % str(val["C"]) + ')\n' + gcode += '(Tool: %s -> ' % str(tool) + 'Dia: %s' % str(val["tooldia"]) + ')\n' gcode += '\n(FEEDRATE Z: )\n' for tool, val in p['exc_tools'].items(): diff --git a/preprocessors/Toolchange_Probe_MACH3.py b/preprocessors/Toolchange_Probe_MACH3.py index 5014116a..5fdf5da7 100644 --- a/preprocessors/Toolchange_Probe_MACH3.py +++ b/preprocessors/Toolchange_Probe_MACH3.py @@ -39,7 +39,7 @@ class Toolchange_Probe_MACH3(PreProc): elif str(p['options']['type']) == 'Excellon' and p['use_ui'] is True: gcode += '\n(TOOLS DIAMETER: )\n' for tool, val in p['exc_tools'].items(): - gcode += '(Tool: %s -> ' % str(tool) + 'Dia: %s' % str(val["C"]) + ')\n' + gcode += '(Tool: %s -> ' % str(tool) + 'Dia: %s' % str(val["tooldia"]) + ')\n' gcode += '\n(FEEDRATE Z: )\n' for tool, val in p['exc_tools'].items(): diff --git a/preprocessors/default.py b/preprocessors/default.py index 79488f67..33563352 100644 --- a/preprocessors/default.py +++ b/preprocessors/default.py @@ -40,7 +40,7 @@ class default(PreProc): elif str(p['options']['type']) == 'Excellon' and p['use_ui'] is True: gcode += '\n(TOOLS DIAMETER: )\n' for tool, val in p['exc_tools'].items(): - gcode += '(Tool: %s -> ' % str(tool) + 'Dia: %s' % str(val["C"]) + ')\n' + gcode += '(Tool: %s -> ' % str(tool) + 'Dia: %s' % str(val["tooldia"]) + ')\n' gcode += '\n(FEEDRATE Z: )\n' for tool, val in p['exc_tools'].items(): diff --git a/preprocessors/grbl_11.py b/preprocessors/grbl_11.py index 8bc32441..dd205cd9 100644 --- a/preprocessors/grbl_11.py +++ b/preprocessors/grbl_11.py @@ -40,7 +40,7 @@ class grbl_11(PreProc): elif str(p['options']['type']) == 'Excellon' and p['use_ui'] is True: gcode += '\n(TOOLS DIAMETER: )\n' for tool, val in p['exc_tools'].items(): - gcode += '(Tool: %s -> ' % str(tool) + 'Dia: %s' % str(val["C"]) + ')\n' + gcode += '(Tool: %s -> ' % str(tool) + 'Dia: %s' % str(val["tooldia"]) + ')\n' gcode += '\n(FEEDRATE Z: )\n' for tool, val in p['exc_tools'].items(): diff --git a/preprocessors/line_xyz.py b/preprocessors/line_xyz.py index d883abf9..145bd06d 100644 --- a/preprocessors/line_xyz.py +++ b/preprocessors/line_xyz.py @@ -39,7 +39,7 @@ class line_xyz(PreProc): elif str(p['options']['type']) == 'Excellon' and p['use_ui'] is True: gcode += '\n(TOOLS DIAMETER: )\n' for tool, val in p['exc_tools'].items(): - gcode += '(Tool: %s -> ' % str(tool) + 'Dia: %s' % str(val["C"]) + ')\n' + gcode += '(Tool: %s -> ' % str(tool) + 'Dia: %s' % str(val["tooldia"]) + ')\n' gcode += '\n(FEEDRATE Z: )\n' for tool, val in p['exc_tools'].items(): diff --git a/tclCommands/TclCommandDrillcncjob.py b/tclCommands/TclCommandDrillcncjob.py index 74bcae18..b0c9ddb0 100644 --- a/tclCommands/TclCommandDrillcncjob.py +++ b/tclCommands/TclCommandDrillcncjob.py @@ -198,25 +198,23 @@ class TclCommandDrillcncjob(TclCommandSignaled): if tools == 'all': sort = [] for k, v in list(obj.tools.items()): - sort.append((k, v.get('C'))) + sort.append((k, v.get('tooldia'))) sorted_tools = sorted(sort, key=lambda t1: t1[1]) use_tools = [i[0] for i in sorted_tools] for tool_no in use_tools: - tool_dia_used = obj.tools[tool_no]['C'] + tool_dia_used = obj.tools[tool_no]['tooldia'] drill_cnt = 0 # variable to store the nr of drills per tool slot_cnt = 0 # variable to store the nr of slots per tool # Find no of drills for the current tool - for drill in obj.drills: - if drill['tool'] == tool_no: - drill_cnt += 1 + if 'drills' in obj.tools[tool_no] and obj.tools[tool_no]['drills']: + drill_cnt = len(obj.tools[tool_no]['drills']) # Find no of slots for the current tool - for slot in obj.slots: - if slot['tool'] == tool_no: - slot_cnt += 1 + if 'slots' in obj.tools[tool_no] and obj.tools[tool_no]['slots']: + slot_cnt = len(obj.tools[tool_no]['slots']) used_tools_info.append([str(tool_no), str(tool_dia_used), str(drill_cnt), str(slot_cnt)])