diff --git a/FlatCAMApp.py b/FlatCAMApp.py index b7aa387b..80df6cab 100644 --- a/FlatCAMApp.py +++ b/FlatCAMApp.py @@ -957,6 +957,7 @@ class App(QtCore.QObject): # Drills Extraction Tool "tools_edrills_hole_type": 'fixed', "tools_edrills_hole_fixed_dia": 0.5, + "tools_edrills_hole_prop_factor": 80.0, "tools_edrills_circular_ring": 0.2, "tools_edrills_oblong_ring": 0.2, "tools_edrills_square_ring": 0.2, @@ -1598,6 +1599,7 @@ class App(QtCore.QObject): # Extract Drills Tool "tools_edrills_hole_type": self.ui.tools2_defaults_form.tools2_edrills_group.hole_size_radio, "tools_edrills_hole_fixed_dia": self.ui.tools2_defaults_form.tools2_edrills_group.dia_entry, + "tools_edrills_hole_prop_factor": self.ui.tools2_defaults_form.tools2_edrills_group.factor_entry, "tools_edrills_circular_ring": self.ui.tools2_defaults_form.tools2_edrills_group.circular_ring_entry, "tools_edrills_oblong_ring": self.ui.tools2_defaults_form.tools2_edrills_group.oblong_ring_entry, "tools_edrills_square_ring": self.ui.tools2_defaults_form.tools2_edrills_group.square_ring_entry, @@ -4277,9 +4279,20 @@ class App(QtCore.QObject): obj.options['xmax'] = xmax obj.options['ymax'] = ymax except Exception as e: - log.warning("The object has no bounds properties. %s" % str(e)) + log.warning("App.new_object() -> The object has no bounds properties. %s" % str(e)) return "fail" + try: + if kind == 'excellon': + obj.fill_color = self.app.defaults["excellon_plot_fill"] + obj.outline_color = self.app.defaults["excellon_plot_line"] + + if kind == 'gerber': + obj.fill_color = self.app.defaults["gerber_plot_fill"] + obj.outline_color = self.app.defaults["gerber_plot_line"] + except Exception as e: + log.warning("App.new_object() -> setting colors error. %s" % str(e)) + # update the KeyWords list with the name of the file self.myKeywords.append(obj.options['name']) @@ -12305,19 +12318,12 @@ class App(QtCore.QObject): new_line_color = color_variant(new_color[:7], 0.7) for sel_obj in sel_obj_list: - if self.is_legacy is False: - sel_obj.fill_color = new_color - sel_obj.outline_color = new_line_color + sel_obj.fill_color = new_color + sel_obj.outline_color = new_line_color - sel_obj.shapes.redraw( - update_colors=(new_color, new_line_color) - ) - else: - sel_obj.fill_color = new_color - sel_obj.outline_color = new_line_color - sel_obj.shapes.redraw( - update_colors=(new_color, new_line_color) - ) + sel_obj.shapes.redraw( + update_colors=(new_color, new_line_color) + ) def on_grid_snap_triggered(self, state): if state: diff --git a/README.md b/README.md index ac71ea1e..ca9dc47d 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,11 @@ CAD program, and create G-Code for Isolation routing. ================================================= +14.01.2020 + +- in Extract Drill Tool added a new method of drills extraction. The methods are: fixed diameter, fixed annular ring and proportional +- in Align Objects Tool finished the Single Point method of alignment + 13.01.2020 - fixed a small GUI issue in Excellon UI when Basic mode is active diff --git a/flatcamGUI/PreferencesUI.py b/flatcamGUI/PreferencesUI.py index a073b534..41ae3f32 100644 --- a/flatcamGUI/PreferencesUI.py +++ b/flatcamGUI/PreferencesUI.py @@ -7697,14 +7697,20 @@ class Tools2EDrillsPrefGroupUI(OptionsGroupUI): grid_lay.addWidget(separator_line, 8, 0, 1, 2) # ## Axis - self.hole_size_radio = RadioSet([{'label': _("Fixed"), 'value': 'fixed'}, - {'label': _("Proportional"), 'value': 'prop'}]) - self.hole_size_label = QtWidgets.QLabel('%s:' % _("Hole Size")) + self.hole_size_radio = RadioSet( + [ + {'label': _("Fixed Diameter"), 'value': 'fixed'}, + {'label': _("Fixed Annular Ring"), 'value': 'ring'}, + {'label': _("Proportional"), 'value': 'prop'} + ], + orientation='vertical', + stretch=False) + self.hole_size_label = QtWidgets.QLabel('%s:' % _("Method")) self.hole_size_label.setToolTip( - _("The type of hole size. Can be:\n" - "- Fixed -> all holes will have a set size\n" - "- Proprotional -> each hole will havea a variable size\n" - "such as to preserve a set annular ring")) + _("The selected method of extracting the drills. Can be:\n" + "- Fixed Diameter -> all holes will have a set size\n" + "- Fixed Annular Ring -> all holes will have a set annular ring\n" + "- Proportional -> each hole size will be a fraction of the pad size")) grid_lay.addWidget(self.hole_size_label, 9, 0) grid_lay.addWidget(self.hole_size_radio, 9, 1) @@ -7716,27 +7722,31 @@ class Tools2EDrillsPrefGroupUI(OptionsGroupUI): separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) grid_lay.addWidget(separator_line, 10, 0, 1, 2) + # Annular Ring + self.fixed_label = QtWidgets.QLabel('%s' % _("Fixed Diameter")) + grid_lay.addWidget(self.fixed_label, 11, 0, 1, 2) + # Diameter value self.dia_entry = FCDoubleSpinner() self.dia_entry.set_precision(self.decimals) self.dia_entry.set_range(0.0000, 9999.9999) - self.dia_label = QtWidgets.QLabel('%s:' % _("Diameter")) + self.dia_label = QtWidgets.QLabel('%s:' % _("value")) self.dia_label.setToolTip( _("Fixed hole diameter.") ) - grid_lay.addWidget(self.dia_label, 11, 0) - grid_lay.addWidget(self.dia_entry, 11, 1) + grid_lay.addWidget(self.dia_label, 12, 0) + grid_lay.addWidget(self.dia_entry, 12, 1) # Annular Ring value - self.ring_label = QtWidgets.QLabel('%s' % _("Annular Ring")) + self.ring_label = QtWidgets.QLabel('%s' % _("Fixed Annular Ring")) self.ring_label.setToolTip( _("The size of annular ring.\n" "The copper sliver between the drill hole exterior\n" "and the margin of the copper pad.") ) - grid_lay.addWidget(self.ring_label, 12, 0, 1, 2) + grid_lay.addWidget(self.ring_label, 13, 0, 1, 2) # Circular Annular Ring Value self.circular_ring_label = QtWidgets.QLabel('%s:' % _("Circular")) @@ -7748,8 +7758,8 @@ class Tools2EDrillsPrefGroupUI(OptionsGroupUI): self.circular_ring_entry.set_precision(self.decimals) self.circular_ring_entry.set_range(0.0000, 9999.9999) - grid_lay.addWidget(self.circular_ring_label, 13, 0) - grid_lay.addWidget(self.circular_ring_entry, 13, 1) + grid_lay.addWidget(self.circular_ring_label, 14, 0) + grid_lay.addWidget(self.circular_ring_entry, 14, 1) # Oblong Annular Ring Value self.oblong_ring_label = QtWidgets.QLabel('%s:' % _("Oblong")) @@ -7761,8 +7771,8 @@ class Tools2EDrillsPrefGroupUI(OptionsGroupUI): self.oblong_ring_entry.set_precision(self.decimals) self.oblong_ring_entry.set_range(0.0000, 9999.9999) - grid_lay.addWidget(self.oblong_ring_label, 14, 0) - grid_lay.addWidget(self.oblong_ring_entry, 14, 1) + grid_lay.addWidget(self.oblong_ring_label, 15, 0) + grid_lay.addWidget(self.oblong_ring_entry, 15, 1) # Square Annular Ring Value self.square_ring_label = QtWidgets.QLabel('%s:' % _("Square")) @@ -7774,8 +7784,8 @@ class Tools2EDrillsPrefGroupUI(OptionsGroupUI): self.square_ring_entry.set_precision(self.decimals) self.square_ring_entry.set_range(0.0000, 9999.9999) - grid_lay.addWidget(self.square_ring_label, 15, 0) - grid_lay.addWidget(self.square_ring_entry, 15, 1) + grid_lay.addWidget(self.square_ring_label, 16, 0) + grid_lay.addWidget(self.square_ring_entry, 16, 1) # Rectangular Annular Ring Value self.rectangular_ring_label = QtWidgets.QLabel('%s:' % _("Rectangular")) @@ -7787,8 +7797,8 @@ class Tools2EDrillsPrefGroupUI(OptionsGroupUI): self.rectangular_ring_entry.set_precision(self.decimals) self.rectangular_ring_entry.set_range(0.0000, 9999.9999) - grid_lay.addWidget(self.rectangular_ring_label, 16, 0) - grid_lay.addWidget(self.rectangular_ring_entry, 16, 1) + grid_lay.addWidget(self.rectangular_ring_label, 17, 0) + grid_lay.addWidget(self.rectangular_ring_entry, 17, 1) # Others Annular Ring Value self.other_ring_label = QtWidgets.QLabel('%s:' % _("Others")) @@ -7800,8 +7810,26 @@ class Tools2EDrillsPrefGroupUI(OptionsGroupUI): self.other_ring_entry.set_precision(self.decimals) self.other_ring_entry.set_range(0.0000, 9999.9999) - grid_lay.addWidget(self.other_ring_label, 17, 0) - grid_lay.addWidget(self.other_ring_entry, 17, 1) + grid_lay.addWidget(self.other_ring_label, 18, 0) + grid_lay.addWidget(self.other_ring_entry, 18, 1) + + self.prop_label = QtWidgets.QLabel('%s' % _("Proportional Diameter")) + grid_lay.addWidget(self.prop_label, 19, 0, 1, 2) + + # Factor value + self.factor_entry = FCDoubleSpinner(suffix='%') + self.factor_entry.set_precision(self.decimals) + self.factor_entry.set_range(0.0000, 100.0000) + self.factor_entry.setSingleStep(0.1) + + self.factor_label = QtWidgets.QLabel('%s:' % _("Factor")) + self.factor_label.setToolTip( + _("Proportional Diameter.\n" + "The drill diameter will be a fraction of the pad size.") + ) + + grid_lay.addWidget(self.factor_label, 20, 0) + grid_lay.addWidget(self.factor_entry, 20, 1) self.layout.addStretch() diff --git a/flatcamTools/ToolAlignObjects.py b/flatcamTools/ToolAlignObjects.py index 505c5a30..91594c16 100644 --- a/flatcamTools/ToolAlignObjects.py +++ b/flatcamTools/ToolAlignObjects.py @@ -54,18 +54,16 @@ class AlignObjects(FlatCAMTool): grid0.setColumnStretch(1, 1) self.layout.addLayout(grid0) - self.aligned_label = QtWidgets.QLabel('%s' % _("Selection of the aligned object")) + self.aligned_label = QtWidgets.QLabel('%s' % _("Selection of the WORKING object")) grid0.addWidget(self.aligned_label, 0, 0, 1, 2) # Type of object to be aligned self.type_obj_combo = FCComboBox() self.type_obj_combo.addItem("Gerber") self.type_obj_combo.addItem("Excellon") - self.type_obj_combo.addItem("Geometry") self.type_obj_combo.setItemIcon(0, QtGui.QIcon(self.app.resource_location + "/flatcam_icon16.png")) self.type_obj_combo.setItemIcon(1, QtGui.QIcon(self.app.resource_location + "/drill16.png")) - self.type_obj_combo.setItemIcon(2, QtGui.QIcon(self.app.resource_location + "/geometry16.png")) self.type_obj_combo_label = QtWidgets.QLabel('%s:' % _("Object Type")) self.type_obj_combo_label.setToolTip( @@ -96,9 +94,9 @@ class AlignObjects(FlatCAMTool): separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) grid0.addWidget(separator_line, 4, 0, 1, 2) - self.aligned_label = QtWidgets.QLabel('%s' % _("Selection of the aligner object")) + self.aligned_label = QtWidgets.QLabel('%s' % _("Selection of the TARGET object")) self.aligned_label.setToolTip( - _("Object to which the other objects will be aligned to (moved).") + _("Object to which the other objects will be aligned to (moved to).") ) grid0.addWidget(self.aligned_label, 6, 0, 1, 2) @@ -106,11 +104,9 @@ class AlignObjects(FlatCAMTool): self.type_aligner_obj_combo = FCComboBox() self.type_aligner_obj_combo.addItem("Gerber") self.type_aligner_obj_combo.addItem("Excellon") - self.type_aligner_obj_combo.addItem("Geometry") self.type_aligner_obj_combo.setItemIcon(0, QtGui.QIcon(self.app.resource_location + "/flatcam_icon16.png")) self.type_aligner_obj_combo.setItemIcon(1, QtGui.QIcon(self.app.resource_location + "/drill16.png")) - self.type_aligner_obj_combo.setItemIcon(2, QtGui.QIcon(self.app.resource_location + "/geometry16.png")) self.type_aligner_obj_combo_label = QtWidgets.QLabel('%s:' % _("Object Type")) self.type_aligner_obj_combo_label.setToolTip( @@ -219,10 +215,17 @@ class AlignObjects(FlatCAMTool): self.clicked_points = list() self.new_start = None - self.new_stop = None + self.new_dest = None self.align_type = None + # old colors of objects involved in the alignment + self.aligner_old_fill_color = None + self.aligner_old_line_color = None + self.aligned_old_fill_color = None + self.aligned_old_line_color = None + + def run(self, toggle=True): self.app.report_usage("ToolAlignObjects()") @@ -261,6 +264,11 @@ class AlignObjects(FlatCAMTool): self.aligned_obj = None self.aligner_obj = None + self.aligner_old_fill_color = None + self.aligner_old_line_color = None + self.aligned_old_fill_color = None + self.aligned_old_line_color = None + self.a_type_radio.set_value(self.app.defaults["tools_align_objects_align_type"]) if self.local_connected is True: @@ -277,6 +285,7 @@ class AlignObjects(FlatCAMTool): self.aligner_object_combo.setCurrentIndex(0) def on_align(self): + self.app.delete_selection_shape() obj_sel_index = self.object_combo.currentIndex() obj_model_index = self.app.collection.index(obj_sel_index, 0, self.object_combo.rootModelIndex()) @@ -314,8 +323,14 @@ class AlignObjects(FlatCAMTool): self.local_connected = True - self.app.inform.emit(_("Get First alignment point on the aligned object.")) + self.aligner_old_fill_color = self.aligner_obj.fill_color + self.aligner_old_line_color = self.aligner_obj.outline_color + self.aligned_old_fill_color = self.aligned_obj.fill_color + self.aligned_old_line_color = self.aligned_obj.outline_color + + self.app.inform.emit('%s: %s' % (_("First Point"), _("Click on the START point."))) self.target_obj = self.aligned_obj + self.set_color() def on_mouse_click_release(self, event): if self.app.is_legacy is False: @@ -365,40 +380,47 @@ class AlignObjects(FlatCAMTool): self.check_points() elif event.button == right_button and self.app.event_is_dragging is False: + self.reset_color() self.clicked_points = list() self.disconnect_cal_events() self.app.inform.emit('[WARNING_NOTCL] %s' % _("Cancelled by user request.")) def check_points(self): - if self.align_type == 'sp': - if len(self.clicked_points) == 1: - self.app.inform.emit(_("Get First alignment point on the aligner object.")) - self.target_obj = self.aligner_obj + if len(self.clicked_points) == 1: + self.app.inform.emit('%s: %s. %s' % ( + _("First Point"), _("Click on the DESTINATION point."), _(" Or right click to cancel."))) + self.target_obj = self.aligner_obj + self.reset_color() + self.set_color() - if len(self.clicked_points) == 2: + if len(self.clicked_points) == 2: + self.align_translate() + if self.align_type == 'sp': self.app.inform.emit('[success] %s' % _("Done.")) - self.align_translate() self.app.plot_all() self.disconnect_cal_events() - else: - if len(self.clicked_points) == 1: - self.app.inform.emit(_("Get Second alignment point on aligned object. Or right click to cancel.")) + return + else: + self.app.inform.emit('%s: %s. %s' % ( + _("Second Point"), _("Click on the START point."), _(" Or right click to cancel."))) + self.target_obj = self.aligned_obj + self.reset_color() + self.set_color() - if len(self.clicked_points) == 2: - self.app.inform.emit(_("Get First alignment point on the aligner object.")) - self.target_obj = self.aligner_obj + if len(self.clicked_points) == 3: + self.app.inform.emit('%s: %s. %s' % ( + _("Second Point"), _("Click on the DESTINATION point."), _(" Or right click to cancel."))) + self.target_obj = self.aligner_obj + self.reset_color() + self.set_color() - if len(self.clicked_points) == 3: - self.app.inform.emit(_("Get Second alignment point on the aligner object. Or right click to cancel.")) + if len(self.clicked_points) == 4: + self.align_rotate() + self.app.inform.emit('[success] %s' % _("Done.")) - if len(self.clicked_points) == 4: - self.app.inform.emit('[success] %s' % _("Done.")) - self.align_translate() - self.align_rotate() - self.app.plot_all() - - self.disconnect_cal_events() + self.disconnect_cal_events() + self.app.plot_all() def align_translate(self): dx = self.clicked_points[1][0] - self.clicked_points[0][0] @@ -477,9 +499,27 @@ class AlignObjects(FlatCAMTool): self.canvas.graph_event_disconnect(self.mr) self.local_connected = False - self.target_obj = None - self.aligned_obj = None - self.aligner_obj = None + + self.aligner_old_fill_color = None + self.aligner_old_line_color = None + self.aligned_old_fill_color = None + self.aligned_old_line_color = None + + def set_color(self): + new_color = "#15678abf" + new_line_color = new_color + self.target_obj.shapes.redraw( + update_colors=(new_color, new_line_color) + ) + + def reset_color(self): + self.aligned_obj.shapes.redraw( + update_colors=(self.aligned_old_fill_color, self.aligned_old_line_color) + ) + + self.aligner_obj.shapes.redraw( + update_colors=(self.aligner_old_fill_color, self.aligner_old_line_color) + ) def reset_fields(self): self.object_combo.setRootModelIndex(self.app.collection.index(0, 0, QtCore.QModelIndex())) diff --git a/flatcamTools/ToolExtractDrills.py b/flatcamTools/ToolExtractDrills.py index e0c72c95..d75a61b5 100644 --- a/flatcamTools/ToolExtractDrills.py +++ b/flatcamTools/ToolExtractDrills.py @@ -125,15 +125,25 @@ class ToolExtractDrills(FlatCAMTool): grid1.setColumnStretch(0, 0) grid1.setColumnStretch(1, 1) + self.method_label = QtWidgets.QLabel('%s' % _("Method")) + grid1.addWidget(self.method_label, 2, 0, 1, 2) + # ## Axis - self.hole_size_radio = RadioSet([{'label': _("Fixed"), 'value': 'fixed'}, - {'label': _("Proportional"), 'value': 'prop'}]) + self.hole_size_radio = RadioSet( + [ + {'label': _("Fixed Diameter"), 'value': 'fixed'}, + {'label': _("Fixed Annular Ring"), 'value': 'ring'}, + {'label': _("Proportional"), 'value': 'prop'} + ], + orientation='vertical', + stretch=False) + self.hole_size_label = QtWidgets.QLabel('%s:' % _("Hole Size")) self.hole_size_label.setToolTip( - _("The type of hole size. Can be:\n" - "- Fixed -> all holes will have a set size\n" - "- Proprotional -> each hole will havea a variable size\n" - "such as to preserve a set annular ring")) + _("The selected method of extracting the drills. Can be:\n" + "- Fixed Diameter -> all holes will have a set size\n" + "- Fixed Annular Ring -> all holes will have a set annular ring\n" + "- Proportional -> each hole size will be a fraction of the pad size")) grid1.addWidget(self.hole_size_label, 3, 0) grid1.addWidget(self.hole_size_radio, 3, 1) @@ -145,18 +155,27 @@ class ToolExtractDrills(FlatCAMTool): separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) grid1.addWidget(separator_line, 5, 0, 1, 2) + # Annular Ring + self.fixed_label = QtWidgets.QLabel('%s' % _("Fixed Diameter")) + grid1.addWidget(self.fixed_label, 6, 0, 1, 2) + # Diameter value self.dia_entry = FCDoubleSpinner() self.dia_entry.set_precision(self.decimals) self.dia_entry.set_range(0.0000, 9999.9999) - self.dia_label = QtWidgets.QLabel('%s:' % _("Diameter")) + self.dia_label = QtWidgets.QLabel('%s:' % _("Value")) self.dia_label.setToolTip( _("Fixed hole diameter.") ) - grid1.addWidget(self.dia_label, 7, 0) - grid1.addWidget(self.dia_entry, 7, 1) + grid1.addWidget(self.dia_label, 8, 0) + grid1.addWidget(self.dia_entry, 8, 1) + + separator_line = QtWidgets.QFrame() + separator_line.setFrameShape(QtWidgets.QFrame.HLine) + separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) + grid1.addWidget(separator_line, 9, 0, 1, 2) self.ring_frame = QtWidgets.QFrame() self.ring_frame.setContentsMargins(0, 0, 0, 0) @@ -173,7 +192,7 @@ class ToolExtractDrills(FlatCAMTool): self.ring_box.addLayout(grid2) # Annular Ring value - self.ring_label = QtWidgets.QLabel('%s' % _("Annular Ring")) + self.ring_label = QtWidgets.QLabel('%s' % _("Fixed Annular Ring")) self.ring_label.setToolTip( _("The size of annular ring.\n" "The copper sliver between the drill hole exterior\n" @@ -246,6 +265,35 @@ class ToolExtractDrills(FlatCAMTool): grid2.addWidget(self.other_ring_label, 5, 0) grid2.addWidget(self.other_ring_entry, 5, 1) + grid3 = QtWidgets.QGridLayout() + self.layout.addLayout(grid3) + grid3.setColumnStretch(0, 0) + grid3.setColumnStretch(1, 1) + + separator_line = QtWidgets.QFrame() + separator_line.setFrameShape(QtWidgets.QFrame.HLine) + separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) + grid3.addWidget(separator_line, 1, 0, 1, 2) + + # Annular Ring value + self.prop_label = QtWidgets.QLabel('%s' % _("Proportional Diameter")) + grid3.addWidget(self.prop_label, 2, 0, 1, 2) + + # Diameter value + self.factor_entry = FCDoubleSpinner(suffix='%') + self.factor_entry.set_precision(self.decimals) + self.factor_entry.set_range(0.0000, 100.0000) + self.factor_entry.setSingleStep(0.1) + + self.factor_label = QtWidgets.QLabel('%s:' % _("Value")) + self.factor_label.setToolTip( + _("Proportional Diameter.\n" + "The drill diameter will be a fraction of the pad size.") + ) + + grid3.addWidget(self.factor_label, 3, 0) + grid3.addWidget(self.factor_entry, 3, 1) + # Extract drills from Gerber apertures flashes (pads) self.e_drills_button = QtWidgets.QPushButton(_("Extract Drills")) self.e_drills_button.setToolTip( @@ -280,6 +328,13 @@ class ToolExtractDrills(FlatCAMTool): self.rectangular_ring_entry.setEnabled(False) self.other_ring_entry.setEnabled(False) + self.dia_entry.setDisabled(True) + self.dia_label.setDisabled(True) + self.factor_label.setDisabled(True) + self.factor_entry.setDisabled(True) + + self.ring_frame.setDisabled(True) + # ## Signals self.hole_size_radio.activated_custom.connect(self.on_hole_size_toggle) self.e_drills_button.clicked.connect(self.on_extract_drills_click) @@ -359,6 +414,8 @@ class ToolExtractDrills(FlatCAMTool): self.rectangular_cb.set_value(self.app.defaults["tools_edrills_rectangular"]) self.other_cb.set_value(self.app.defaults["tools_edrills_others"]) + self.factor_entry.set_value(float(self.app.defaults["tools_edrills_hole_prop_factor"])) + def on_extract_drills_click(self): drill_dia = self.dia_entry.get_value() @@ -368,6 +425,8 @@ class ToolExtractDrills(FlatCAMTool): rect_r_val = self.rectangular_ring_entry.get_value() other_r_val = self.other_ring_entry.get_value() + prop_factor = self.factor_entry.get_value() / 100.0 + drills = list() tools = dict() @@ -376,7 +435,7 @@ class ToolExtractDrills(FlatCAMTool): try: fcobj = model_index.internalPointer().obj - except Exception as e: + except Exception: self.app.inform.emit('[WARNING_NOTCL] %s' % _("There is no Gerber object loaded ...")) return @@ -421,7 +480,7 @@ class ToolExtractDrills(FlatCAMTool): if 'solid_geometry' not in tools["1"] or not tools["1"]['solid_geometry']: self.app.inform.emit('[WARNING_NOTCL] %s' % _("No drills extracted. Try different parameters.")) return - else: + elif mode == 'ring': drills_found = set() for apid, apid_value in fcobj.apertures.items(): ap_type = apid_value['type'] @@ -435,9 +494,9 @@ class ToolExtractDrills(FlatCAMTool): height = float(apid_value['height']) if self.oblong_cb.get_value(): if width > height: - dia = float(apid_value['height']) - (2 * rect_r_val) + dia = float(apid_value['height']) - (2 * oblong_r_val) else: - dia = float(apid_value['width']) - (2 * rect_r_val) + dia = float(apid_value['width']) - (2 * oblong_r_val) elif ap_type == 'R': width = float(apid_value['width']) height = float(apid_value['height']) @@ -506,6 +565,91 @@ class ToolExtractDrills(FlatCAMTool): if True not in drills_found: self.app.inform.emit('[WARNING_NOTCL] %s' % _("No drills extracted. Try different parameters.")) return + else: + drills_found = set() + for apid, apid_value in fcobj.apertures.items(): + ap_type = apid_value['type'] + + dia = None + if ap_type == 'C': + if self.circular_cb.get_value(): + dia = float(apid_value['size']) * prop_factor + elif ap_type == 'O': + width = float(apid_value['width']) + height = float(apid_value['height']) + if self.oblong_cb.get_value(): + if width > height: + dia = float(apid_value['height']) * prop_factor + else: + dia = float(apid_value['width']) * prop_factor + elif ap_type == 'R': + width = float(apid_value['width']) + height = float(apid_value['height']) + + # if the height == width (float numbers so the reason for the following) + if abs(float('%.*f' % (self.decimals, width)) - float('%.*f' % (self.decimals, height))) < \ + (10 ** -self.decimals): + if self.square_cb.get_value(): + dia = float(apid_value['height']) * prop_factor + else: + if self.rectangular_cb.get_value(): + if width > height: + dia = float(apid_value['height']) * prop_factor + else: + dia = float(apid_value['width']) * prop_factor + else: + if self.other_cb.get_value(): + try: + dia = float(apid_value['size']) * prop_factor + except KeyError: + if ap_type == 'AM': + pol = apid_value['geometry'][0]['solid'] + x0, y0, x1, y1 = pol.bounds + dx = x1 - x0 + dy = y1 - y0 + if dx <= dy: + dia = dx * prop_factor + else: + dia = dy * prop_factor + + # if dia is None then none of the above applied so we skip the following + if dia is None: + continue + + 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))) < \ + (10 ** -self.decimals): + tool_in_drills = tool + + if tool_in_drills is False: + if tools: + new_tool = max([int(t) for t in tools]) + 1 + tool_in_drills = str(new_tool) + else: + tool_in_drills = "1" + + for geo_el in apid_value['geometry']: + if 'follow' in geo_el and isinstance(geo_el['follow'], Point): + if tool_in_drills not in tools: + tools[tool_in_drills] = {"C": dia} + + drills.append({"point": geo_el['follow'], "tool": tool_in_drills}) + + if 'solid_geometry' not in tools[tool_in_drills]: + tools[tool_in_drills]['solid_geometry'] = list() + else: + tools[tool_in_drills]['solid_geometry'].append(geo_el['follow']) + + if tool_in_drills in tools: + if 'solid_geometry' not in tools[tool_in_drills] or not tools[tool_in_drills]['solid_geometry']: + drills_found.add(False) + else: + drills_found.add(True) + + if True not in drills_found: + self.app.inform.emit('[WARNING_NOTCL] %s' % _("No drills extracted. Try different parameters.")) + return def obj_init(obj_inst, app_inst): obj_inst.tools = tools @@ -518,16 +662,36 @@ class ToolExtractDrills(FlatCAMTool): def on_hole_size_toggle(self, val): if val == "fixed": + self.fixed_label.setDisabled(False) self.dia_entry.setDisabled(False) self.dia_label.setDisabled(False) self.ring_frame.setDisabled(True) - else: + + self.prop_label.setDisabled(True) + self.factor_label.setDisabled(True) + self.factor_entry.setDisabled(True) + elif val == "ring": + self.fixed_label.setDisabled(True) self.dia_entry.setDisabled(True) self.dia_label.setDisabled(True) self.ring_frame.setDisabled(False) + self.prop_label.setDisabled(True) + self.factor_label.setDisabled(True) + self.factor_entry.setDisabled(True) + elif val == "prop": + self.fixed_label.setDisabled(True) + self.dia_entry.setDisabled(True) + self.dia_label.setDisabled(True) + + self.ring_frame.setDisabled(True) + + self.prop_label.setDisabled(False) + self.factor_label.setDisabled(False) + self.factor_entry.setDisabled(False) + def reset_fields(self): self.gerber_object_combo.setRootModelIndex(self.app.collection.index(0, 0, QtCore.QModelIndex())) self.gerber_object_combo.setCurrentIndex(0)