From c886e3300c919ca25e6a713a0c76a995aa8214db Mon Sep 17 00:00:00 2001 From: Marius Stanciu Date: Fri, 16 Aug 2019 00:44:04 +0300 Subject: [PATCH] - added the Slot Type parameter for exporting Excellon in Edit -> Preferences -> Excellon -> Export Excellon. Now the Excellon object can be exported also with drilled slot command G85 - fixed bug in Excellon export when there are no zero suppression (coordinates with decimals) --- FlatCAMApp.py | 11 ++++++--- FlatCAMObj.py | 50 +++++++++++++++++++++++++++------------- README.md | 2 ++ camlib.py | 18 ++++++++------- flatcamGUI/FlatCAMGUI.py | 23 ++++++++++++++++++ 5 files changed, 77 insertions(+), 27 deletions(-) diff --git a/FlatCAMApp.py b/FlatCAMApp.py index eea68969..777e7ca9 100644 --- a/FlatCAMApp.py +++ b/FlatCAMApp.py @@ -469,6 +469,7 @@ class App(QtCore.QObject): "excellon_exp_integer": self.ui.excellon_defaults_form.excellon_exp_group.format_whole_entry, "excellon_exp_decimals": self.ui.excellon_defaults_form.excellon_exp_group.format_dec_entry, "excellon_exp_zeros": self.ui.excellon_defaults_form.excellon_exp_group.zeros_radio, + "excellon_exp_slot_type": self.ui.excellon_defaults_form.excellon_exp_group.slot_type_radio, # Excellon Editor "excellon_editor_sel_limit": self.ui.excellon_defaults_form.excellon_editor_group.sel_limit_entry, @@ -835,6 +836,7 @@ class App(QtCore.QObject): "excellon_exp_integer": 2, "excellon_exp_decimals": 4, "excellon_exp_zeros": 'LZ', + "excellon_exp_slot_type": 'routing', # Excellon Editor "excellon_editor_sel_limit": 30, @@ -7582,6 +7584,7 @@ class App(QtCore.QObject): efract = self.defaults["excellon_exp_decimals"] ezeros = self.defaults["excellon_exp_zeros"] eformat = self.defaults["excellon_exp_format"] + slot_type = self.defaults["excellon_exp_slot_type"] fc_units = self.ui.general_defaults_form.general_app_group.units_radio.get_value().upper() if fc_units == 'MM': @@ -7601,7 +7604,7 @@ class App(QtCore.QObject): header += ';Created on : %s' % time_str + '\n' if eformat == 'dec': - has_slots, excellon_code = obj.export_excellon(ewhole, efract, factor=factor) + has_slots, excellon_code = obj.export_excellon(ewhole, efract, factor=factor, slot_type=slot_type) header += eunits + '\n' for tool in obj.tools: @@ -7616,7 +7619,8 @@ class App(QtCore.QObject): else: if ezeros == 'LZ': has_slots, excellon_code = obj.export_excellon(ewhole, efract, - form='ndec', e_zeros='LZ', factor=factor) + form='ndec', e_zeros='LZ', factor=factor, + slot_type=slot_type) header += '%s,%s\n' % (eunits, 'LZ') header += format_exc @@ -7631,7 +7635,8 @@ class App(QtCore.QObject): dec=4) else: has_slots, excellon_code = obj.export_excellon(ewhole, efract, - form='ndec', e_zeros='TZ', factor=factor) + form='ndec', e_zeros='TZ', factor=factor, + slot_type=slot_type) header += '%s,%s\n' % (eunits, 'TZ') header += format_exc diff --git a/FlatCAMObj.py b/FlatCAMObj.py index 0cbb8ddf..dafe7b24 100644 --- a/FlatCAMObj.py +++ b/FlatCAMObj.py @@ -2237,7 +2237,7 @@ class FlatCAMExcellon(FlatCAMObj, Excellon): item[0] = str(item[0]) return table_tools_items - def export_excellon(self, whole, fract, e_zeros=None, form='dec', factor=1): + def export_excellon(self, whole, fract, e_zeros=None, form='dec', factor=1, slot_type='routing'): """ Returns two values, first is a boolean , if 1 then the file has slots and second contain the Excellon code :return: has_slots and Excellon_code @@ -2303,6 +2303,8 @@ class FlatCAMExcellon(FlatCAMObj, Excellon): if self.slots: has_slots = 1 for tool in self.tools: + excellon_code += 'G05\n' + if int(tool) < 10: excellon_code += 'T0' + str(tool) + '\n' else: @@ -2314,13 +2316,17 @@ class FlatCAMExcellon(FlatCAMObj, Excellon): start_slot_y = slot['start'].y * factor stop_slot_x = slot['stop'].x * factor stop_slot_y = slot['stop'].y * factor - - excellon_code += "G00X{:.{dec}f}Y{:.{dec}f}\nM15\n".format(start_slot_x, - start_slot_y, - dec=fract) - excellon_code += "G00X{:.{dec}f}Y{:.{dec}f}\nM16\n".format(stop_slot_x, - stop_slot_y, - dec=fract) + if slot_type == 'routing': + excellon_code += "G00X{:.{dec}f}Y{:.{dec}f}\nM15\n".format(start_slot_x, + start_slot_y, + dec=fract) + excellon_code += "G01X{:.{dec}f}Y{:.{dec}f}\nM16\n".format(stop_slot_x, + stop_slot_y, + dec=fract) + elif slot_type == 'drilling': + excellon_code += "X{:.{dec}f}Y{:.{dec}f}G85X{:.{dec}f}Y{:.{dec}f}\nG05\n".format( + 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 @@ -2352,10 +2358,16 @@ class FlatCAMExcellon(FlatCAMObj, Excellon): stop_slot_x_formatted = stop_x_whole + stop_slot_x_formatted[2] stop_slot_y_formatted = stop_y_whole + stop_slot_y_formatted[2] - excellon_code += "G00X{xstart}Y{ystart}\nM15\n".format(xstart=start_slot_x_formatted, - ystart=start_slot_y_formatted) - excellon_code += "G00X{xstop}Y{ystop}\nM16\n".format(xstop=stop_slot_x_formatted, - ystop=stop_slot_y_formatted) + if slot_type == 'routing': + excellon_code += "G00X{xstart}Y{ystart}\nM15\n".format(xstart=start_slot_x_formatted, + ystart=start_slot_y_formatted) + excellon_code += "G01X{xstop}Y{ystop}\nM16\n".format(xstop=stop_slot_x_formatted, + ystop=stop_slot_y_formatted) + elif slot_type == 'drilling': + excellon_code += "{xstart}Y{ystart}G85X{xstop}Y{ystop}\nG05\n".format( + 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 @@ -2374,10 +2386,16 @@ class FlatCAMExcellon(FlatCAMObj, Excellon): stop_slot_x_formatted.ljust(length, '0') stop_slot_y_formatted.ljust(length, '0') - excellon_code += "G00X{xstart}Y{ystart}\nM15\n".format(xstart=start_slot_x_formatted, - ystart=start_slot_y_formatted) - excellon_code += "G00X{xstop}Y{ystop}\nM16\n".format(xstop=stop_slot_x_formatted, - ystop=stop_slot_y_formatted) + if slot_type == 'routing': + excellon_code += "G00X{xstart}Y{ystart}\nM15\n".format(xstart=start_slot_x_formatted, + ystart=start_slot_y_formatted) + excellon_code += "G01X{xstop}Y{ystop}\nM16\n".format(xstop=stop_slot_x_formatted, + ystop=stop_slot_y_formatted) + elif slot_type == 'drilling': + excellon_code += "{xstart}Y{ystart}G85X{xstop}Y{ystop}\nG05\n".format( + xstart=start_slot_x_formatted, ystart=start_slot_y_formatted, + xstop=stop_slot_x_formatted, ystop=stop_slot_y_formatted + ) except Exception as e: log.debug(str(e)) diff --git a/README.md b/README.md index b3e9a6c0..ce4564f5 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,8 @@ CAD program, and create G-Code for Isolation routing. - added the key shortcut handlers for Add Slot and Add Slot Array tools in Excellon Editor - started to work on the Resize tool for the case of Excellon slots in Excellon Editor - final fix for the VisPy data files; the defaults files are saved to the Config folder when the app is set to be portable +- added the Slot Type parameter for exporting Excellon in Edit -> Preferences -> Excellon -> Export Excellon. Now the Excellon object can be exported also with drilled slot command G85 +- fixed bug in Excellon export when there are no zero suppression (coordinates with decimals) 14.08.2019 diff --git a/camlib.py b/camlib.py index 32a71093..8640cbe0 100644 --- a/camlib.py +++ b/camlib.py @@ -3979,10 +3979,10 @@ class Excellon(Geometry): ':' + str(self.excellon_format_lower_in)) continue - #### Body ## ## + # ### Body #### if not in_header: - # ## Tool change # ## + # ## Tool change ### match = self.toolsel_re.search(eline) if match: current_tool = str(int(match.group(1))) @@ -4022,7 +4022,7 @@ class Excellon(Geometry): continue - # ## Allegro Type Tool change # ## + # ## Allegro Type Tool change ### if allegro_warning is True: match = self.absinc_re.search(eline) match1 = self.stop_re.search(eline) @@ -4114,7 +4114,7 @@ class Excellon(Geometry): ) continue - # Slot coordinates with period: Use literally. # ## + # Slot coordinates with period: Use literally. ### # get the coordinates for slot start and for slot stop into variables start_coords_period = self.coordsperiod_re.search(start_coords_match) stop_coords_period = self.coordsperiod_re.search(stop_coords_match) @@ -4274,7 +4274,6 @@ class Excellon(Geometry): if match: # signal that there are drill operations self.defaults['excellon_drills'] = True - try: x = float(match.group(1)) repeating_x = current_x @@ -4346,7 +4345,7 @@ class Excellon(Geometry): # log.debug("{:15} {:8} {:8}".format(eline, x, y)) continue - #### Header ## ## + # ### Header #### if in_header: # ## Tool definitions # ## @@ -4484,7 +4483,7 @@ class Excellon(Geometry): match = self.leadingzeros_re.search(number_str) nr_length = len(match.group(1)) + len(match.group(2)) try: - if self.zeros == "L" or self.zeros == "LZ": + if self.zeros == "L" or self.zeros == "LZ": # Leading # With leading zeros, when you type in a coordinate, # the leading zeros must always be included. Trailing zeros # are unneeded and may be left off. The CNC-7 will automatically add them. @@ -4498,7 +4497,7 @@ class Excellon(Geometry): else: result = float(number_str) / (10 ** (float(nr_length) - float(self.excellon_format_upper_mm))) return result - else: # Trailing + elif self.zeros == "T" or self.zeros == "TZ": # Trailing # You must show all zeros to the right of the number and can omit # all zeros to the left of the number. The CNC-7 will count the number # of digits you typed and automatically fill in the missing zeros. @@ -4510,6 +4509,9 @@ class Excellon(Geometry): else: # Metric is 000.000 result = float(number_str) / (10 ** (float(self.excellon_format_lower_mm))) return result + else: # None - the numbers are in decimal format + return float(number_str) + except Exception as e: log.error("Aborted. Operation could not be completed due of %s" % str(e)) return diff --git a/flatcamGUI/FlatCAMGUI.py b/flatcamGUI/FlatCAMGUI.py index 2d818519..c29ac911 100644 --- a/flatcamGUI/FlatCAMGUI.py +++ b/flatcamGUI/FlatCAMGUI.py @@ -5146,6 +5146,29 @@ class ExcellonExpPrefGroupUI(OptionsGroupUI): form.addRow(self.zeros_label, self.zeros_radio) + # Slot type + self.slot_type_label = QtWidgets.QLabel(_('Slot type:')) + self.slot_type_label.setAlignment(QtCore.Qt.AlignLeft) + self.slot_type_label.setToolTip( + _("This sets how the slots will be exported.\n" + "If ROUTED then the slots will be routed\n" + "using M15/M16 commands.\n" + "If DRILLED(G85) the slots will be exported\n" + "using the Drilled slot command (G85).") + ) + + self.slot_type_radio = RadioSet([{'label': _('Routed'), 'value': 'routing'}, + {'label': _('Drilled(G85)'), 'value': 'drilling'}]) + self.slot_type_radio.setToolTip( + _("This sets how the slots will be exported.\n" + "If ROUTED then the slots will be routed\n" + "using M15/M16 commands.\n" + "If DRILLED(G85) the slots will be exported\n" + "using the Drilled slot command (G85).") + ) + + form.addRow(self.slot_type_label, self.slot_type_radio) + self.layout.addStretch() self.format_radio.activated_custom.connect(self.optimization_selection)