- refactored the Isolation Plugin class

This commit is contained in:
Marius Stanciu
2022-01-30 03:50:27 +02:00
committed by Marius
parent 05c4993f92
commit 66b874835c
3 changed files with 127 additions and 85 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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)