From f6106dd3191cc4820918704c6a1e1edd24720f7e Mon Sep 17 00:00:00 2001 From: Marius Stanciu Date: Tue, 7 May 2019 02:08:17 +0300 Subject: [PATCH] - updated the ToolPanelize tool so the Gerber panel of type FlatCAMGerber can be isolated like any other FlatCAMGerber object - updated the ToolPanelize tool so it can be edited --- README.md | 2 + flatcamTools/ToolPanelize.py | 141 +++++++++++++++++++++++------------ 2 files changed, 96 insertions(+), 47 deletions(-) diff --git a/README.md b/README.md index 61b3a709..85b7613d 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,8 @@ CAD program, and create G-Code for Isolation routing. - fixed some bugs related to moving an Gerber object with the aperture table in view - added a new parameter in the Edit -> Preferences -> App Preferences named Geo Tolerance. This parameter control the level of geometric detail throughout FlatCAM. It directly influence the effect of Circle Steps parameter. - solved a bug in Excellon Editor that caused app crash when trying to edit a tool in Tool Table due of missing a tool offset +- updated the ToolPanelize tool so the Gerber panel of type FlatCAMGerber can be isolated like any other FlatCAMGerber object +- updated the ToolPanelize tool so it can be edited 5.05.2019 diff --git a/flatcamTools/ToolPanelize.py b/flatcamTools/ToolPanelize.py index 40db1004..b8c08669 100644 --- a/flatcamTools/ToolPanelize.py +++ b/flatcamTools/ToolPanelize.py @@ -13,9 +13,9 @@ import time import gettext import FlatCAMTranslation as fcTranslate +import builtins fcTranslate.apply_language('strings') -import builtins if '_' not in builtins.__dict__: _ = gettext.gettext @@ -39,11 +39,11 @@ class Panelize(FlatCAMTool): """) self.layout.addWidget(title_label) - ## Form Layout + # Form Layout form_layout = QtWidgets.QFormLayout() self.layout.addLayout(form_layout) - ## Type of object to be panelized + # Type of object to be panelized self.type_obj_combo = QtWidgets.QComboBox() self.type_obj_combo.addItem("Gerber") self.type_obj_combo.addItem("Excellon") @@ -56,13 +56,13 @@ class Panelize(FlatCAMTool): self.type_obj_combo_label = QtWidgets.QLabel(_("Object Type:")) self.type_obj_combo_label.setToolTip( _("Specify the type of object to be panelized\n" - "It can be of type: Gerber, Excellon or Geometry.\n" - "The selection here decide the type of objects that will be\n" - "in the Object combobox.") + "It can be of type: Gerber, Excellon or Geometry.\n" + "The selection here decide the type of objects that will be\n" + "in the Object combobox.") ) form_layout.addRow(self.type_obj_combo_label, self.type_obj_combo) - ## Object to be panelized + # Object to be panelized self.object_combo = QtWidgets.QComboBox() self.object_combo.setModel(self.app.collection) self.object_combo.setRootModelIndex(self.app.collection.index(0, 0, QtCore.QModelIndex())) @@ -71,11 +71,11 @@ class Panelize(FlatCAMTool): self.object_label = QtWidgets.QLabel(_("Object:")) self.object_label.setToolTip( _("Object to be panelized. This means that it will\n" - "be duplicated in an array of rows and columns.") + "be duplicated in an array of rows and columns.") ) form_layout.addRow(self.object_label, self.object_combo) - ## Type of Box Object to be used as an envelope for panelization + # Type of Box Object to be used as an envelope for panelization self.type_box_combo = QtWidgets.QComboBox() self.type_box_combo.addItem("Gerber") self.type_box_combo.addItem("Excellon") @@ -89,13 +89,13 @@ class Panelize(FlatCAMTool): self.type_box_combo_label = QtWidgets.QLabel(_("Box Type:")) self.type_box_combo_label.setToolTip( _("Specify the type of object to be used as an container for\n" - "panelization. It can be: Gerber or Geometry type.\n" - "The selection here decide the type of objects that will be\n" - "in the Box Object combobox.") + "panelization. It can be: Gerber or Geometry type.\n" + "The selection here decide the type of objects that will be\n" + "in the Box Object combobox.") ) form_layout.addRow(self.type_box_combo_label, self.type_box_combo) - ## Box + # Box self.box_combo = QtWidgets.QComboBox() self.box_combo.setModel(self.app.collection) self.box_combo.setRootModelIndex(self.app.collection.index(0, 0, QtCore.QModelIndex())) @@ -104,29 +104,29 @@ class Panelize(FlatCAMTool): self.box_combo_label = QtWidgets.QLabel(_("Box Object:")) self.box_combo_label.setToolTip( _("The actual object that is used a container for the\n " - "selected object that is to be panelized.") + "selected object that is to be panelized.") ) form_layout.addRow(self.box_combo_label, self.box_combo) - ## Spacing Columns + # Spacing Columns self.spacing_columns = FCEntry() self.spacing_columns_label = QtWidgets.QLabel(_("Spacing cols:")) self.spacing_columns_label.setToolTip( _("Spacing between columns of the desired panel.\n" - "In current units.") + "In current units.") ) form_layout.addRow(self.spacing_columns_label, self.spacing_columns) - ## Spacing Rows + # Spacing Rows self.spacing_rows = FCEntry() self.spacing_rows_label = QtWidgets.QLabel(_("Spacing rows:")) self.spacing_rows_label.setToolTip( _("Spacing between rows of the desired panel.\n" - "In current units.") + "In current units.") ) form_layout.addRow(self.spacing_rows_label, self.spacing_rows) - ## Columns + # Columns self.columns = FCEntry() self.columns_label = QtWidgets.QLabel(_("Columns:")) self.columns_label.setToolTip( @@ -134,7 +134,7 @@ class Panelize(FlatCAMTool): ) form_layout.addRow(self.columns_label, self.columns) - ## Rows + # Rows self.rows = FCEntry() self.rows_label = QtWidgets.QLabel(_("Rows:")) self.rows_label.setToolTip( @@ -142,26 +142,26 @@ class Panelize(FlatCAMTool): ) form_layout.addRow(self.rows_label, self.rows) - ## Type of resulting Panel object + # Type of resulting Panel object self.panel_type_radio = RadioSet([{'label': 'Gerber', 'value': 'gerber'}, - {'label': 'Geometry', 'value': 'geometry'}]) + {'label': 'Geometry', 'value': 'geometry'}]) self.panel_type_label = QtWidgets.QLabel(_("Panel Type:")) self.panel_type_label.setToolTip( _("Choose the type of object for the panel object:\n" - "- Geometry\n" - "- Gerber") + "- Geometry\n" + "- Gerber") ) form_layout.addRow(self.panel_type_label) form_layout.addRow(self.panel_type_radio) - ## Constrains + # Constrains self.constrain_cb = FCCheckBox(_("Constrain panel within:")) self.constrain_cb.setToolTip( _("Area define by DX and DY within to constrain the panel.\n" - "DX and DY values are in current units.\n" - "Regardless of how many columns and rows are desired,\n" - "the final panel will have as many columns and rows as\n" - "they fit completely within selected area.") + "DX and DY values are in current units.\n" + "Regardless of how many columns and rows are desired,\n" + "the final panel will have as many columns and rows as\n" + "they fit completely within selected area.") ) form_layout.addRow(self.constrain_cb) @@ -169,7 +169,7 @@ class Panelize(FlatCAMTool): self.x_width_lbl = QtWidgets.QLabel(_("Width (DX):")) self.x_width_lbl.setToolTip( _("The width (DX) within which the panel must fit.\n" - "In current units.") + "In current units.") ) form_layout.addRow(self.x_width_lbl, self.x_width_entry) @@ -177,14 +177,14 @@ class Panelize(FlatCAMTool): self.y_height_lbl = QtWidgets.QLabel(_("Height (DY):")) self.y_height_lbl.setToolTip( _("The height (DY)within which the panel must fit.\n" - "In current units.") + "In current units.") ) form_layout.addRow(self.y_height_lbl, self.y_height_entry) self.constrain_sel = OptionalInputSection( self.constrain_cb, [self.x_width_lbl, self.x_width_entry, self.y_height_lbl, self.y_height_entry]) - ## Buttons + # Buttons hlay_2 = QtWidgets.QHBoxLayout() self.layout.addLayout(hlay_2) @@ -192,14 +192,14 @@ class Panelize(FlatCAMTool): self.panelize_object_button = QtWidgets.QPushButton(_("Panelize Object")) self.panelize_object_button.setToolTip( _("Panelize the specified object around the specified box.\n" - "In other words it creates multiple copies of the source object,\n" - "arranged in a 2D array of rows and columns.") + "In other words it creates multiple copies of the source object,\n" + "arranged in a 2D array of rows and columns.") ) hlay_2.addWidget(self.panelize_object_button) self.layout.addStretch() - ## Signals + # Signals self.panelize_object_button.clicked.connect(self.on_panelize) self.type_obj_combo.currentIndexChanged.connect(self.on_type_obj_index_changed) self.type_box_combo.currentIndexChanged.connect(self.on_type_box_index_changed) @@ -387,7 +387,6 @@ class Panelize(FlatCAMTool): panel_type = str(self.panel_type_radio.get_value()) - if 0 in {columns, rows}: self.app.inform.emit(_("[ERROR_NOTCL] Columns or Rows are zero value. Change them to a positive integer.")) return "Columns or Rows are zero value. Change them to a positive integer." @@ -471,7 +470,11 @@ class Panelize(FlatCAMTool): if type(geom) == list: geoms = list() for local_geom in geom: - geoms.append(translate_recursion(local_geom)) + res_geo = translate_recursion(local_geom) + try: + geoms += (res_geo) + except TypeError: + geoms.append(res_geo) return geoms else: return affinity.translate(geom, xoff=currentx, yoff=currenty) @@ -485,6 +488,16 @@ class Panelize(FlatCAMTool): for tool in panel_obj.tools: obj_fin.tools[tool]['solid_geometry'][:] = [] + if isinstance(panel_obj, FlatCAMGerber): + obj_fin.apertures = deepcopy(panel_obj.apertures) + for ap in obj_fin.apertures: + if 'solid_geometry' in obj_fin.apertures[ap]: + obj_fin.apertures[ap]['solid_geometry'] = [] + if 'clear_geometry' in obj_fin.apertures[ap]: + obj_fin.apertures[ap]['clear_geometry'] = [] + if 'follow_geometry' in obj_fin.apertures[ap]: + obj_fin.apertures[ap]['follow_geometry'] = [] + self.app.progress.emit(0) for row in range(rows): currentx = 0.0 @@ -493,21 +506,54 @@ class Panelize(FlatCAMTool): if isinstance(panel_obj, FlatCAMGeometry): if panel_obj.multigeo is True: for tool in panel_obj.tools: - obj_fin.tools[tool]['solid_geometry'].append(translate_recursion( - panel_obj.tools[tool]['solid_geometry']) - ) + geo = translate_recursion(panel_obj.tools[tool]['solid_geometry']) + if isinstance(geo, list): + obj_fin.tools[tool]['solid_geometry'] += geo + else: + obj_fin.tools[tool]['solid_geometry'].append(geo) else: - obj_fin.solid_geometry.append( - translate_recursion(panel_obj.solid_geometry) - ) + geo = translate_recursion(panel_obj.solid_geometry) + if isinstance(geo, list): + obj_fin.solid_geometry += geo + else: + obj_fin.solid_geometry.append(geo) else: - obj_fin.solid_geometry.append( - translate_recursion(panel_obj.solid_geometry) - ) + geo = translate_recursion(panel_obj.solid_geometry) + if isinstance(geo, list): + obj_fin.solid_geometry += geo + else: + obj_fin.solid_geometry.append(geo) + + for apid in panel_obj.apertures: + if 'solid_geometry' in panel_obj.apertures[apid]: + geo_aper = translate_recursion(panel_obj.apertures[apid]['solid_geometry']) + if isinstance(geo_aper, list): + obj_fin.apertures[apid]['solid_geometry'] += geo_aper + else: + obj_fin.apertures[apid]['solid_geometry'].append(geo_aper) + + if 'clear_geometry' in panel_obj.apertures[apid]: + geo_aper = translate_recursion(panel_obj.apertures[apid]['clear_geometry']) + if isinstance(geo_aper, list): + obj_fin.apertures[apid]['clear_geometry'] += geo_aper + else: + obj_fin.apertures[apid]['clear_geometry'].append(geo_aper) + + if 'follow_geometry' in panel_obj.apertures[apid]: + geo_aper = translate_recursion(panel_obj.apertures[apid]['follow_geometry']) + if isinstance(geo_aper, list): + obj_fin.apertures[apid]['follow_geometry'] += geo_aper + else: + obj_fin.apertures[apid]['follow_geometry'].append(geo_aper) currentx += lenghtx currenty += lenghty + app_obj.log.debug("Found %s geometries. Creating a panel geometry cascaded union ..." % + len(obj_fin.solid_geometry)) + obj_fin.solid_geometry = cascaded_union(obj_fin.solid_geometry) + app_obj.log.debug("Finished creating a cascaded union for the panel.") + if isinstance(panel_obj, FlatCAMExcellon): self.app.progress.emit(50) self.app.new_object("excellon", self.outname, job_init_excellon, plot=True, autoselected=True) @@ -520,7 +566,8 @@ class Panelize(FlatCAMTool): self.app.inform.emit(_("[success] Panel done...")) else: self.constrain_flag = False - self.app.inform.emit(_("[WARNING] Too big for the constrain area. Final panel has {col} columns and {row} rows").format( + self.app.inform.emit(_("[WARNING] Too big for the constrain area. " + "Final panel has {col} columns and {row} rows").format( col=columns, row=rows)) proc = self.app.proc_container.new(_("Generating panel ... Please wait."))