From ada271cbd68b4db6eaa87dcbedb31636df60ee40 Mon Sep 17 00:00:00 2001 From: Marius Stanciu Date: Sat, 2 May 2020 15:56:30 +0300 Subject: [PATCH] - modified the Cutout Tool to generate multi-geo objects therefore the set geometry parameters will populate the Geometry Object UI - modified the Panelize Tool to optimize the output from Cutout Tool such that there are no longer overlapping cuts - some string corrections --- CHANGELOG.md | 3 + FlatCAMApp.py | 6 +- flatcamEditors/FlatCAMExcEditor.py | 4 +- flatcamGUI/FlatCAMGUI.py | 2 +- .../preferences/PreferencesUIManager.py | 2 +- flatcamObjects/FlatCAMCNCJob.py | 2 +- flatcamParsers/ParseExcellon.py | 2 +- flatcamTools/ToolCutOut.py | 115 ++++++++++++- flatcamTools/ToolPanelize.py | 155 +++++++++--------- flatcamTools/ToolSolderPaste.py | 2 +- flatcamTools/ToolSub.py | 2 +- locale/de/LC_MESSAGES/strings.po | 6 +- locale/en/LC_MESSAGES/strings.po | 12 +- locale/es/LC_MESSAGES/strings.po | 6 +- locale/fr/LC_MESSAGES/strings.po | 4 +- locale/hu/LC_MESSAGES/strings.po | 16 +- locale/it/LC_MESSAGES/strings.po | 8 +- locale/pt_BR/LC_MESSAGES/strings.po | 6 +- locale/ro/LC_MESSAGES/strings.po | 6 +- locale/ru/LC_MESSAGES/strings.po | 6 +- locale_template/strings.pot | 6 +- tclCommands/TclCommandJoinExcellon.py | 2 +- tclCommands/TclCommandJoinGeometry.py | 2 +- 23 files changed, 238 insertions(+), 137 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b4d0dfd..19054283 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,9 @@ CHANGELOG for FlatCAM beta - fixed bug in Gerber Editor in which the units conversion wasn't calculated correct - fixed bug in Gerber Editor in which the QThread that is started on object edit was not stopped at clean up stage - fixed bug in Gerber Editor that kept all the apertures (including the geometry) of a previously edited object that was not saved after edit +- modified the Cutout Tool to generate multi-geo objects therefore the set geometry parameters will populate the Geometry Object UI +- modified the Panelize Tool to optimize the output from Cutout Tool such that there are no longer overlapping cuts +- some string corrections 01.05.2020 diff --git a/FlatCAMApp.py b/FlatCAMApp.py index 49cc7d0f..5157f436 100644 --- a/FlatCAMApp.py +++ b/FlatCAMApp.py @@ -4111,9 +4111,11 @@ class App(QtCore.QObject): obj.multigeo = True for tooluid, dict_value in obj.tools.items(): dict_value['solid_geometry'] = deepcopy(obj.solid_geometry) + if not isinstance(obj.solid_geometry, list): obj.solid_geometry = [obj.solid_geometry] - obj.solid_geometry[:] = [] + + # obj.solid_geometry[:] = [] obj.plot() self.should_we_save = True @@ -5024,7 +5026,7 @@ class App(QtCore.QObject): self.paste_tool.on_add_tool_by_key() # It's meant to delete tools in tool tables via a 'Delete' shortcut key but only if certain conditions are met - # See description bellow. + # See description below. def on_delete_keypress(self): notebook_widget_name = self.ui.notebook.currentWidget().objectName() diff --git a/flatcamEditors/FlatCAMExcEditor.py b/flatcamEditors/FlatCAMExcEditor.py index 2f2e274c..49dc5eb5 100644 --- a/flatcamEditors/FlatCAMExcEditor.py +++ b/flatcamEditors/FlatCAMExcEditor.py @@ -3226,7 +3226,7 @@ class FlatCAMExcEditor(QtCore.QObject): spec = {"C": float(tool_dia[0])} self.new_tools[name] = spec - # add in self.tools the 'solid_geometry' key, the value (a list) is populated bellow + # add in self.tools the 'solid_geometry' key, the value (a list) is populated below self.new_tools[name]['solid_geometry'] = [] # create the self.drills for the new Excellon object (the one with edited content) @@ -3258,7 +3258,7 @@ class FlatCAMExcEditor(QtCore.QObject): spec = {"C": float(tool_dia[0])} self.new_tools[name] = spec - # add in self.tools the 'solid_geometry' key, the value (a list) is populated bellow + # add in self.tools the 'solid_geometry' key, the value (a list) is populated below self.new_tools[name]['solid_geometry'] = [] # create the self.slots for the new Excellon object (the one with edited content) diff --git a/flatcamGUI/FlatCAMGUI.py b/flatcamGUI/FlatCAMGUI.py index 05c173df..c1b368b4 100644 --- a/flatcamGUI/FlatCAMGUI.py +++ b/flatcamGUI/FlatCAMGUI.py @@ -3232,7 +3232,7 @@ class FlatCAMGUI(QtWidgets.QMainWindow): else: self.app.collection.set_active(names_list[active_index-1]) - # Select the object in the Tree bellow the current one + # Select the object in the Tree below the current one if key == QtCore.Qt.Key_Down: # make sure it works only for the Project Tab who is an instance of KeySensitiveListView focused_wdg = QtWidgets.QApplication.focusWidget() diff --git a/flatcamGUI/preferences/PreferencesUIManager.py b/flatcamGUI/preferences/PreferencesUIManager.py index 7934cdc6..a8a9eab3 100644 --- a/flatcamGUI/preferences/PreferencesUIManager.py +++ b/flatcamGUI/preferences/PreferencesUIManager.py @@ -42,7 +42,7 @@ class PreferencesUIManager: # if Preferences are changed in the Edit -> Preferences tab the value will be set to True self.preferences_changed_flag = False - # when adding entries here read the comments in the method found bellow named: + # when adding entries here read the comments in the method found below named: # def new_object(self, kind, name, initialize, active=True, fit=True, plot=True) self.defaults_form_fields = { # General App diff --git a/flatcamObjects/FlatCAMCNCJob.py b/flatcamObjects/FlatCAMCNCJob.py index fa73b56c..c9a47076 100644 --- a/flatcamObjects/FlatCAMCNCJob.py +++ b/flatcamObjects/FlatCAMCNCJob.py @@ -364,7 +364,7 @@ class CNCJobObject(FlatCAMObj, CNCjob): self.units_found = self.app.defaults['units'] # this signal has to be connected to it's slot before the defaults are populated - # the decision done in the slot has to override the default value set bellow + # the decision done in the slot has to override the default value set below self.ui.toolchange_cb.toggled.connect(self.on_toolchange_custom_clicked) self.form_fields.update({ diff --git a/flatcamParsers/ParseExcellon.py b/flatcamParsers/ParseExcellon.py index ab52e44a..07930005 100644 --- a/flatcamParsers/ParseExcellon.py +++ b/flatcamParsers/ParseExcellon.py @@ -426,7 +426,7 @@ class Excellon(Geometry): # it's possible that tool definition has only tool number and no diameter info # (those could be in another file like PCB Wizard do) # then match.group(2) = None and float(None) will create the exception - # the bellow construction is so each tool will have a slightly different diameter + # the below construction is so each tool will have a slightly different diameter # starting with a default value, to allow Excellon editing after that self.diameterless = True self.app.inform.emit('[WARNING] %s%s %s' % diff --git a/flatcamTools/ToolCutOut.py b/flatcamTools/ToolCutOut.py index 5f7083d8..31f51b31 100644 --- a/flatcamTools/ToolCutOut.py +++ b/flatcamTools/ToolCutOut.py @@ -293,12 +293,12 @@ class CutOut(FlatCAMTool): font-weight: bold; } """) - self.layout.addWidget(self.rect_cutout_object_btn) + grid0.addWidget(self.rect_cutout_object_btn, 21, 0, 1, 2) separator_line = QtWidgets.QFrame() separator_line.setFrameShape(QtWidgets.QFrame.HLine) separator_line.setFrameShadow(QtWidgets.QFrame.Sunken) - grid0.addWidget(separator_line, 21, 0, 1, 2) + grid0.addWidget(separator_line, 22, 0, 1, 2) # Title5 title_manual_label = QtWidgets.QLabel("%s" % _('B. Manual Bridge Gaps')) @@ -307,7 +307,7 @@ class CutOut(FlatCAMTool): "This is done by mouse clicking on the perimeter of the\n" "Geometry object that is used as a cutout object. ") ) - grid0.addWidget(title_manual_label, 22, 0, 1, 2) + grid0.addWidget(title_manual_label, 23, 0, 1, 2) # Manual Geo Object self.man_object_combo = FCComboBox() @@ -322,8 +322,8 @@ class CutOut(FlatCAMTool): ) # self.man_object_label.setMinimumWidth(60) - grid0.addWidget(self.man_object_label, 23, 0, 1, 2) - grid0.addWidget(self.man_object_combo, 24, 0, 1, 2) + grid0.addWidget(self.man_object_label, 25, 0, 1, 2) + grid0.addWidget(self.man_object_combo, 26, 0, 1, 2) self.man_geo_creation_btn = FCButton(_("Generate Manual Geometry")) self.man_geo_creation_btn.setToolTip( @@ -338,7 +338,7 @@ class CutOut(FlatCAMTool): font-weight: bold; } """) - grid0.addWidget(self.man_geo_creation_btn, 25, 0, 1, 2) + grid0.addWidget(self.man_geo_creation_btn, 28, 0, 1, 2) self.man_gaps_creation_btn = FCButton(_("Manual Add Bridge Gaps")) self.man_gaps_creation_btn.setToolTip( @@ -354,7 +354,7 @@ class CutOut(FlatCAMTool): font-weight: bold; } """) - grid0.addWidget(self.man_gaps_creation_btn, 27, 0, 1, 2) + grid0.addWidget(self.man_gaps_creation_btn, 30, 0, 1, 2) self.layout.addStretch() @@ -394,6 +394,9 @@ class CutOut(FlatCAMTool): self.x_pos = None self.y_pos = None + # store the default data for the resulting Geometry Object + self.default_data = {} + # Signals self.ff_cutout_object_btn.clicked.connect(self.on_freeform_cutout) self.rect_cutout_object_btn.clicked.connect(self.on_rectangular_cutout) @@ -454,6 +457,48 @@ class CutOut(FlatCAMTool): self.convex_box.set_value(self.app.defaults['tools_cutout_convexshape']) self.type_obj_radio.set_value('grb') + self.default_data.update({ + "plot": True, + "cutz": float(self.app.defaults["geometry_cutz"]), + "multidepth": self.app.defaults["geometry_multidepth"], + "depthperpass": float(self.app.defaults["geometry_depthperpass"]), + "vtipdia": float(self.app.defaults["geometry_vtipdia"]), + "vtipangle": float(self.app.defaults["geometry_vtipangle"]), + "travelz": float(self.app.defaults["geometry_travelz"]), + "feedrate": float(self.app.defaults["geometry_feedrate"]), + "feedrate_z": float(self.app.defaults["geometry_feedrate_z"]), + "feedrate_rapid": float(self.app.defaults["geometry_feedrate_rapid"]), + "spindlespeed": self.app.defaults["geometry_spindlespeed"], + "dwell": self.app.defaults["geometry_dwell"], + "dwelltime": float(self.app.defaults["geometry_dwelltime"]), + "ppname_g": self.app.defaults["geometry_ppname_g"], + "extracut": self.app.defaults["geometry_extracut"], + "extracut_length": float(self.app.defaults["geometry_extracut_length"]), + "toolchange": self.app.defaults["geometry_toolchange"], + "toolchangexy": self.app.defaults["geometry_toolchangexy"], + "toolchangez": float(self.app.defaults["geometry_toolchangez"]), + "startz": self.app.defaults["geometry_startz"], + "endz": float(self.app.defaults["geometry_endz"]), + + # NCC + "tools_nccoperation": self.app.defaults["tools_nccoperation"], + "tools_nccmilling_type": self.app.defaults["tools_nccmilling_type"], + "tools_nccoverlap": float(self.app.defaults["tools_nccoverlap"]), + "tools_nccmargin": float(self.app.defaults["tools_nccmargin"]), + "tools_nccmethod": self.app.defaults["tools_nccmethod"], + "tools_nccconnect": self.app.defaults["tools_nccconnect"], + "tools_ncccontour": self.app.defaults["tools_ncccontour"], + "tools_ncc_offset_choice": self.app.defaults["tools_ncc_offset_choice"], + "tools_ncc_offset_value": float(self.app.defaults["tools_ncc_offset_value"]), + + # Paint + "tools_paintoverlap": float(self.app.defaults["tools_paintoverlap"]), + "tools_paintmargin": float(self.app.defaults["tools_paintmargin"]), + "tools_paintmethod": self.app.defaults["tools_paintmethod"], + "tools_pathconnect": self.app.defaults["tools_pathconnect"], + "tools_paintcontour": self.app.defaults["tools_paintcontour"], + }) + def on_freeform_cutout(self): log.debug("Cutout.on_freeform_cutout() was launched ...") @@ -622,8 +667,8 @@ class CutOut(FlatCAMTool): solid_geo += cutout_handler(geom=geom_struct) - geo_obj.solid_geometry = deepcopy(solid_geo) xmin, ymin, xmax, ymax = recursive_bounds(geo_obj.solid_geometry) + geo_obj.solid_geometry = deepcopy(solid_geo) geo_obj.options['xmin'] = xmin geo_obj.options['ymin'] = ymin geo_obj.options['xmax'] = xmax @@ -633,6 +678,23 @@ class CutOut(FlatCAMTool): geo_obj.options['multidepth'] = self.mpass_cb.get_value() geo_obj.options['depthperpass'] = self.maxdepth_entry.get_value() + geo_obj.tools.update({ + 1: { + 'tooldia': str(dia), + 'offset': 'Path', + 'offset_value': 0.0, + 'type': _('Rough'), + 'tool_type': 'C1', + 'data': self.default_data, + 'solid_geometry': geo_obj.solid_geometry + } + }) + geo_obj.multigeo = True + geo_obj.tools[1]['data']['name'] = outname + geo_obj.tools[1]['data']['cutz'] = self.cutz_entry.get_value() + geo_obj.tools[1]['data']['multidepth'] = self.mpass_cb.get_value() + geo_obj.tools[1]['data']['depthperpass'] = self.maxdepth_entry.get_value() + outname = cutout_obj.options["name"] + "_cutout" self.app.new_object('geometry', outname, geo_init) @@ -759,6 +821,7 @@ class CutOut(FlatCAMTool): return proc_geometry if kind == 'single': + # fuse the lines object_geo = unary_union(object_geo) xmin, ymin, xmax, ymax = object_geo.bounds @@ -805,11 +868,28 @@ class CutOut(FlatCAMTool): _("Rectangular cutout with negative margin is not possible.")) return "fail" - geo_obj.solid_geometry = deepcopy(solid_geo) geo_obj.options['cnctooldia'] = str(dia) geo_obj.options['cutz'] = self.cutz_entry.get_value() geo_obj.options['multidepth'] = self.mpass_cb.get_value() geo_obj.options['depthperpass'] = self.maxdepth_entry.get_value() + geo_obj.solid_geometry = deepcopy(solid_geo) + + geo_obj.tools.update({ + 1: { + 'tooldia': str(dia), + 'offset': 'Path', + 'offset_value': 0.0, + 'type': _('Rough'), + 'tool_type': 'C1', + 'data': self.default_data, + 'solid_geometry': geo_obj.solid_geometry + } + }) + geo_obj.multigeo = True + geo_obj.tools[1]['data']['name'] = outname + geo_obj.tools[1]['data']['cutz'] = self.cutz_entry.get_value() + geo_obj.tools[1]['data']['multidepth'] = self.mpass_cb.get_value() + geo_obj.tools[1]['data']['depthperpass'] = self.maxdepth_entry.get_value() outname = cutout_obj.options["name"] + "_cutout" ret = self.app.new_object('geometry', outname, geo_init) @@ -954,6 +1034,23 @@ class CutOut(FlatCAMTool): geo_obj.options['multidepth'] = self.mpass_cb.get_value() geo_obj.options['depthperpass'] = self.maxdepth_entry.get_value() + geo_obj.tools.update({ + 1: { + 'tooldia': str(dia), + 'offset': 'Path', + 'offset_value': 0.0, + 'type': _('Rough'), + 'tool_type': 'C1', + 'data': self.default_data, + 'solid_geometry': geo_obj.solid_geometry + } + }) + geo_obj.multigeo = True + geo_obj.tools[1]['data']['name'] = outname + geo_obj.tools[1]['data']['cutz'] = self.cutz_entry.get_value() + geo_obj.tools[1]['data']['multidepth'] = self.mpass_cb.get_value() + geo_obj.tools[1]['data']['depthperpass'] = self.maxdepth_entry.get_value() + outname = cutout_obj.options["name"] + "_cutout" self.app.new_object('geometry', outname, geo_init) diff --git a/flatcamTools/ToolPanelize.py b/flatcamTools/ToolPanelize.py index 4195e303..8995da05 100644 --- a/flatcamTools/ToolPanelize.py +++ b/flatcamTools/ToolPanelize.py @@ -14,6 +14,8 @@ from copy import deepcopy import numpy as np import shapely.affinity as affinity +from shapely.ops import unary_union +from shapely.geometry import LineString import gettext import FlatCAMTranslation as fcTranslate @@ -402,19 +404,18 @@ class Panelize(FlatCAMTool): def on_panelize(self): name = self.object_combo.currentText() - # Get source object. + # Get source object to be panelized. try: - panel_obj = self.app.collection.get_by_name(str(name)) + panel_source_obj = self.app.collection.get_by_name(str(name)) except Exception as e: log.debug("Panelize.on_panelize() --> %s" % str(e)) - self.app.inform.emit('[ERROR_NOTCL] %s: %s' % - (_("Could not retrieve object"), name)) + self.app.inform.emit('[ERROR_NOTCL] %s: %s' % (_("Could not retrieve object"), name)) return "Could not retrieve object: %s" % name - if panel_obj is None: + if panel_source_obj is None: self.app.inform.emit('[ERROR_NOTCL] %s: %s' % - (_("Object not found"), panel_obj)) - return "Object not found: %s" % panel_obj + (_("Object not found"), panel_source_obj)) + return "Object not found: %s" % panel_source_obj boxname = self.box_combo.currentText() @@ -422,17 +423,15 @@ class Panelize(FlatCAMTool): box = self.app.collection.get_by_name(boxname) except Exception as e: log.debug("Panelize.on_panelize() --> %s" % str(e)) - self.app.inform.emit('[ERROR_NOTCL] %s: %s' % - (_("Could not retrieve object"), boxname)) + self.app.inform.emit('[ERROR_NOTCL] %s: %s' % (_("Could not retrieve object"), boxname)) return "Could not retrieve object: %s" % boxname if box is None: - self.app.inform.emit('[WARNING_NOTCL]%s: %s' % - (_("No object Box. Using instead"), panel_obj)) + self.app.inform.emit('[WARNING_NOTCL]%s: %s' % (_("No object Box. Using instead"), panel_source_obj)) self.reference_radio.set_value('bbox') if self.reference_radio.get_value() == 'bbox': - box = panel_obj + box = panel_source_obj self.outname = name + '_panelized' @@ -478,20 +477,20 @@ class Panelize(FlatCAMTool): rows -= 1 panel_lengthy = ((ymax - ymin) * rows) + (spacing_rows * (rows - 1)) - if panel_obj.kind == 'excellon' or panel_obj.kind == 'geometry': + if panel_source_obj.kind == 'excellon' or panel_source_obj.kind == 'geometry': # make a copy of the panelized Excellon or Geometry tools copied_tools = {} - for tt, tt_val in list(panel_obj.tools.items()): + for tt, tt_val in list(panel_source_obj.tools.items()): copied_tools[tt] = deepcopy(tt_val) - if panel_obj.kind == 'gerber': + if panel_source_obj.kind == 'gerber': # make a copy of the panelized Gerber apertures copied_apertures = {} - for tt, tt_val in list(panel_obj.apertures.items()): + for tt, tt_val in list(panel_source_obj.apertures.items()): copied_apertures[tt] = deepcopy(tt_val) - def panelize_2(): - if panel_obj is not None: + def panelize_worker(): + if panel_source_obj is not None: self.app.inform.emit(_("Generating panel ... ")) def job_init_excellon(obj_fin, app_obj): @@ -501,15 +500,15 @@ class Panelize(FlatCAMTool): obj_fin.slots = [] obj_fin.solid_geometry = [] - for option in panel_obj.options: + for option in panel_source_obj.options: if option != 'name': try: - obj_fin.options[option] = panel_obj.options[option] + obj_fin.options[option] = panel_source_obj.options[option] except KeyError: log.warning("Failed to copy option. %s" % str(option)) - geo_len_drills = len(panel_obj.drills) if panel_obj.drills else 0 - geo_len_slots = len(panel_obj.slots) if panel_obj.slots else 0 + geo_len_drills = len(panel_source_obj.drills) if panel_source_obj.drills else 0 + geo_len_slots = len(panel_source_obj.slots) if panel_source_obj.slots else 0 element = 0 for row in range(rows): @@ -518,9 +517,9 @@ class Panelize(FlatCAMTool): element += 1 old_disp_number = 0 - if panel_obj.drills: + if panel_source_obj.drills: drill_nr = 0 - for tool_dict in panel_obj.drills: + for tool_dict in panel_source_obj.drills: if self.app.abort_flag: # graceful abort requested by the user raise grace @@ -543,9 +542,9 @@ class Panelize(FlatCAMTool): disp_number)) old_disp_number = disp_number - if panel_obj.slots: + if panel_source_obj.slots: slot_nr = 0 - for tool_dict in panel_obj.slots: + for tool_dict in panel_source_obj.slots: if self.app.abort_flag: # graceful abort requested by the user raise grace @@ -574,8 +573,8 @@ class Panelize(FlatCAMTool): currenty += lenghty obj_fin.create_geometry() - obj_fin.zeros = panel_obj.zeros - obj_fin.units = panel_obj.units + obj_fin.zeros = panel_source_obj.zeros + obj_fin.units = panel_source_obj.units self.app.proc_container.update_view_text('') def job_init_geometry(obj_fin, app_obj): @@ -598,36 +597,36 @@ class Panelize(FlatCAMTool): obj_fin.solid_geometry = [] # create the initial structure on which to create the panel - if panel_obj.kind == 'geometry': - obj_fin.multigeo = panel_obj.multigeo + if panel_source_obj.kind == 'geometry': + obj_fin.multigeo = panel_source_obj.multigeo obj_fin.tools = copied_tools - if panel_obj.multigeo is True: - for tool in panel_obj.tools: + if panel_source_obj.multigeo is True: + for tool in panel_source_obj.tools: obj_fin.tools[tool]['solid_geometry'][:] = [] - elif panel_obj.kind == 'gerber': + elif panel_source_obj.kind == 'gerber': obj_fin.apertures = copied_apertures for ap in obj_fin.apertures: obj_fin.apertures[ap]['geometry'] = [] # find the number of polygons in the source solid_geometry geo_len = 0 - if panel_obj.kind == 'geometry': - if panel_obj.multigeo is True: - for tool in panel_obj.tools: + if panel_source_obj.kind == 'geometry': + if panel_source_obj.multigeo is True: + for tool in panel_source_obj.tools: try: - geo_len += len(panel_obj.tools[tool]['solid_geometry']) + geo_len += len(panel_source_obj.tools[tool]['solid_geometry']) except TypeError: geo_len += 1 else: try: - geo_len = len(panel_obj.solid_geometry) + geo_len = len(panel_source_obj.solid_geometry) except TypeError: geo_len = 1 - elif panel_obj.kind == 'gerber': - for ap in panel_obj.apertures: - if 'geometry' in panel_obj.apertures[ap]: + elif panel_source_obj.kind == 'gerber': + for ap in panel_source_obj.apertures: + if 'geometry' in panel_source_obj.apertures[ap]: try: - geo_len += len(panel_obj.apertures[ap]['geometry']) + geo_len += len(panel_source_obj.apertures[ap]['geometry']) except TypeError: geo_len += 1 @@ -639,29 +638,23 @@ class Panelize(FlatCAMTool): element += 1 old_disp_number = 0 - if panel_obj.kind == 'geometry': - if panel_obj.multigeo is True: - for tool in panel_obj.tools: + # Will panelize a Geometry Object + if panel_source_obj.kind == 'geometry': + if panel_source_obj.multigeo is True: + for tool in panel_source_obj.tools: if self.app.abort_flag: # graceful abort requested by the user raise grace - # 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) - # calculate the number of polygons - geo_len = len(panel_obj.tools[tool]['solid_geometry']) + geo_len = len(panel_source_obj.tools[tool]['solid_geometry']) pol_nr = 0 - for geo_el in panel_obj.tools[tool]['solid_geometry']: + for geo_el in panel_source_obj.tools[tool]['solid_geometry']: trans_geo = translate_recursion(geo_el) obj_fin.tools[tool]['solid_geometry'].append(trans_geo) pol_nr += 1 disp_number = int(np.interp(pol_nr, [0, geo_len], [0, 100])) - if old_disp_number < disp_number <= 100: self.app.proc_container.update_view_text(' %s: %d %d%%' % (_("Copy"), @@ -669,23 +662,18 @@ class Panelize(FlatCAMTool): disp_number)) old_disp_number = disp_number else: - # geo = translate_recursion(panel_obj.solid_geometry) - # if isinstance(geo, list): - # obj_fin.solid_geometry += geo - # else: - # obj_fin.solid_geometry.append(geo) if self.app.abort_flag: # graceful abort requested by the user raise grace try: # calculate the number of polygons - geo_len = len(panel_obj.solid_geometry) + geo_len = len(panel_source_obj.solid_geometry) except TypeError: geo_len = 1 pol_nr = 0 try: - for geo_el in panel_obj.solid_geometry: + for geo_el in panel_source_obj.solid_geometry: if self.app.abort_flag: # graceful abort requested by the user raise grace @@ -702,21 +690,18 @@ class Panelize(FlatCAMTool): int(element), disp_number)) old_disp_number = disp_number + except TypeError: - trans_geo = translate_recursion(panel_obj.solid_geometry) + trans_geo = translate_recursion(panel_source_obj.solid_geometry) obj_fin.solid_geometry.append(trans_geo) + # Will panelize a Gerber Object else: - # geo = translate_recursion(panel_obj.solid_geometry) - # if isinstance(geo, list): - # obj_fin.solid_geometry += geo - # else: - # obj_fin.solid_geometry.append(geo) if self.app.abort_flag: # graceful abort requested by the user raise grace try: - for geo_el in panel_obj.solid_geometry: + for geo_el in panel_source_obj.solid_geometry: if self.app.abort_flag: # graceful abort requested by the user raise grace @@ -724,21 +709,21 @@ class Panelize(FlatCAMTool): trans_geo = translate_recursion(geo_el) obj_fin.solid_geometry.append(trans_geo) except TypeError: - trans_geo = translate_recursion(panel_obj.solid_geometry) + trans_geo = translate_recursion(panel_source_obj.solid_geometry) obj_fin.solid_geometry.append(trans_geo) - for apid in panel_obj.apertures: + for apid in panel_source_obj.apertures: if self.app.abort_flag: # graceful abort requested by the user raise grace - if 'geometry' in panel_obj.apertures[apid]: + if 'geometry' in panel_source_obj.apertures[apid]: try: # calculate the number of polygons - geo_len = len(panel_obj.apertures[apid]['geometry']) + geo_len = len(panel_source_obj.apertures[apid]['geometry']) except TypeError: geo_len = 1 pol_nr = 0 - for el in panel_obj.apertures[apid]['geometry']: + for el in panel_source_obj.apertures[apid]['geometry']: if self.app.abort_flag: # graceful abort requested by the user raise grace @@ -771,20 +756,34 @@ class Panelize(FlatCAMTool): currentx += lenghtx currenty += lenghty + print("before", obj_fin.tools) + if panel_source_obj.kind == 'geometry' and panel_source_obj.multigeo is True: + # I'm going to do this only here as a fix for panelizing cutouts + # I'm going to separate linestrings out of the solid geometry from other + # possible type of elements and apply unary_union on them to fuse them + for tool in obj_fin.tools: + lines = [] + other_geo = [] + for geo in obj_fin.tools[tool]['solid_geometry']: + if isinstance(geo, LineString): + lines.append(geo) + else: + other_geo.append(geo) + fused_lines = list(unary_union(lines)) + obj_fin.tools[tool]['solid_geometry'] = fused_lines + other_geo + print("after", obj_fin.tools) + if panel_type == 'gerber': self.app.inform.emit('%s' % _("Generating panel ... Adding the Gerber code.")) obj_fin.source_file = self.app.export_gerber(obj_name=self.outname, filename=None, local_use=obj_fin, use_thread=False) - # 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.") self.app.proc_container.update_view_text('') self.app.inform.emit('%s: %d' % (_("Generating panel... Spawning copies"), (int(rows * columns)))) - if panel_obj.kind == 'excellon': + if panel_source_obj.kind == 'excellon': self.app.new_object("excellon", self.outname, job_init_excellon, plot=True, autoselected=True) else: self.app.new_object(panel_type, self.outname, job_init_geometry, plot=True, autoselected=True) @@ -801,7 +800,7 @@ class Panelize(FlatCAMTool): def job_thread(app_obj): try: - panelize_2() + panelize_worker() self.app.inform.emit('[success] %s' % _("Panel created successfully.")) except Exception as ee: proc.done() diff --git a/flatcamTools/ToolSolderPaste.py b/flatcamTools/ToolSolderPaste.py index f77c2a98..93cb4744 100644 --- a/flatcamTools/ToolSolderPaste.py +++ b/flatcamTools/ToolSolderPaste.py @@ -155,7 +155,7 @@ class SolderPaste(FlatCAMTool): step1_lbl = QtWidgets.QLabel("%s:" % _('STEP 1')) step1_lbl.setToolTip( _("First step is to select a number of nozzle tools for usage\n" - "and then optionally modify the GCode parameters bellow.") + "and then optionally modify the GCode parameters below.") ) step1_description_lbl = QtWidgets.QLabel(_("Select tools.\n" "Modify parameters.")) diff --git a/flatcamTools/ToolSub.py b/flatcamTools/ToolSub.py index ef826a0f..5409fa76 100644 --- a/flatcamTools/ToolSub.py +++ b/flatcamTools/ToolSub.py @@ -97,7 +97,7 @@ class ToolSub(FlatCAMTool): form_layout.addRow(self.sub_gerber_label, self.sub_gerber_combo) - self.intersect_btn = FCButton(_('Substract Gerber')) + self.intersect_btn = FCButton(_('Subtract Gerber')) self.intersect_btn.setToolTip( _("Will remove the area occupied by the subtractor\n" "Gerber from the Target Gerber.\n" diff --git a/locale/de/LC_MESSAGES/strings.po b/locale/de/LC_MESSAGES/strings.po index 326937b3..1e37e6cb 100644 --- a/locale/de/LC_MESSAGES/strings.po +++ b/locale/de/LC_MESSAGES/strings.po @@ -17325,7 +17325,7 @@ msgstr "SCHRITT 1" #: flatcamTools/ToolSolderPaste.py:157 msgid "" "First step is to select a number of nozzle tools for usage\n" -"and then optionally modify the GCode parameters bellow." +"and then optionally modify the GCode parameters below." msgstr "" "Zunächst müssen Sie eine Reihe von Düsenwerkzeugen auswählen\n" "und ändern Sie dann optional die GCode-Parameter." @@ -17565,7 +17565,7 @@ msgstr "" "vom Zielobjekt Gerber." #: flatcamTools/ToolSub.py:100 -msgid "Substract Gerber" +msgid "Subtract Gerber" msgstr "Gerber abziehen" #: flatcamTools/ToolSub.py:102 @@ -20547,7 +20547,7 @@ msgstr "" #~ msgid "[success] Paint Area Done." #~ msgstr "[success] Lackierbereich fertig." -#~ msgid "...proccessing... [%s]" +#~ msgid "...processing... [%s]" #~ msgstr "...wird bearbeitet...[%s]" #~ msgid "Parsing aperture %s geometry ..." diff --git a/locale/en/LC_MESSAGES/strings.po b/locale/en/LC_MESSAGES/strings.po index 161975b5..83a3b193 100644 --- a/locale/en/LC_MESSAGES/strings.po +++ b/locale/en/LC_MESSAGES/strings.po @@ -16981,10 +16981,10 @@ msgstr "STEP 1" #: flatcamTools/ToolSolderPaste.py:157 msgid "" "First step is to select a number of nozzle tools for usage\n" -"and then optionally modify the GCode parameters bellow." +"and then optionally modify the GCode parameters below." msgstr "" "First step is to select a number of nozzle tools for usage\n" -"and then optionally modify the GCode parameters bellow." +"and then optionally modify the GCode parameters below." #: flatcamTools/ToolSolderPaste.py:160 msgid "" @@ -17216,8 +17216,8 @@ msgstr "" "from the target Gerber object." #: flatcamTools/ToolSub.py:100 -msgid "Substract Gerber" -msgstr "Substract Gerber" +msgid "Subtract Gerber" +msgstr "Subtract Gerber" #: flatcamTools/ToolSub.py:102 msgid "" @@ -20512,8 +20512,8 @@ msgstr "No Geometry name in args. Provide a name and try again." #~ msgid "Generating panel ... Please wait." #~ msgstr "Generating panel ... Please wait." -#~ msgid "...proccessing... [%s]" -#~ msgstr "...proccessing... [%s]" +#~ msgid "...processing... [%s]" +#~ msgstr "...processing... [%s]" #~ msgid "Parsing aperture %s geometry ..." #~ msgstr "Parsing aperture %s geometry ..." diff --git a/locale/es/LC_MESSAGES/strings.po b/locale/es/LC_MESSAGES/strings.po index 1f495e05..21152ba5 100644 --- a/locale/es/LC_MESSAGES/strings.po +++ b/locale/es/LC_MESSAGES/strings.po @@ -17257,7 +17257,7 @@ msgstr "PASO 1" #: flatcamTools/ToolSolderPaste.py:157 msgid "" "First step is to select a number of nozzle tools for usage\n" -"and then optionally modify the GCode parameters bellow." +"and then optionally modify the GCode parameters below." msgstr "" "El primer paso es seleccionar una serie de herramientas de boquillas para su " "uso\n" @@ -17502,7 +17502,7 @@ msgstr "" "del objeto objetivo de Gerber." #: flatcamTools/ToolSub.py:100 -msgid "Substract Gerber" +msgid "Subtract Gerber" msgstr "Restar Gerber" #: flatcamTools/ToolSub.py:102 @@ -19224,7 +19224,7 @@ msgstr "" #~ msgid "[success] Paint Area Done." #~ msgstr "[éxito] Área de pintura realizada." -#~ msgid "...proccessing... [%s]" +#~ msgid "...processing... [%s]" #~ msgstr "... procesando ... [% s]" #~ msgid "Parsing aperture %s geometry ..." diff --git a/locale/fr/LC_MESSAGES/strings.po b/locale/fr/LC_MESSAGES/strings.po index 2b9beb3c..82d6a131 100644 --- a/locale/fr/LC_MESSAGES/strings.po +++ b/locale/fr/LC_MESSAGES/strings.po @@ -17254,7 +17254,7 @@ msgstr "ÉTAPE 1" #: flatcamTools/ToolSolderPaste.py:157 msgid "" "First step is to select a number of nozzle tools for usage\n" -"and then optionally modify the GCode parameters bellow." +"and then optionally modify the GCode parameters below." msgstr "" "La première étape consiste à sélectionner un certain nombre d’outils de buse " "à utiliser.\n" @@ -17498,7 +17498,7 @@ msgstr "" "à partir de l'objet Gerber cible." #: flatcamTools/ToolSub.py:100 -msgid "Substract Gerber" +msgid "Subtract Gerber" msgstr "Soustraire Gerber" #: flatcamTools/ToolSub.py:102 diff --git a/locale/hu/LC_MESSAGES/strings.po b/locale/hu/LC_MESSAGES/strings.po index bd24dcc7..950d8d23 100644 --- a/locale/hu/LC_MESSAGES/strings.po +++ b/locale/hu/LC_MESSAGES/strings.po @@ -7235,11 +7235,11 @@ msgstr "Except" #: flatcamGUI/ObjectUI.py:436 msgid "" "When the isolation geometry is generated,\n" -"by checking this, the area of the object bellow\n" +"by checking this, the area of the object below\n" "will be subtracted from the isolation geometry." msgstr "" "When the isolation geometry is generated,\n" -"by checking this, the area of the object bellow\n" +"by checking this, the area of the object below\n" "will be subtracted from the isolation geometry." #: flatcamGUI/ObjectUI.py:449 flatcamGUI/PreferencesUI.py:6527 @@ -16986,10 +16986,10 @@ msgstr "STEP 1" #: flatcamTools/ToolSolderPaste.py:157 msgid "" "First step is to select a number of nozzle tools for usage\n" -"and then optionally modify the GCode parameters bellow." +"and then optionally modify the GCode parameters below." msgstr "" "First step is to select a number of nozzle tools for usage\n" -"and then optionally modify the GCode parameters bellow." +"and then optionally modify the GCode parameters below." #: flatcamTools/ToolSolderPaste.py:160 msgid "" @@ -17221,8 +17221,8 @@ msgstr "" "from the target Gerber object." #: flatcamTools/ToolSub.py:100 -msgid "Substract Gerber" -msgstr "Substract Gerber" +msgid "Subtract Gerber" +msgstr "Subtract Gerber" #: flatcamTools/ToolSub.py:102 msgid "" @@ -20477,8 +20477,8 @@ msgstr "No Geometry name in args. Provide a name and try again." #~ msgid "Generating panel ... Please wait." #~ msgstr "Generating panel ... Please wait." -#~ msgid "...proccessing... [%s]" -#~ msgstr "...proccessing... [%s]" +#~ msgid "...processing... [%s]" +#~ msgstr "...processing... [%s]" #~ msgid "Parsing aperture %s geometry ..." #~ msgstr "Parsing aperture %s geometry ..." diff --git a/locale/it/LC_MESSAGES/strings.po b/locale/it/LC_MESSAGES/strings.po index bac53820..15b42fc6 100644 --- a/locale/it/LC_MESSAGES/strings.po +++ b/locale/it/LC_MESSAGES/strings.po @@ -6804,7 +6804,7 @@ msgstr "" #: flatcamGUI/ObjectUI.py:431 msgid "" "When the isolation geometry is generated,\n" -"by checking this, the area of the object bellow\n" +"by checking this, the area of the object below\n" "will be subtracted from the isolation geometry." msgstr "" @@ -14198,7 +14198,7 @@ msgid "Violations: There are no violations for the current rule." msgstr "" #: flatcamTools/ToolShell.py:70 flatcamTools/ToolShell.py:72 -msgid "...proccessing..." +msgid "...processing..." msgstr "" #: flatcamTools/ToolSolderPaste.py:37 @@ -14251,7 +14251,7 @@ msgstr "" #: flatcamTools/ToolSolderPaste.py:156 msgid "" "First step is to select a number of nozzle tools for usage\n" -"and then optionally modify the GCode parameters bellow." +"and then optionally modify the GCode parameters below." msgstr "" #: flatcamTools/ToolSolderPaste.py:159 @@ -14452,7 +14452,7 @@ msgid "" msgstr "" #: flatcamTools/ToolSub.py:97 -msgid "Substract Gerber" +msgid "Subtract Gerber" msgstr "" #: flatcamTools/ToolSub.py:99 diff --git a/locale/pt_BR/LC_MESSAGES/strings.po b/locale/pt_BR/LC_MESSAGES/strings.po index b90a1858..386e81b4 100644 --- a/locale/pt_BR/LC_MESSAGES/strings.po +++ b/locale/pt_BR/LC_MESSAGES/strings.po @@ -17045,7 +17045,7 @@ msgstr "PASSO 1" #: flatcamTools/ToolSolderPaste.py:157 msgid "" "First step is to select a number of nozzle tools for usage\n" -"and then optionally modify the GCode parameters bellow." +"and then optionally modify the GCode parameters below." msgstr "" "O primeiro passo é selecionar um número de ferramentas de bico para usar,\n" "e opcionalmente, modificar os parâmetros do G-Code abaixo." @@ -17286,7 +17286,7 @@ msgstr "" "do objeto Gerber de destino." #: flatcamTools/ToolSub.py:100 -msgid "Substract Gerber" +msgid "Subtract Gerber" msgstr "Subtrair Gerber" #: flatcamTools/ToolSub.py:102 @@ -20225,7 +20225,7 @@ msgstr "Nenhum nome de geometria nos argumentos. Altere e tente novamente." #~ msgid "Generating panel ... Please wait." #~ msgstr "Gerando painel ... Por favor, aguarde." -#~ msgid "...proccessing... [%s]" +#~ msgid "...processing... [%s]" #~ msgstr "...processando... [%s]" #~ msgid "Parsing aperture %s geometry ..." diff --git a/locale/ro/LC_MESSAGES/strings.po b/locale/ro/LC_MESSAGES/strings.po index a2abeb59..f740e587 100644 --- a/locale/ro/LC_MESSAGES/strings.po +++ b/locale/ro/LC_MESSAGES/strings.po @@ -17265,7 +17265,7 @@ msgstr "PAS 1" #: flatcamTools/ToolSolderPaste.py:157 msgid "" "First step is to select a number of nozzle tools for usage\n" -"and then optionally modify the GCode parameters bellow." +"and then optionally modify the GCode parameters below." msgstr "" "Primul pas este să se efectueza o selecţie de unelte Nozzl pt \n" "utilizare și apoi in mod optional, să se modifice parametrii\n" @@ -17512,7 +17512,7 @@ msgstr "" "obiectul Gerber tintă." #: flatcamTools/ToolSub.py:100 -msgid "Substract Gerber" +msgid "Subtract Gerber" msgstr "Execută" #: flatcamTools/ToolSub.py:102 @@ -20553,7 +20553,7 @@ msgstr "" #~ msgid "Generating panel ... Please wait." #~ msgstr "Se generează panelul ... Va rugăm asteptati." -#~ msgid "...proccessing... [%s]" +#~ msgid "...processing... [%s]" #~ msgstr "...in procesare... [%s]" #~ msgid "Parsing aperture %s geometry ..." diff --git a/locale/ru/LC_MESSAGES/strings.po b/locale/ru/LC_MESSAGES/strings.po index 4056ae5f..97a00a7c 100644 --- a/locale/ru/LC_MESSAGES/strings.po +++ b/locale/ru/LC_MESSAGES/strings.po @@ -17107,7 +17107,7 @@ msgstr "ШАГ 1" #: flatcamTools/ToolSolderPaste.py:157 msgid "" "First step is to select a number of nozzle tools for usage\n" -"and then optionally modify the GCode parameters bellow." +"and then optionally modify the GCode parameters below." msgstr "" "Первый шаг - выбрать несколько инструментов для использования насадок.\n" "а затем при необходимости измените параметры кода G ниже." @@ -17349,7 +17349,7 @@ msgstr "" "из целевого Gerber объекта." #: flatcamTools/ToolSub.py:100 -msgid "Substract Gerber" +msgid "Subtract Gerber" msgstr "Вычесть Gerber" #: flatcamTools/ToolSub.py:102 @@ -20369,7 +20369,7 @@ msgstr "Нет имени геометрии в аргументах. Укажи #~ msgid "Generating panel ... Please wait." #~ msgstr "Выполняется панелизация ... Пожалуйста, подождите." -#~ msgid "...proccessing... [%s]" +#~ msgid "...processing... [%s]" #~ msgstr "...обработка... [%s]" #~ msgid "Parsing aperture %s geometry ..." diff --git a/locale_template/strings.pot b/locale_template/strings.pot index f195910d..4e2b0c0e 100644 --- a/locale_template/strings.pot +++ b/locale_template/strings.pot @@ -6789,7 +6789,7 @@ msgstr "" #: flatcamGUI/ObjectUI.py:436 msgid "" "When the isolation geometry is generated,\n" -"by checking this, the area of the object bellow\n" +"by checking this, the area of the object below\n" "will be subtracted from the isolation geometry." msgstr "" @@ -14604,7 +14604,7 @@ msgstr "" #: flatcamTools/ToolSolderPaste.py:158 msgid "" "First step is to select a number of nozzle tools for usage\n" -"and then optionally modify the GCode parameters bellow." +"and then optionally modify the GCode parameters below." msgstr "" #: flatcamTools/ToolSolderPaste.py:161 @@ -14800,7 +14800,7 @@ msgid "" msgstr "" #: flatcamTools/ToolSub.py:100 -msgid "Substract Gerber" +msgid "Subtract Gerber" msgstr "" #: flatcamTools/ToolSub.py:102 diff --git a/tclCommands/TclCommandJoinExcellon.py b/tclCommands/TclCommandJoinExcellon.py index e2a209d1..5c1962ff 100644 --- a/tclCommands/TclCommandJoinExcellon.py +++ b/tclCommands/TclCommandJoinExcellon.py @@ -34,7 +34,7 @@ class TclCommandJoinExcellon(TclCommand): help = { 'main': "Runs a merge operation (join) on the Excellon objects.\n" "The names of the Excellon objects to be merged will be entered after the outname,\n" - "separated by spaces. See the example bellow.\n" + "separated by spaces. See the example below.\n" "WARNING: if the name of an Excellon objects has spaces, enclose the name with quotes.", 'args': collections.OrderedDict([ ('outname', 'Name of the new Excellon Object made by joining of other Excellon objects. Required'), diff --git a/tclCommands/TclCommandJoinGeometry.py b/tclCommands/TclCommandJoinGeometry.py index 52fa83fa..67e3aeb5 100644 --- a/tclCommands/TclCommandJoinGeometry.py +++ b/tclCommands/TclCommandJoinGeometry.py @@ -34,7 +34,7 @@ class TclCommandJoinGeometry(TclCommand): help = { 'main': "Runs a merge operation (join) on the Geometry objects.\n" "The names of the Geometry objects to be merged will be entered after the outname,\n" - "separated by spaces. See the example bellow.\n" + "separated by spaces. See the example below.\n" "WARNING: if the name of an Geometry objects has spaces, enclose the name with quotes.", 'args': collections.OrderedDict([ ('outname', 'Name of the new Geometry Object made by joining of other Geometry objects. Required'),