From 0d57852ec5c51711fa00760ac84e25028c191b30 Mon Sep 17 00:00:00 2001 From: Marius Stanciu Date: Sat, 30 May 2020 11:25:18 +0300 Subject: [PATCH] - Isolation Tool: removed the tools that have empty geometry in case of rest machining - Isolation Tool: solved some naming issues --- AppTools/ToolIsolation.py | 323 +++++++++++++++++++------------------- CHANGELOG.md | 2 + 2 files changed, 166 insertions(+), 159 deletions(-) diff --git a/AppTools/ToolIsolation.py b/AppTools/ToolIsolation.py index 570c7cf0..697ef638 100644 --- a/AppTools/ToolIsolation.py +++ b/AppTools/ToolIsolation.py @@ -724,132 +724,6 @@ class ToolIsolation(AppTool, Gerber): "gerber": "Gerber", "geometry": "Geometry" }[self.type_excobj_radio.get_value()] - def on_row_selection_change(self): - self.blockSignals(True) - - sel_rows = [it.row() for it in self.tools_table.selectedItems()] - # sel_rows = sorted(set(index.row() for index in self.tools_table.selectedIndexes())) - - if not sel_rows: - sel_rows = [0] - - for current_row in sel_rows: - # populate the form with the data from the tool associated with the row parameter - try: - item = self.tools_table.item(current_row, 3) - if item is not None: - tooluid = int(item.text()) - else: - return - except Exception as e: - log.debug("Tool missing. Add a tool in the Tool Table. %s" % str(e)) - return - - # update the QLabel that shows for which Tool we have the parameters in the UI form - if len(sel_rows) == 1: - cr = current_row + 1 - self.tool_data_label.setText( - "%s: %s %d" % (_('Parameters for'), _("Tool"), cr) - ) - try: - # set the form with data from the newly selected tool - for tooluid_key, tooluid_value in list(self.iso_tools.items()): - if int(tooluid_key) == tooluid: - for key, value in tooluid_value.items(): - if key == 'data': - form_value_storage = tooluid_value[key] - self.storage_to_form(form_value_storage) - except Exception as e: - log.debug("ToolIsolation ---> update_ui() " + str(e)) - else: - self.tool_data_label.setText( - "%s: %s" % (_('Parameters for'), _("Multiple Tools")) - ) - - self.blockSignals(False) - - def storage_to_form(self, dict_storage): - for form_key in self.form_fields: - for storage_key in dict_storage: - if form_key == storage_key: - try: - self.form_fields[form_key].set_value(dict_storage[form_key]) - except Exception as e: - log.debug("ToolIsolation.storage_to_form() --> %s" % str(e)) - pass - - def form_to_storage(self): - if self.tools_table.rowCount() == 0: - # there is no tool in tool table so we can't save the GUI elements values to storage - return - - self.blockSignals(True) - - widget_changed = self.sender() - wdg_objname = widget_changed.objectName() - option_changed = self.name2option[wdg_objname] - - # row = self.tools_table.currentRow() - rows = sorted(set(index.row() for index in self.tools_table.selectedIndexes())) - for row in rows: - if row < 0: - row = 0 - tooluid_item = int(self.tools_table.item(row, 3).text()) - - for tooluid_key, tooluid_val in self.iso_tools.items(): - if int(tooluid_key) == tooluid_item: - new_option_value = self.form_fields[option_changed].get_value() - if option_changed in tooluid_val: - tooluid_val[option_changed] = new_option_value - if option_changed in tooluid_val['data']: - tooluid_val['data'][option_changed] = new_option_value - - self.blockSignals(False) - - def on_apply_param_to_all_clicked(self): - if self.tools_table.rowCount() == 0: - # there is no tool in tool table so we can't save the GUI elements values to storage - log.debug("ToolIsolation.on_apply_param_to_all_clicked() --> no tool in Tools Table, aborting.") - return - - self.blockSignals(True) - - row = self.tools_table.currentRow() - if row < 0: - row = 0 - - tooluid_item = int(self.tools_table.item(row, 3).text()) - temp_tool_data = {} - - for tooluid_key, tooluid_val in self.iso_tools.items(): - if int(tooluid_key) == tooluid_item: - # this will hold the 'data' key of the self.tools[tool] dictionary that corresponds to - # the current row in the tool table - temp_tool_data = tooluid_val['data'] - break - - for tooluid_key, tooluid_val in self.iso_tools.items(): - tooluid_val['data'] = deepcopy(temp_tool_data) - - self.app.inform.emit('[success] %s' % _("Current Tool parameters were applied to all tools.")) - self.blockSignals(False) - - def on_add_tool_by_key(self): - tool_add_popup = FCInputDialog(title='%s...' % _("New Tool"), - text='%s:' % _('Enter a Tool Diameter'), - min=0.0001, max=9999.9999, decimals=self.decimals) - tool_add_popup.setWindowIcon(QtGui.QIcon(self.app.resource_location + '/letter_t_32.png')) - - val, ok = tool_add_popup.get_value() - if ok: - if float(val) == 0: - self.app.inform.emit('[WARNING_NOTCL] %s' % - _("Please enter a tool diameter with non-zero value, in Float format.")) - return - self.on_tool_add(dia=float(val)) - else: - self.app.inform.emit('[WARNING_NOTCL] %s...' % _("Adding Tool cancelled")) - def install(self, icon=None, separator=None, **kwargs): AppTool.install(self, icon, separator, shortcut='Alt+I', **kwargs) @@ -892,8 +766,10 @@ class ToolIsolation(AppTool, Gerber): # try to select in the Gerber combobox the active object try: - current_name = self.app.collection.get_active().options['name'] - self.object_combo.set_value(current_name) + selected_obj = self.app.collection.get_active() + if selected_obj.kind == 'gerber': + current_name = selected_obj.options['name'] + self.object_combo.set_value(current_name) except Exception: pass @@ -1259,6 +1135,132 @@ class ToolIsolation(AppTool, Gerber): except (TypeError, AttributeError): pass + def on_row_selection_change(self): + self.blockSignals(True) + + sel_rows = [it.row() for it in self.tools_table.selectedItems()] + # sel_rows = sorted(set(index.row() for index in self.tools_table.selectedIndexes())) + + if not sel_rows: + sel_rows = [0] + + for current_row in sel_rows: + # populate the form with the data from the tool associated with the row parameter + try: + item = self.tools_table.item(current_row, 3) + if item is not None: + tooluid = int(item.text()) + else: + return + except Exception as e: + log.debug("Tool missing. Add a tool in the Tool Table. %s" % str(e)) + return + + # update the QLabel that shows for which Tool we have the parameters in the UI form + if len(sel_rows) == 1: + cr = current_row + 1 + self.tool_data_label.setText( + "%s: %s %d" % (_('Parameters for'), _("Tool"), cr) + ) + try: + # set the form with data from the newly selected tool + for tooluid_key, tooluid_value in list(self.iso_tools.items()): + if int(tooluid_key) == tooluid: + for key, value in tooluid_value.items(): + if key == 'data': + form_value_storage = tooluid_value[key] + self.storage_to_form(form_value_storage) + except Exception as e: + log.debug("ToolIsolation ---> update_ui() " + str(e)) + else: + self.tool_data_label.setText( + "%s: %s" % (_('Parameters for'), _("Multiple Tools")) + ) + + self.blockSignals(False) + + def storage_to_form(self, dict_storage): + for form_key in self.form_fields: + for storage_key in dict_storage: + if form_key == storage_key: + try: + self.form_fields[form_key].set_value(dict_storage[form_key]) + except Exception as e: + log.debug("ToolIsolation.storage_to_form() --> %s" % str(e)) + pass + + def form_to_storage(self): + if self.tools_table.rowCount() == 0: + # there is no tool in tool table so we can't save the GUI elements values to storage + return + + self.blockSignals(True) + + widget_changed = self.sender() + wdg_objname = widget_changed.objectName() + option_changed = self.name2option[wdg_objname] + + # row = self.tools_table.currentRow() + rows = sorted(set(index.row() for index in self.tools_table.selectedIndexes())) + for row in rows: + if row < 0: + row = 0 + tooluid_item = int(self.tools_table.item(row, 3).text()) + + for tooluid_key, tooluid_val in self.iso_tools.items(): + if int(tooluid_key) == tooluid_item: + new_option_value = self.form_fields[option_changed].get_value() + if option_changed in tooluid_val: + tooluid_val[option_changed] = new_option_value + if option_changed in tooluid_val['data']: + tooluid_val['data'][option_changed] = new_option_value + + self.blockSignals(False) + + def on_apply_param_to_all_clicked(self): + if self.tools_table.rowCount() == 0: + # there is no tool in tool table so we can't save the GUI elements values to storage + log.debug("ToolIsolation.on_apply_param_to_all_clicked() --> no tool in Tools Table, aborting.") + return + + self.blockSignals(True) + + row = self.tools_table.currentRow() + if row < 0: + row = 0 + + tooluid_item = int(self.tools_table.item(row, 3).text()) + temp_tool_data = {} + + for tooluid_key, tooluid_val in self.iso_tools.items(): + if int(tooluid_key) == tooluid_item: + # this will hold the 'data' key of the self.tools[tool] dictionary that corresponds to + # the current row in the tool table + temp_tool_data = tooluid_val['data'] + break + + for tooluid_key, tooluid_val in self.iso_tools.items(): + tooluid_val['data'] = deepcopy(temp_tool_data) + + self.app.inform.emit('[success] %s' % _("Current Tool parameters were applied to all tools.")) + self.blockSignals(False) + + def on_add_tool_by_key(self): + tool_add_popup = FCInputDialog(title='%s...' % _("New Tool"), + text='%s:' % _('Enter a Tool Diameter'), + min=0.0001, max=9999.9999, decimals=self.decimals) + tool_add_popup.setWindowIcon(QtGui.QIcon(self.app.resource_location + '/letter_t_32.png')) + + val, ok = tool_add_popup.get_value() + if ok: + if float(val) == 0: + self.app.inform.emit('[WARNING_NOTCL] %s' % + _("Please enter a tool diameter with non-zero value, in Float format.")) + return + self.on_tool_add(dia=float(val)) + else: + self.app.inform.emit('[WARNING_NOTCL] %s...' % _("Adding Tool cancelled")) + def on_tooldia_updated(self): if self.tool_type_radio.get_value() == 'C1': self.old_tool_dia = self.addtool_entry.get_value() @@ -1606,11 +1608,11 @@ class ToolIsolation(AppTool, Gerber): self.app.inform.emit('[ERROR_NOTCL] %s: %s' % (_("Object not found"), str(self.obj_name))) return - def worker_task(iso_obj, app_obj): + def worker_task(iso_obj): with self.app.proc_container.new(_("Isolating...")): self.isolate_handler(iso_obj) - self.app.worker_task.emit({'fcn': worker_task, 'params': [self.grb_obj, self.app]}) + self.app.worker_task.emit({'fcn': worker_task, 'params': [self.grb_obj]}) def follow_geo(self, followed_obj, outname): """ @@ -1623,7 +1625,7 @@ class ToolIsolation(AppTool, Gerber): :return: None """ - def follow_init(follow_obj, app): + def follow_init(follow_obj, app_obj): # Propagate options follow_obj.options["cnctooldia"] = str(tooldia) follow_obj.solid_geometry = self.grb_obj.follow_geometry @@ -1879,7 +1881,7 @@ class ToolIsolation(AppTool, Gerber): total_solid_geometry = [] - iso_name = iso_obj.options["name"] + iso_name = iso_obj.options["name"] + '_iso_rest' work_geo = iso_obj.solid_geometry if iso2geo is None else iso2geo sorted_tools = [] @@ -1920,11 +1922,11 @@ class ToolIsolation(AppTool, Gerber): outname = "%s_%.*f" % (iso_obj.options["name"], self.decimals, float(tool_dia)) - iso_name = outname + "_iso" + internal_name = outname + "_iso" if iso_t == 0: - iso_name = outname + "_ext_iso" + internal_name = outname + "_ext_iso" elif iso_t == 1: - iso_name = outname + "_int_iso" + internal_name = outname + "_int_iso" # transfer the Cut Z and Vtip and VAngle values in case that we use the V-Shape tool in Gerber UI if tool_type.lower() == 'v': @@ -1933,14 +1935,14 @@ class ToolIsolation(AppTool, Gerber): new_vtipangle = self.ui.tipangle_spinner.get_value() tool_type = 'V' tool_data.update({ - "name": iso_name, + "name": internal_name, "cutz": new_cutz, "vtipdia": new_vtipdia, "vtipangle": new_vtipangle, }) else: tool_data.update({ - "name": iso_name, + "name": internal_name, }) tool_type = 'C1' @@ -1984,15 +1986,18 @@ class ToolIsolation(AppTool, Gerber): geo_obj.solid_geometry = total_solid_geometry # even if combine is checked, one pass is still single-geo + # remove the tools that have no geometry + for geo_tool in list(geo_obj.tools.keys()): + if not geo_obj.tools[geo_tool]['solid_geometry']: + geo_obj.tools.pop(geo_tool, None) + if len(tools_storage) > 1: geo_obj.multigeo = True else: - try: - passes_no = float(tools_storage[0]['data']['tools_iso_passes']) + for ky in tools_storage.keys(): + passes_no = float(tools_storage[ky]['data']['tools_iso_passes']) geo_obj.multigeo = True if passes_no > 1 else False - except KeyError as e: - log.debug("ToolIsolation.combined_rest.iso_init() --> KeyError: %s" % str(e)) - geo_obj.multogeo = False + break # detect if solid_geometry is empty and this require list flattening which is "heavy" # or just looking in the lists (they are one level depth) and if any is not empty @@ -2051,7 +2056,7 @@ class ToolIsolation(AppTool, Gerber): total_solid_geometry = [] - iso_name = iso_obj.options["name"] + iso_name = iso_obj.options["name"] + '_iso_combined' geometry = iso2geo for tool in tools_storage: @@ -2083,11 +2088,11 @@ class ToolIsolation(AppTool, Gerber): outname = "%s_%.*f" % (iso_obj.options["name"], self.decimals, float(tool_dia)) - iso_name = outname + "_iso" + internal_name = outname + "_iso" if iso_t == 0: - iso_name = outname + "_ext_iso" + internal_name = outname + "_ext_iso" elif iso_t == 1: - iso_name = outname + "_int_iso" + internal_name = outname + "_int_iso" # transfer the Cut Z and Vtip and VAngle values in case that we use the V-Shape tool in Gerber UI if tool_type.lower() == 'v': @@ -2096,14 +2101,14 @@ class ToolIsolation(AppTool, Gerber): new_vtipangle = self.ui.tipangle_spinner.get_value() tool_type = 'V' tool_data.update({ - "name": iso_name, + "name": internal_name, "cutz": new_cutz, "vtipdia": new_vtipdia, "vtipangle": new_vtipangle, }) else: tool_data.update({ - "name": iso_name, + "name": internal_name, }) tool_type = 'C1' @@ -2189,19 +2194,19 @@ class ToolIsolation(AppTool, Gerber): self.app.app_obj.new_object("geometry", iso_name, iso_init, plot=plot) - def area_subtraction(self, geo, subtractor_geo): + def area_subtraction(self, geo, subtraction_geo): """ - Subtracts the subtractor_geo (if present else self.solid_geometry) from the geo + Subtracts the subtraction_geo (if present else self.solid_geometry) from the geo - :param geo: target geometry from which to subtract - :param subtractor_geo: geometry that acts as subtractor + :param geo: target geometry from which to subtract + :param subtraction_geo: geometry that acts as subtraction geo :return: """ new_geometry = [] target_geo = geo - if subtractor_geo: - sub_union = cascaded_union(subtractor_geo) + if subtraction_geo: + sub_union = cascaded_union(subtraction_geo) else: name = self.exc_obj_combo.currentText() subtractor_obj = self.app.collection.get_by_name(name) @@ -2220,7 +2225,7 @@ class ToolIsolation(AppTool, Gerber): new_geo = ring.difference(sub_union) if new_geo and not new_geo.is_empty: new_geometry.append(new_geo) - elif isinstance(geo_elem, LineString): + elif isinstance(geo_elem, LineString) or isinstance(geo_elem, LinearRing): new_geo = geo_elem.difference(sub_union) if new_geo: if not new_geo.is_empty: @@ -2237,7 +2242,7 @@ class ToolIsolation(AppTool, Gerber): if new_geo: if not new_geo.is_empty: new_geometry.append(new_geo) - elif isinstance(target_geo, LineString): + elif isinstance(target_geo, LineString) or isinstance(target_geo, LinearRing): new_geo = target_geo.difference(sub_union) if new_geo and not new_geo.is_empty: new_geometry.append(new_geo) @@ -2274,7 +2279,7 @@ class ToolIsolation(AppTool, Gerber): new_geo = ring.intersection(intersect_union) if new_geo and not new_geo.is_empty: new_geometry.append(new_geo) - elif isinstance(geo_elem, LineString): + elif isinstance(geo_elem, LineString) or isinstance(geo_elem, LinearRing): new_geo = geo_elem.intersection(intersect_union) if new_geo: if not new_geo.is_empty: @@ -2291,7 +2296,7 @@ class ToolIsolation(AppTool, Gerber): if new_geo: if not new_geo.is_empty: new_geometry.append(new_geo) - elif isinstance(target_geo, LineString): + elif isinstance(target_geo, LineString) or isinstance(target_geo, LinearRing): new_geo = target_geo.intersection(intersect_union) if new_geo and not new_geo.is_empty: new_geometry.append(new_geo) @@ -2798,7 +2803,7 @@ class ToolIsolation(AppTool, Gerber): intersect_flag = True break - if intersect_flag == False: + if intersect_flag is False: for geo_search_idx in range(start_idx, len(geometry)): if check_geo.intersects(geometry[geo_search_idx]): intersect_flag = True diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d61aaf1..1fef0330 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,8 @@ CHANGELOG for FlatCAM beta - made confirmation messages for the values that are modified not to be printed in the Shell - Isolation Tool: working on the Rest machining: almost there, perhaps I will use multiprocessing +- Isolation Tool: removed the tools that have empty geometry in case of rest machining +- Isolation Tool: solved some naming issues 29.05.2020