- refactored the Isolation Plugin class
This commit is contained in:
@@ -7,6 +7,10 @@ CHANGELOG for FlatCAM beta
|
|||||||
|
|
||||||
=================================================
|
=================================================
|
||||||
|
|
||||||
|
30.01.2022
|
||||||
|
|
||||||
|
- refactored the Isolation Plugin class
|
||||||
|
|
||||||
29.01.2022
|
29.01.2022
|
||||||
|
|
||||||
- upgraded/fixed the Panelize Tcl command
|
- upgraded/fixed the Panelize Tcl command
|
||||||
|
|||||||
@@ -1657,10 +1657,20 @@ class ToolIsolation(AppTool, Gerber):
|
|||||||
:type isolated_obj: AppObjects.FlatCAMGerber.GerberObject
|
:type isolated_obj: AppObjects.FlatCAMGerber.GerberObject
|
||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
selection = self.ui.select_combo.get_value()
|
|
||||||
|
|
||||||
|
sel_tools = []
|
||||||
|
table_items = self.ui.tools_table.selectedItems()
|
||||||
|
sel_rows = {t.row() for t in table_items}
|
||||||
|
for row in sel_rows:
|
||||||
|
tid = int(self.ui.tools_table.item(row, 3).text())
|
||||||
|
sel_tools.append(tid)
|
||||||
|
if not sel_tools:
|
||||||
|
self.app.inform.emit('[ERROR_NOTCL] %s' % _("There are no tools selected in the Tool Table."))
|
||||||
|
return 'fail'
|
||||||
|
|
||||||
|
selection = self.ui.select_combo.get_value()
|
||||||
if selection == 0: # ALL
|
if selection == 0: # ALL
|
||||||
self.isolate(isolated_obj=isolated_obj)
|
self.isolate(isolated_obj=isolated_obj, sel_tools=sel_tools, tools_storage=self.iso_tools)
|
||||||
elif selection == 1: # Area Selection
|
elif selection == 1: # Area Selection
|
||||||
self.app.inform.emit('[WARNING_NOTCL] %s' % _("Click the start point of the area."))
|
self.app.inform.emit('[WARNING_NOTCL] %s' % _("Click the start point of the area."))
|
||||||
|
|
||||||
@@ -1705,14 +1715,19 @@ class ToolIsolation(AppTool, Gerber):
|
|||||||
ref_obj = self.app.collection.get_by_name(self.ui.reference_combo.get_value())
|
ref_obj = self.app.collection.get_by_name(self.ui.reference_combo.get_value())
|
||||||
ref_geo = unary_union(ref_obj.solid_geometry)
|
ref_geo = unary_union(ref_obj.solid_geometry)
|
||||||
use_geo = unary_union(isolated_obj.solid_geometry).difference(ref_geo)
|
use_geo = unary_union(isolated_obj.solid_geometry).difference(ref_geo)
|
||||||
self.isolate(isolated_obj=isolated_obj, geometry=use_geo)
|
self.isolate(isolated_obj=isolated_obj, geometry=use_geo, sel_tools=sel_tools, tools_storage=self.iso_tools)
|
||||||
|
|
||||||
def isolate(self, isolated_obj, geometry=None, limited_area=None, negative_dia=None, plot=True):
|
def isolate(self, isolated_obj, sel_tools, tools_storage, geometry=None, limited_area=None, negative_dia=None,
|
||||||
|
plot=True, **args):
|
||||||
"""
|
"""
|
||||||
Creates an isolation routing geometry object in the project.
|
Creates an isolation routing geometry object in the project.
|
||||||
|
|
||||||
:param isolated_obj: Gerber object for which to generate the isolating routing geometry
|
:param isolated_obj: Gerber object for which to generate the isolating routing geometry
|
||||||
:type isolated_obj: AppObjects.FlatCAMGerber.GerberObject
|
:type isolated_obj: AppObjects.FlatCAMGerber.GerberObject
|
||||||
|
:param sel_tools: A list of tools to be used for isolation
|
||||||
|
:type sel_tools: list
|
||||||
|
:param tools_storage: A dictionary that holds the isolation object tools
|
||||||
|
:type tools_storage: dict
|
||||||
:param geometry: specific geometry to isolate
|
:param geometry: specific geometry to isolate
|
||||||
:type geometry: List of Shapely polygon
|
:type geometry: List of Shapely polygon
|
||||||
:param limited_area: if not None isolate only this area
|
:param limited_area: if not None isolate only this area
|
||||||
@@ -1724,43 +1739,40 @@ class ToolIsolation(AppTool, Gerber):
|
|||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
|
|
||||||
combine = self.ui.combine_passes_cb.get_value()
|
use_combine = args['combine'] if 'combine' in args else self.ui.combine_passes_cb.get_value()
|
||||||
tools_storage = self.iso_tools
|
use_iso_except = args['iso_except'] if 'iso_except' in args else self.ui.except_cb.get_value()
|
||||||
|
use_extra_passes = args['e_passes'] if 'e_passes' in args else self.ui.pad_passes_entry.get_value()
|
||||||
sorted_tools = []
|
use_area_exception = args['area_except'] if 'area_except' in args else self.ui.except_cb.get_value()
|
||||||
table_items = self.ui.tools_table.selectedItems()
|
sel_area_shape = args['area_shape'] if 'area_shape' in args else self.ui.area_shape_radio.get_value()
|
||||||
sel_rows = {t.row() for t in table_items}
|
use_rest = args['rest'] if 'rest' in args else self.ui.rest_cb.get_value()
|
||||||
for row in sel_rows:
|
selection_type = args['sel_type'] if 'sel_type' in args else self.ui.select_combo.get_value()
|
||||||
tid = int(self.ui.tools_table.item(row, 3).text())
|
tool_tip_shape = args['tip_shape'] if 'tip_shape' in args else self.ui.tool_shape_combo.get_value()
|
||||||
sorted_tools.append(tid)
|
|
||||||
if not sorted_tools:
|
|
||||||
self.app.inform.emit('[ERROR_NOTCL] %s' % _("There are no tools selected in the Tool Table."))
|
|
||||||
return 'fail'
|
|
||||||
|
|
||||||
# update the Common Parameters values in the self.iso_tools
|
# update the Common Parameters values in the self.iso_tools
|
||||||
for tool_iso in self.iso_tools:
|
for tool_iso in tools_storage:
|
||||||
for key in self.iso_tools[tool_iso]:
|
for key in tools_storage[tool_iso]:
|
||||||
if key == 'data':
|
if key == 'data':
|
||||||
self.iso_tools[tool_iso][key]["tools_iso_rest"] = self.ui.rest_cb.get_value()
|
tools_storage[tool_iso][key]["tools_iso_rest"] = use_rest
|
||||||
self.iso_tools[tool_iso][key]["tools_iso_combine_passes"] = combine
|
tools_storage[tool_iso][key]["tools_iso_combine_passes"] = use_combine
|
||||||
self.iso_tools[tool_iso][key]["tools_iso_isoexcept"] = self.ui.except_cb.get_value()
|
tools_storage[tool_iso][key]["tools_iso_isoexcept"] = use_iso_except
|
||||||
self.iso_tools[tool_iso][key]["tools_iso_selection"] = self.ui.select_combo.get_value()
|
tools_storage[tool_iso][key]["tools_iso_selection"] = selection_type
|
||||||
self.iso_tools[tool_iso][key]["tools_iso_area_shape"] = self.ui.area_shape_radio.get_value()
|
tools_storage[tool_iso][key]["tools_iso_area_shape"] = sel_area_shape
|
||||||
self.iso_tools[tool_iso][key]["tools_mill_job_type"] = 2 # _("Isolation")
|
tools_storage[tool_iso][key]["tools_mill_job_type"] = 2 # _("Isolation")
|
||||||
self.iso_tools[tool_iso][key]["tools_mill_tool_shape"] = self.ui.tool_shape_combo.get_value()
|
tools_storage[tool_iso][key]["tools_mill_tool_shape"] = tool_tip_shape
|
||||||
|
|
||||||
if combine:
|
if use_combine:
|
||||||
if self.ui.rest_cb.get_value():
|
if use_rest:
|
||||||
self.combined_rest(iso_obj=isolated_obj, iso2geo=geometry, tools_storage=tools_storage,
|
self.combined_rest(iso_obj=isolated_obj, iso2geo=geometry, tools_storage=tools_storage,
|
||||||
lim_area=limited_area, negative_dia=negative_dia, plot=plot)
|
lim_area=limited_area, negative_dia=negative_dia, plot=plot)
|
||||||
else:
|
else:
|
||||||
self.combined_normal(iso_obj=isolated_obj, iso2geo=geometry, tools_storage=tools_storage,
|
self.combined_normal(iso_obj=isolated_obj, iso2geo=geometry, tools_storage=tools_storage,
|
||||||
lim_area=limited_area, negative_dia=negative_dia, plot=plot)
|
sel_tools=sel_tools, iso_except=use_iso_except, lim_area=limited_area,
|
||||||
|
negative_dia=negative_dia, extra_passes=use_extra_passes, plot=plot)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
prog_plot = self.app.defaults["tools_iso_plotting"]
|
prog_plot = self.app.defaults["tools_iso_plotting"]
|
||||||
|
|
||||||
for tool in sorted_tools:
|
for tool in sel_tools:
|
||||||
tool_data = tools_storage[tool]['data']
|
tool_data = tools_storage[tool]['data']
|
||||||
|
|
||||||
work_geo = geometry
|
work_geo = geometry
|
||||||
@@ -1781,8 +1793,6 @@ class ToolIsolation(AppTool, Gerber):
|
|||||||
|
|
||||||
milling_type = tool_data['tools_iso_milling_type']
|
milling_type = tool_data['tools_iso_milling_type']
|
||||||
|
|
||||||
iso_except = self.ui.except_cb.get_value()
|
|
||||||
|
|
||||||
tool_dia = tools_storage[tool]['tooldia']
|
tool_dia = tools_storage[tool]['tooldia']
|
||||||
for i in range(passes):
|
for i in range(passes):
|
||||||
iso_offset = tool_dia * ((2 * i + 1) / 2.0000001) - (i * overlap * tool_dia)
|
iso_offset = tool_dia * ((2 * i + 1) / 2.0000001) - (i * overlap * tool_dia)
|
||||||
@@ -1807,24 +1817,23 @@ class ToolIsolation(AppTool, Gerber):
|
|||||||
# if milling type is climb then the move is counter-clockwise around features
|
# if milling type is climb then the move is counter-clockwise around features
|
||||||
mill_dir = 1 if milling_type == 'cl' else 0
|
mill_dir = 1 if milling_type == 'cl' else 0
|
||||||
|
|
||||||
iso_geo = self.generate_envelope(iso_offset, mill_dir, geometry=work_geo, env_iso_type=iso_t,
|
iso_geo = self.generate_envelope(isolated_obj, iso_offset, mill_dir, geometry=work_geo,
|
||||||
nr_passes=i, prog_plot=prog_plot)
|
env_iso_type=iso_t, nr_passes=i, prog_plot=prog_plot)
|
||||||
if iso_geo == 'fail':
|
if iso_geo == 'fail':
|
||||||
self.app.inform.emit('[ERROR_NOTCL] %s' % _("Isolation geometry could not be generated."))
|
self.app.inform.emit('[ERROR_NOTCL] %s' % _("Isolation geometry could not be generated."))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Extra Pads isolations
|
# Extra Pads isolations
|
||||||
pad_geo = []
|
pad_geo = []
|
||||||
extra_passes = self.ui.pad_passes_entry.get_value()
|
if use_extra_passes > 0:
|
||||||
if extra_passes > 0:
|
|
||||||
solid_geo_union = unary_union(iso_geo)
|
solid_geo_union = unary_union(iso_geo)
|
||||||
extra_geo = []
|
extra_geo = []
|
||||||
for apid in self.grb_obj.tools:
|
for apid in isolated_obj.tools:
|
||||||
for t_geo_dict in self.grb_obj.tools[apid]['geometry']:
|
for t_geo_dict in isolated_obj.tools[apid]['geometry']:
|
||||||
if isinstance(t_geo_dict['follow'], Point):
|
if isinstance(t_geo_dict['follow'], Point):
|
||||||
extra_geo.append(t_geo_dict['solid'])
|
extra_geo.append(t_geo_dict['solid'])
|
||||||
|
|
||||||
for nr_pass in range(i, extra_passes + i):
|
for nr_pass in range(i, use_extra_passes + i):
|
||||||
pad_pass_geo = []
|
pad_pass_geo = []
|
||||||
for geo in extra_geo:
|
for geo in extra_geo:
|
||||||
iso_offset = tool_dia * ((2 * nr_pass + 1) / 2.0000001) - (
|
iso_offset = tool_dia * ((2 * nr_pass + 1) / 2.0000001) - (
|
||||||
@@ -1849,7 +1858,7 @@ class ToolIsolation(AppTool, Gerber):
|
|||||||
# ############################################################
|
# ############################################################
|
||||||
# ########## AREA SUBTRACTION ################################
|
# ########## AREA SUBTRACTION ################################
|
||||||
# ############################################################
|
# ############################################################
|
||||||
if iso_except:
|
if use_iso_except:
|
||||||
self.app.proc_container.update_view_text(' %s' % _("Subtracting Geo"))
|
self.app.proc_container.update_view_text(' %s' % _("Subtracting Geo"))
|
||||||
iso_geo = self.area_subtraction(iso_geo)
|
iso_geo = self.area_subtraction(iso_geo)
|
||||||
|
|
||||||
@@ -1874,18 +1883,17 @@ class ToolIsolation(AppTool, Gerber):
|
|||||||
# ############################################################
|
# ############################################################
|
||||||
# ########## AREA SUBTRACTION ################################
|
# ########## AREA SUBTRACTION ################################
|
||||||
# ############################################################
|
# ############################################################
|
||||||
if self.ui.except_cb.get_value():
|
if use_area_exception:
|
||||||
self.app.proc_container.update_view_text(' %s' % _("Subtracting Geo"))
|
self.app.proc_container.update_view_text(' %s' % _("Subtracting Geo"))
|
||||||
geo_obj.solid_geometry = self.area_subtraction(geo_obj.solid_geometry)
|
geo_obj.solid_geometry = self.area_subtraction(geo_obj.solid_geometry)
|
||||||
|
|
||||||
geo_obj.tools = {'1': {}}
|
geo_obj.tools = {
|
||||||
geo_obj.tools.update({
|
1: {
|
||||||
'1': {
|
|
||||||
'tooldia': float(tool_dia),
|
'tooldia': float(tool_dia),
|
||||||
'data': tool_data,
|
'data': tool_data,
|
||||||
'solid_geometry': geo_obj.solid_geometry
|
'solid_geometry': geo_obj.solid_geometry
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
|
||||||
# detect if solid_geometry is empty and this require list flattening which is "heavy"
|
# 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
|
# or just looking in the lists (they are one level depth) and if any is not empty
|
||||||
@@ -1902,12 +1910,12 @@ class ToolIsolation(AppTool, Gerber):
|
|||||||
empty_cnt += 1
|
empty_cnt += 1
|
||||||
|
|
||||||
if empty_cnt == len(geo_obj.solid_geometry):
|
if empty_cnt == len(geo_obj.solid_geometry):
|
||||||
fc_obj.inform.emit('[ERROR_NOTCL] %s: %s' % (
|
msg = '[ERROR_NOTCL] %s: %s' % (_("Empty Geometry in"), geo_obj.options["name"])
|
||||||
_("Empty Geometry in"), geo_obj.options["name"]))
|
fc_obj.inform.emit(msg)
|
||||||
return 'fail'
|
return 'fail'
|
||||||
else:
|
else:
|
||||||
fc_obj.inform.emit('[success] %s: %s' %
|
msg = '[success] %s: %s' % (_("Isolation geometry created"), geo_obj.options["name"])
|
||||||
(_("Isolation geometry created"), geo_obj.options["name"]))
|
fc_obj.inform.emit(msg)
|
||||||
geo_obj.multigeo = True
|
geo_obj.multigeo = True
|
||||||
|
|
||||||
self.app.app_obj.new_object("geometry", iso_name, iso_init, plot=plot)
|
self.app.app_obj.new_object("geometry", iso_name, iso_init, plot=plot)
|
||||||
@@ -1915,7 +1923,10 @@ class ToolIsolation(AppTool, Gerber):
|
|||||||
# clean the progressive plotted shapes if it was used
|
# clean the progressive plotted shapes if it was used
|
||||||
|
|
||||||
if prog_plot == 'progressive':
|
if prog_plot == 'progressive':
|
||||||
|
try:
|
||||||
self.temp_shapes.clear(update=True)
|
self.temp_shapes.clear(update=True)
|
||||||
|
except Exception as err:
|
||||||
|
self.app.log.debug("ToolIsolation.isolate(). Clear temp_shapes -> %s" % str(err))
|
||||||
|
|
||||||
# Switch notebook to Properties page
|
# Switch notebook to Properties page
|
||||||
# self.app.ui.notebook.setCurrentWidget(self.app.ui.properties_tab)
|
# self.app.ui.notebook.setCurrentWidget(self.app.ui.properties_tab)
|
||||||
@@ -1940,7 +1951,7 @@ class ToolIsolation(AppTool, Gerber):
|
|||||||
:rtype:
|
:rtype:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
log.debug("ToolIsolation.combine_rest()")
|
self.app.log.debug("ToolIsolation.combine_rest()")
|
||||||
|
|
||||||
total_solid_geometry = []
|
total_solid_geometry = []
|
||||||
|
|
||||||
@@ -2116,7 +2127,8 @@ class ToolIsolation(AppTool, Gerber):
|
|||||||
msg += coords
|
msg += coords
|
||||||
self.app.inform_shell.emit(msg=msg)
|
self.app.inform_shell.emit(msg=msg)
|
||||||
|
|
||||||
def combined_normal(self, iso_obj, iso2geo, tools_storage, lim_area, negative_dia=None, plot=True):
|
def combined_normal(self, iso_obj, iso2geo, tools_storage, lim_area, sel_tools, iso_except, extra_passes=None,
|
||||||
|
negative_dia=None, plot=True, prog_plot=None):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
:param iso_obj: the isolated Gerber object
|
:param iso_obj: the isolated Gerber object
|
||||||
@@ -2127,32 +2139,31 @@ class ToolIsolation(AppTool, Gerber):
|
|||||||
:type tools_storage: dict
|
:type tools_storage: dict
|
||||||
:param lim_area: if not None restrict isolation to this area
|
:param lim_area: if not None restrict isolation to this area
|
||||||
:type lim_area: Shapely Polygon or a list of them
|
:type lim_area: Shapely Polygon or a list of them
|
||||||
|
:param sel_tools: a list of the selected tools
|
||||||
|
:type sel_tools: list
|
||||||
|
:param iso_except: If True it will isolate except a special area
|
||||||
|
:type iso_except: bool
|
||||||
|
:param extra_passes: If not None then the value is the nr of extra isolation passes for pads only
|
||||||
|
:type extra_passes: int
|
||||||
:param negative_dia: isolate the geometry with a negative value for the tool diameter
|
:param negative_dia: isolate the geometry with a negative value for the tool diameter
|
||||||
:type negative_dia: bool
|
:type negative_dia: bool
|
||||||
:param plot: if to plot the resulting geometry object
|
:param plot: if to plot the resulting geometry object
|
||||||
:type plot: bool
|
:type plot: bool
|
||||||
|
:param prog_plot: If True a progressive plot is used
|
||||||
|
:type prog_plot: bool
|
||||||
:return: Isolated solid geometry
|
:return: Isolated solid geometry
|
||||||
:rtype:
|
:rtype:
|
||||||
"""
|
"""
|
||||||
log.debug("ToolIsolation.combined_normal()")
|
self.app.log.debug("ToolIsolation.combined_normal()")
|
||||||
|
|
||||||
total_solid_geometry = []
|
total_solid_geometry = []
|
||||||
|
|
||||||
iso_name = iso_obj.options["name"] + '_iso_combined'
|
iso_name = iso_obj.options["name"] + '_iso_combined'
|
||||||
geometry = iso2geo
|
geometry = iso2geo
|
||||||
|
if prog_plot is None:
|
||||||
prog_plot = self.app.defaults["tools_iso_plotting"]
|
prog_plot = self.app.defaults["tools_iso_plotting"]
|
||||||
|
|
||||||
sorted_tools = []
|
for tool in sel_tools:
|
||||||
table_items = self.ui.tools_table.selectedItems()
|
|
||||||
sel_rows = {t.row() for t in table_items}
|
|
||||||
for row in sel_rows:
|
|
||||||
tid = int(self.ui.tools_table.item(row, 3).text())
|
|
||||||
sorted_tools.append(tid)
|
|
||||||
if not sorted_tools:
|
|
||||||
self.app.inform.emit('[ERROR_NOTCL] %s' % _("There are no tools selected in the Tool Table."))
|
|
||||||
return 'fail'
|
|
||||||
|
|
||||||
for tool in sorted_tools:
|
|
||||||
tool_dia = tools_storage[tool]['tooldia']
|
tool_dia = tools_storage[tool]['tooldia']
|
||||||
tool_has_offset = tools_storage[tool]['data']['tools_mill_offset_type']
|
tool_has_offset = tools_storage[tool]['data']['tools_mill_offset_type']
|
||||||
tool_offset_value = tools_storage[tool]['data']['tools_mill_offset_value']
|
tool_offset_value = tools_storage[tool]['data']['tools_mill_offset_value']
|
||||||
@@ -2175,8 +2186,6 @@ class ToolIsolation(AppTool, Gerber):
|
|||||||
|
|
||||||
milling_type = tool_data['tools_iso_milling_type']
|
milling_type = tool_data['tools_iso_milling_type']
|
||||||
|
|
||||||
iso_except = self.ui.except_cb.get_value()
|
|
||||||
|
|
||||||
outname = "%s_%.*f" % (iso_obj.options["name"], self.decimals, float(tool_dia))
|
outname = "%s_%.*f" % (iso_obj.options["name"], self.decimals, float(tool_dia))
|
||||||
|
|
||||||
internal_name = outname + "_iso"
|
internal_name = outname + "_iso"
|
||||||
@@ -2198,7 +2207,7 @@ class ToolIsolation(AppTool, Gerber):
|
|||||||
# if milling type is climb then the move is counter-clockwise around features
|
# if milling type is climb then the move is counter-clockwise around features
|
||||||
mill_dir = 1 if milling_type == 'cl' else 0
|
mill_dir = 1 if milling_type == 'cl' else 0
|
||||||
|
|
||||||
iso_geo = self.generate_envelope(iso_offset, mill_dir, geometry=work_geo, env_iso_type=iso_t,
|
iso_geo = self.generate_envelope(iso_obj, iso_offset, mill_dir, geometry=work_geo, env_iso_type=iso_t,
|
||||||
nr_passes=nr_pass, prog_plot=prog_plot)
|
nr_passes=nr_pass, prog_plot=prog_plot)
|
||||||
if iso_geo == 'fail':
|
if iso_geo == 'fail':
|
||||||
self.app.inform.emit('[ERROR_NOTCL] %s' % _("Isolation geometry could not be generated."))
|
self.app.inform.emit('[ERROR_NOTCL] %s' % _("Isolation geometry could not be generated."))
|
||||||
@@ -2212,12 +2221,11 @@ class ToolIsolation(AppTool, Gerber):
|
|||||||
|
|
||||||
# Extra Pads isolations
|
# Extra Pads isolations
|
||||||
pad_geo = []
|
pad_geo = []
|
||||||
extra_passes = self.ui.pad_passes_entry.get_value()
|
if extra_passes is not None and extra_passes > 0:
|
||||||
if extra_passes > 0:
|
|
||||||
solid_geo_union = unary_union(solid_geo)
|
solid_geo_union = unary_union(solid_geo)
|
||||||
extra_geo = []
|
extra_geo = []
|
||||||
for apid in self.grb_obj.tools:
|
for apid in iso_obj.tools:
|
||||||
for t_geo_dict in self.grb_obj.tools[apid]['geometry']:
|
for t_geo_dict in iso_obj.tools[apid]['geometry']:
|
||||||
if 'follow' in t_geo_dict:
|
if 'follow' in t_geo_dict:
|
||||||
if isinstance(t_geo_dict['follow'], Point):
|
if isinstance(t_geo_dict['follow'], Point):
|
||||||
extra_geo.append(t_geo_dict['solid'])
|
extra_geo.append(t_geo_dict['solid'])
|
||||||
@@ -2263,7 +2271,10 @@ class ToolIsolation(AppTool, Gerber):
|
|||||||
|
|
||||||
# clean the progressive plotted shapes if it was used
|
# clean the progressive plotted shapes if it was used
|
||||||
if prog_plot == 'progressive':
|
if prog_plot == 'progressive':
|
||||||
|
try:
|
||||||
self.temp_shapes.clear(update=True)
|
self.temp_shapes.clear(update=True)
|
||||||
|
except Exception as err:
|
||||||
|
self.app.log.debug("ToolIsolation.combined_normal(). Progressive plotting -> %s" % str(err))
|
||||||
|
|
||||||
# remove tools without geometry
|
# remove tools without geometry
|
||||||
for tool, tool_dict in list(tools_storage.items()):
|
for tool, tool_dict in list(tools_storage.items()):
|
||||||
@@ -2507,16 +2518,29 @@ class ToolIsolation(AppTool, Gerber):
|
|||||||
|
|
||||||
self.app.tool_shapes.clear(update=True)
|
self.app.tool_shapes.clear(update=True)
|
||||||
|
|
||||||
|
sel_tools = []
|
||||||
|
table_items = self.ui.tools_table.selectedItems()
|
||||||
|
sel_rows = {t.row() for t in table_items}
|
||||||
|
for row in sel_rows:
|
||||||
|
tid = int(self.ui.tools_table.item(row, 3).text())
|
||||||
|
sel_tools.append(tid)
|
||||||
|
if not sel_tools:
|
||||||
|
self.app.inform.emit('[ERROR_NOTCL] %s' % _("There are no tools selected in the Tool Table."))
|
||||||
|
return 'fail'
|
||||||
|
|
||||||
if self.poly_dict:
|
if self.poly_dict:
|
||||||
poly_list = deepcopy(list(self.poly_dict.values()))
|
poly_list = deepcopy(list(self.poly_dict.values()))
|
||||||
if self.ui.poly_int_cb.get_value() is True:
|
if self.ui.poly_int_cb.get_value() is True:
|
||||||
# isolate the interior polygons with a negative tool
|
# isolate the interior polygons with a negative tool
|
||||||
self.isolate(isolated_obj=self.grb_obj, geometry=poly_list, negative_dia=True)
|
self.isolate(isolated_obj=self.grb_obj, geometry=poly_list, negative_dia=True, sel_tools=sel_tools,
|
||||||
|
tools_storage=self.iso_tools)
|
||||||
else:
|
else:
|
||||||
self.isolate(isolated_obj=self.grb_obj, geometry=poly_list)
|
self.isolate(isolated_obj=self.grb_obj, geometry=poly_list, sel_tools=sel_tools,
|
||||||
|
tools_storage=self.iso_tools)
|
||||||
self.poly_dict.clear()
|
self.poly_dict.clear()
|
||||||
else:
|
else:
|
||||||
self.app.inform.emit('[ERROR_NOTCL] %s' % _("List of single polygons is empty. Aborting."))
|
self.app.inform.emit('[ERROR_NOTCL] %s' % _("List of single polygons is empty. Aborting."))
|
||||||
|
return "fail"
|
||||||
|
|
||||||
def on_select_all_polygons(self):
|
def on_select_all_polygons(self):
|
||||||
self.app.log.debug("ToolIsolation.on_select_all_polygons()")
|
self.app.log.debug("ToolIsolation.on_select_all_polygons()")
|
||||||
@@ -2738,8 +2762,19 @@ class ToolIsolation(AppTool, Gerber):
|
|||||||
if len(self.sel_rect) == 0:
|
if len(self.sel_rect) == 0:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
sel_tools = []
|
||||||
|
table_items = self.ui.tools_table.selectedItems()
|
||||||
|
sel_rows = {t.row() for t in table_items}
|
||||||
|
for row in sel_rows:
|
||||||
|
tid = int(self.ui.tools_table.item(row, 3).text())
|
||||||
|
sel_tools.append(tid)
|
||||||
|
if not sel_tools:
|
||||||
|
self.app.inform.emit('[ERROR_NOTCL] %s' % _("There are no tools selected in the Tool Table."))
|
||||||
|
return 'fail'
|
||||||
|
|
||||||
self.sel_rect = unary_union(self.sel_rect)
|
self.sel_rect = unary_union(self.sel_rect)
|
||||||
self.isolate(isolated_obj=self.grb_obj, limited_area=self.sel_rect, plot=True)
|
self.isolate(isolated_obj=self.grb_obj, limited_area=self.sel_rect, sel_tools=sel_tools,
|
||||||
|
tools_storage=self.iso_tools, plot=True)
|
||||||
self.sel_rect = []
|
self.sel_rect = []
|
||||||
|
|
||||||
# called on mouse move
|
# called on mouse move
|
||||||
@@ -3002,7 +3037,7 @@ class ToolIsolation(AppTool, Gerber):
|
|||||||
def poly2ints(poly):
|
def poly2ints(poly):
|
||||||
return [interior for interior in poly.interiors]
|
return [interior for interior in poly.interiors]
|
||||||
|
|
||||||
def generate_envelope(self, offset, invert, geometry=None, env_iso_type=2, nr_passes=0,
|
def generate_envelope(self, iso_obj, offset, invert, geometry=None, env_iso_type=2, nr_passes=0,
|
||||||
prog_plot=False):
|
prog_plot=False):
|
||||||
"""
|
"""
|
||||||
Isolation_geometry produces an envelope that is going on the left of the geometry
|
Isolation_geometry produces an envelope that is going on the left of the geometry
|
||||||
@@ -3012,6 +3047,7 @@ class ToolIsolation(AppTool, Gerber):
|
|||||||
the other passes overlap preceding ones and cut the left over copper. It is better for them
|
the other passes overlap preceding ones and cut the left over copper. It is better for them
|
||||||
to cut on the right side of the left over copper i.e on the left side of the features.
|
to cut on the right side of the left over copper i.e on the left side of the features.
|
||||||
|
|
||||||
|
:param iso_obj: The Gerber object to be isolated
|
||||||
:param offset: Offset distance to be passed to the obj.isolation_geometry() method
|
:param offset: Offset distance to be passed to the obj.isolation_geometry() method
|
||||||
:type offset: float
|
:type offset: float
|
||||||
:param invert: If to invert the direction of geometry (CW to CCW or reverse)
|
:param invert: If to invert the direction of geometry (CW to CCW or reverse)
|
||||||
@@ -3029,10 +3065,10 @@ class ToolIsolation(AppTool, Gerber):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
geom_shp = self.grb_obj.isolation_geometry(offset, geometry=geometry, iso_type=env_iso_type,
|
geom_shp = iso_obj.isolation_geometry(offset, geometry=geometry, iso_type=env_iso_type,
|
||||||
passes=nr_passes, prog_plot=prog_plot)
|
passes=nr_passes, prog_plot=prog_plot)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.error('ToolIsolation.generate_envelope() --> %s' % str(e))
|
self.app.log.error('ToolIsolation.generate_envelope() --> %s' % str(e))
|
||||||
return 'fail'
|
return 'fail'
|
||||||
|
|
||||||
if isinstance(geom_shp, (MultiPolygon, MultiLineString)):
|
if isinstance(geom_shp, (MultiPolygon, MultiLineString)):
|
||||||
@@ -3056,10 +3092,10 @@ class ToolIsolation(AppTool, Gerber):
|
|||||||
elif isinstance(geom, LinearRing) and geom is not None:
|
elif isinstance(geom, LinearRing) and geom is not None:
|
||||||
geom = Polygon(geom.coords[::-1])
|
geom = Polygon(geom.coords[::-1])
|
||||||
else:
|
else:
|
||||||
log.debug("ToolIsolation.generate_envelope() Error --> Unexpected Geometry %s" %
|
msg = "ToolIsolation.generate_envelope() Error --> Unexpected Geometry %s" % type(geom)
|
||||||
type(geom))
|
self.app.log.debug(msg)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.error("ToolIsolation.generate_envelope() Error --> %s" % str(e))
|
self.app.log.error("ToolIsolation.generate_envelope() Error --> %s" % str(e))
|
||||||
return 'fail'
|
return 'fail'
|
||||||
return geom
|
return geom
|
||||||
|
|
||||||
|
|||||||
@@ -82,16 +82,18 @@ class TclCommandIsolate(TclCommandSignaled):
|
|||||||
par = args['combine'].capitalize()
|
par = args['combine'].capitalize()
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
par = args['combine']
|
par = args['combine']
|
||||||
args['combine'] = bool(eval(par))
|
args['combine'] = bool(eval(str(par)))
|
||||||
else:
|
else:
|
||||||
args['combine'] = bool(eval(str(self.app.defaults["tools_iso_combine_passes"])))
|
args['combine'] = bool(eval(str(self.app.defaults["tools_iso_combine_passes"])))
|
||||||
|
|
||||||
obj = self.app.collection.get_by_name(name)
|
obj = self.app.collection.get_by_name(name)
|
||||||
if obj is None:
|
if obj is None:
|
||||||
self.raise_tcl_error("Object not found: %s" % name)
|
self.raise_tcl_error("Object not found: %s" % name)
|
||||||
|
return "fail"
|
||||||
|
|
||||||
if obj.kind != 'gerber':
|
if obj.kind != 'gerber':
|
||||||
self.raise_tcl_error('Expected GerberObject, got %s %s.' % (name, type(obj)))
|
self.raise_tcl_error('Expected GerberObject, got %s %s.' % (name, type(obj)))
|
||||||
|
return "fail"
|
||||||
|
|
||||||
args.pop('name', None)
|
args.pop('name', None)
|
||||||
obj.isolate(plot=False, **args)
|
obj.isolate(plot=False, **args)
|
||||||
|
|||||||
Reference in New Issue
Block a user