From eea66c031192c18262d25a36e2121c8d2a4a42de Mon Sep 17 00:00:00 2001 From: Marius Stanciu Date: Sat, 10 Aug 2019 14:59:29 +0300 Subject: [PATCH] - added new feature in NCC Tool: now another object can be used as reference for the area extent to be cleared of copper --- FlatCAMApp.py | 2 + FlatCAMObj.py | 4 +- README.md | 1 + flatcamGUI/FlatCAMGUI.py | 13 ++++ flatcamTools/ToolDblSided.py | 2 +- flatcamTools/ToolNonCopperClear.py | 105 +++++++++++++++++++++++++++-- 6 files changed, 120 insertions(+), 7 deletions(-) diff --git a/FlatCAMApp.py b/FlatCAMApp.py index 921cf11f..09498b16 100644 --- a/FlatCAMApp.py +++ b/FlatCAMApp.py @@ -513,6 +513,7 @@ class App(QtCore.QObject): "tools_nccconnect": self.ui.tools_defaults_form.tools_ncc_group.ncc_connect_cb, "tools_ncccontour": self.ui.tools_defaults_form.tools_ncc_group.ncc_contour_cb, "tools_nccrest": self.ui.tools_defaults_form.tools_ncc_group.ncc_rest_cb, + "tools_nccref": self.ui.tools_defaults_form.tools_ncc_group.reference_radio, # CutOut Tool "tools_cutouttooldia": self.ui.tools_defaults_form.tools_cutout_group.cutout_tooldia_entry, @@ -852,6 +853,7 @@ class App(QtCore.QObject): "tools_nccconnect": True, "tools_ncccontour": True, "tools_nccrest": False, + "tools_nccref": 'itself', "tools_cutouttooldia": 0.00393701, "tools_cutoutkind": "single", diff --git a/FlatCAMObj.py b/FlatCAMObj.py index 4b84e0e7..260f63df 100644 --- a/FlatCAMObj.py +++ b/FlatCAMObj.py @@ -3838,7 +3838,7 @@ class FlatCAMGeometry(FlatCAMObj, Geometry): # populate the form with the data from the tool associated with the row parameter try: item = self.ui.geo_tools_table.item(current_row, 5) - if item is not None: + if type(item) is not None: tooluid = int(item.text()) else: return @@ -3856,7 +3856,7 @@ class FlatCAMGeometry(FlatCAMObj, Geometry): else: return except Exception as e: - log.debug("Tool missing. Add a tool in Geo Tool Table. %s" % str(e)) + log.debug("Tool missing in ui_update_v_shape(). Add a tool in Geo Tool Table. %s" % str(e)) return try: diff --git a/README.md b/README.md index 6e026aa2..93487e94 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ CAD program, and create G-Code for Isolation routing. - finished added 'Area' type of Paint in Paint Tool - fixed bug that created a choppy geometry for CNCJob when working in INCH - fixed bug that did not asked the user to save the preferences after importing a new set of preferences, after the user is trying to close the Preferences tab window +- added new feature in NCC Tool: now another object can be used as reference for the area extent to be cleared of copper 7.09.2019 diff --git a/flatcamGUI/FlatCAMGUI.py b/flatcamGUI/FlatCAMGUI.py index 25bebdc9..7f973b6a 100644 --- a/flatcamGUI/FlatCAMGUI.py +++ b/flatcamGUI/FlatCAMGUI.py @@ -5875,6 +5875,19 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI): self.ncc_rest_cb = FCCheckBox() grid0.addWidget(self.ncc_rest_cb, 6, 1) + # ## Reference + self.reference_radio = RadioSet([{'label': _('Itself'), 'value': 'itself'}, + {'label': _('Box'), 'value': 'box'}]) + reference_label = QtWidgets.QLabel(_("Reference:")) + reference_label.setToolTip( + _("When choosing the 'Itself' option the non copper clearing extent\n" + "is based on the object that is copper cleared.\n " + "Choosing the 'Box' option will do non copper clearing within the box\n" + "specified by another object different than the one that is copper cleared.") + ) + grid0.addWidget(reference_label, 7, 0) + grid0.addWidget(self.reference_radio, 7, 1) + self.layout.addStretch() diff --git a/flatcamTools/ToolDblSided.py b/flatcamTools/ToolDblSided.py index 2ed9b47b..bd934605 100644 --- a/flatcamTools/ToolDblSided.py +++ b/flatcamTools/ToolDblSided.py @@ -171,8 +171,8 @@ class DblSidedTool(FlatCAMTool): grid_lay2.addWidget(self.add_point_button, 11, 1) self.point_entry = EvalEntry() - self.point_box_container.addWidget(self.point_entry) + self.box_combo = QtWidgets.QComboBox() self.box_combo.setModel(self.app.collection) self.box_combo.setRootModelIndex(self.app.collection.index(0, 0, QtCore.QModelIndex())) diff --git a/flatcamTools/ToolNonCopperClear.py b/flatcamTools/ToolNonCopperClear.py index 9e36da34..99d42368 100644 --- a/flatcamTools/ToolNonCopperClear.py +++ b/flatcamTools/ToolNonCopperClear.py @@ -235,6 +235,51 @@ class NonCopperClear(FlatCAMTool, Gerber): self.ncc_rest_cb = FCCheckBox() grid3.addWidget(self.ncc_rest_cb, 6, 1) + # ## Reference + self.reference_radio = RadioSet([{'label': _('Itself'), 'value': 'itself'}, + {'label': _('Box'), 'value': 'box'}]) + self.reference_label = QtWidgets.QLabel(_("Reference:")) + self.reference_label.setToolTip( + _("- 'Itself': the non copper clearing extent\n" + "is based on the object that is copper cleared.\n " + "- 'Box': will do non copper clearing within the box\n" + "specified by the object selected in the Ref. Object combobox.") + ) + grid3.addWidget(self.reference_label, 7, 0) + grid3.addWidget(self.reference_radio, 7, 1) + + grid4 = QtWidgets.QGridLayout() + self.tools_box.addLayout(grid4) + + self.box_combo_type_label = QtWidgets.QLabel(_("Ref. Type:")) + self.box_combo_type_label.setToolTip( + _("The type of FlatCAM object to be used as non copper clearing reference.\n" + "It can be Gerber, Excellon or Geometry.") + ) + self.box_combo_type = QtWidgets.QComboBox() + self.box_combo_type.addItem(_("Gerber Reference Box Object")) + self.box_combo_type.addItem(_("Excellon Reference Box Object")) + self.box_combo_type.addItem(_("Geometry Reference Box Object")) + + grid4.addWidget(self.box_combo_type_label, 0, 0) + grid4.addWidget(self.box_combo_type, 0, 1) + + self.box_combo_label = QtWidgets.QLabel(_("Ref. Object:")) + self.box_combo_label.setToolTip( + _("The FlatCAM object to be used as non copper clearing reference.") + ) + self.box_combo = QtWidgets.QComboBox() + self.box_combo.setModel(self.app.collection) + self.box_combo.setRootModelIndex(self.app.collection.index(0, 0, QtCore.QModelIndex())) + self.box_combo.setCurrentIndex(1) + grid4.addWidget(self.box_combo_label, 1, 0) + grid4.addWidget(self.box_combo, 1, 1) + + self.box_combo.hide() + self.box_combo_label.hide() + self.box_combo_type.hide() + self.box_combo_type_label.hide() + self.generate_ncc_button = QtWidgets.QPushButton(_('Generate Geometry')) self.generate_ncc_button.setToolTip( _("Create the Geometry Object\n" @@ -251,6 +296,9 @@ class NonCopperClear(FlatCAMTool, Gerber): self.obj_name = "" self.ncc_obj = None + self.bound_obj_name = "" + self.bound_obj = None + self.tools_box.addStretch() self.addtool_btn.clicked.connect(self.on_tool_add) @@ -258,6 +306,9 @@ class NonCopperClear(FlatCAMTool, Gerber): self.deltool_btn.clicked.connect(self.on_tool_delete) self.generate_ncc_button.clicked.connect(self.on_ncc) + self.box_combo_type.currentIndexChanged.connect(self.on_combo_box_type) + self.reference_radio.group_toggle_fn = self.on_toggle_reference + def install(self, icon=None, separator=None, **kwargs): FlatCAMTool.install(self, icon, separator, shortcut='ALT+N', **kwargs) @@ -293,6 +344,7 @@ class NonCopperClear(FlatCAMTool, Gerber): self.ncc_connect_cb.set_value(self.app.defaults["tools_nccconnect"]) self.ncc_contour_cb.set_value(self.app.defaults["tools_ncccontour"]) self.ncc_rest_cb.set_value(self.app.defaults["tools_nccrest"]) + self.reference_radio.set_value(self.app.defaults["tools_nccref"]) self.tools_table.setupContextMenu() self.tools_table.addContextMenu( @@ -365,8 +417,12 @@ class NonCopperClear(FlatCAMTool, Gerber): 'solid_geometry': [] } }) + self.obj_name = "" self.ncc_obj = None + self.bound_obj_name = "" + self.bound_obj = None + self.tool_type_item_options = ["C1", "C2", "C3", "C4", "B", "V"] self.units = self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().upper() @@ -464,6 +520,23 @@ class NonCopperClear(FlatCAMTool, Gerber): except (TypeError, AttributeError): pass + def on_combo_box_type(self): + obj_type = self.box_combo_type.currentIndex() + self.box_combo.setRootModelIndex(self.app.collection.index(obj_type, 0, QtCore.QModelIndex())) + self.box_combo.setCurrentIndex(0) + + def on_toggle_reference(self): + if self.reference_radio.get_value() == "itself": + self.box_combo.hide() + self.box_combo_label.hide() + self.box_combo_type.hide() + self.box_combo_type_label.hide() + else: + self.box_combo.show() + self.box_combo_label.show() + self.box_combo_type.show() + self.box_combo_type_label.show() + def on_tool_add(self, dia=None, muted=None): self.ui_disconnect() @@ -647,7 +720,7 @@ class NonCopperClear(FlatCAMTool, Gerber): self.app.inform.emit(_("[ERROR_NOTCL] Wrong value format entered, " "use a number.")) return - margin = margin if margin else self.app.defaults["tools_nccmargin"] + margin = margin if margin is not None else float(self.app.defaults["tools_nccmargin"]) connect = self.ncc_connect_cb.get_value() connect = connect if connect else self.app.defaults["tools_nccconnect"] @@ -661,6 +734,23 @@ class NonCopperClear(FlatCAMTool, Gerber): pol_method = self.ncc_method_radio.get_value() pol_method = pol_method if pol_method else self.app.defaults["tools_nccmethod"] + if self.reference_radio.get_value() == 'itself': + self.bound_obj_name = self.object_combo.currentText() + # Get source object. + try: + self.bound_obj = self.app.collection.get_by_name(self.bound_obj_name) + except Exception as e: + self.app.inform.emit(_("[ERROR_NOTCL] Could not retrieve object: %s") % self.obj_name) + return "Could not retrieve object: %s" % self.obj_name + else: + self.bound_obj_name = self.box_combo.currentText() + # Get source object. + try: + self.bound_obj = self.app.collection.get_by_name(self.bound_obj_name) + except Exception as e: + self.app.inform.emit(_("[ERROR_NOTCL] Could not retrieve object: %s") % self.obj_name) + return "Could not retrieve object: %s" % self.obj_name + self.obj_name = self.object_combo.currentText() # Get source object. try: @@ -671,10 +761,13 @@ class NonCopperClear(FlatCAMTool, Gerber): # Prepare non-copper polygons try: - bounding_box = self.ncc_obj.solid_geometry.envelope.buffer(distance=margin, - join_style=base.JOIN_STYLE.mitre) + if not isinstance(self.bound_obj.solid_geometry, MultiPolygon): + env_obj = MultiPolygon(self.bound_obj.solid_geometry).convex_hull + else: + env_obj = self.bound_obj.solid_geometry.convex_hull + bounding_box = env_obj.buffer(distance=margin, join_style=base.JOIN_STYLE.mitre) except AttributeError: - self.app.inform.emit(_("[ERROR_NOTCL] No Gerber file available.")) + self.app.inform.emit(_("[ERROR_NOTCL] No object available.")) return # calculate the empty area by subtracting the solid_geometry from the object bounding box geometry @@ -682,6 +775,10 @@ class NonCopperClear(FlatCAMTool, Gerber): if type(empty) is Polygon: empty = MultiPolygon([empty]) + if empty.is_empty: + self.app.inform.emit(_("[ERROR_NOTCL] Could not get the extent of the area to be non copper cleared.")) + return + # clear non copper using standard algorithm if clearing_method is False: self.clear_non_copper(