- made Progressive plotting work in Isolation Tool

- fix an issue with progressive plotted shapes not being deleted on the end of the job
This commit is contained in:
Marius Stanciu 2020-06-01 20:37:31 +03:00 committed by Marius
parent aef1607fd5
commit 54407f6e50
3 changed files with 81 additions and 31 deletions

View File

@ -805,6 +805,9 @@ class ToolIsolation(AppTool, Gerber):
self.except_cb.set_value(False) self.except_cb.set_value(False)
self.except_cb.hide() self.except_cb.hide()
self.type_excobj_radio.hide()
self.exc_obj_combo.hide()
self.select_combo.setCurrentIndex(0) self.select_combo.setCurrentIndex(0)
self.select_combo.hide() self.select_combo.hide()
self.select_label.hide() self.select_label.hide()
@ -1747,6 +1750,8 @@ class ToolIsolation(AppTool, Gerber):
lim_area=limited_area, plot=plot) lim_area=limited_area, plot=plot)
else: else:
prog_plot = self.app.defaults["tools_iso_plotting"]
for tool in tools_storage: for tool in tools_storage:
tool_data = tools_storage[tool]['data'] tool_data = tools_storage[tool]['data']
to_follow = tool_data['tools_iso_follow'] to_follow = tool_data['tools_iso_follow']
@ -1793,7 +1798,7 @@ class ToolIsolation(AppTool, Gerber):
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_offset, mill_dir, geometry=work_geo, env_iso_type=iso_t,
follow=to_follow, nr_passes=i) follow=to_follow, nr_passes=i, prog_plot=prog_plot)
if iso_geo == 'fail': if iso_geo == 'fail':
self.app.inform.emit( self.app.inform.emit(
'[ERROR_NOTCL] %s' % _("Isolation geometry could not be generated.")) '[ERROR_NOTCL] %s' % _("Isolation geometry could not be generated."))
@ -1865,11 +1870,17 @@ class ToolIsolation(AppTool, Gerber):
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)
# clean the progressive plotted shapes if it was used
if prog_plot == 'progressive':
self.temp_shapes.clear(update=True)
# Switch notebook to Selected page # Switch notebook to Selected page
self.app.ui.notebook.setCurrentWidget(self.app.ui.selected_tab) self.app.ui.notebook.setCurrentWidget(self.app.ui.selected_tab)
def combined_rest(self, iso_obj, iso2geo, tools_storage, lim_area, plot=True): def combined_rest(self, iso_obj, iso2geo, tools_storage, lim_area, plot=True):
""" """
Isolate the provided Gerber object using "rest machining" strategy
:param iso_obj: the isolated Gerber object :param iso_obj: the isolated Gerber object
:type iso_obj: AppObjects.FlatCAMGerber.GerberObject :type iso_obj: AppObjects.FlatCAMGerber.GerberObject
@ -1904,6 +1915,9 @@ class ToolIsolation(AppTool, Gerber):
else: else:
pass pass
# decide to use "progressive" or "normal" plotting
prog_plot = self.app.defaults["tools_iso_plotting"]
for sorted_tool in sorted_tools: for sorted_tool in sorted_tools:
for tool in tools_storage: for tool in tools_storage:
if float('%.*f' % (self.decimals, tools_storage[tool]['tooldia'])) == sorted_tool: if float('%.*f' % (self.decimals, tools_storage[tool]['tooldia'])) == sorted_tool:
@ -1942,7 +1956,8 @@ class ToolIsolation(AppTool, Gerber):
solid_geo, work_geo = self.generate_rest_geometry(geometry=work_geo, tooldia=tool_dia, solid_geo, work_geo = self.generate_rest_geometry(geometry=work_geo, tooldia=tool_dia,
passes=passes, overlap=overlap, invert=mill_dir, passes=passes, overlap=overlap, invert=mill_dir,
env_iso_type=iso_t) env_iso_type=iso_t, prog_plot=prog_plot,
prog_plot_handler=self.plot_temp_shapes)
# ############################################################ # ############################################################
# ########## AREA SUBTRACTION ################################ # ########## AREA SUBTRACTION ################################
@ -1973,6 +1988,10 @@ class ToolIsolation(AppTool, Gerber):
if not work_geo: if not work_geo:
break break
# clean the progressive plotted shapes if it was used
if self.app.defaults["tools_iso_plotting"] == 'progressive':
self.temp_shapes.clear(update=True)
def iso_init(geo_obj, app_obj): def iso_init(geo_obj, app_obj):
geo_obj.options["cnctooldia"] = str(tool_dia) geo_obj.options["cnctooldia"] = str(tool_dia)
@ -2052,6 +2071,7 @@ class ToolIsolation(AppTool, Gerber):
iso_name = iso_obj.options["name"] + '_iso_combined' iso_name = iso_obj.options["name"] + '_iso_combined'
geometry = iso2geo geometry = iso2geo
prog_plot = self.app.defaults["tools_iso_plotting"]
for tool in tools_storage: for tool in tools_storage:
tool_dia = tools_storage[tool]['tooldia'] tool_dia = tools_storage[tool]['tooldia']
@ -2100,7 +2120,7 @@ class ToolIsolation(AppTool, Gerber):
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_offset, mill_dir, geometry=work_geo, env_iso_type=iso_t,
follow=to_follow, nr_passes=nr_pass) follow=to_follow, 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."))
continue continue
@ -2135,6 +2155,10 @@ class ToolIsolation(AppTool, Gerber):
total_solid_geometry += solid_geo total_solid_geometry += solid_geo
# clean the progressive plotted shapes if it was used
if prog_plot == 'progressive':
self.temp_shapes.clear(update=True)
def iso_init(geo_obj, app_obj): def iso_init(geo_obj, app_obj):
geo_obj.options["cnctooldia"] = str(tool_dia) geo_obj.options["cnctooldia"] = str(tool_dia)
@ -2709,7 +2733,8 @@ 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, follow=None, nr_passes=0): def generate_envelope(self, offset, invert, geometry=None, env_iso_type=2, follow=None, nr_passes=0,
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
(the copper features). To leave the least amount of burrs on the features (the copper features). To leave the least amount of burrs on the features
@ -2730,17 +2755,19 @@ class ToolIsolation(AppTool, Gerber):
:type follow: bool :type follow: bool
:param nr_passes: Number of passes :param nr_passes: Number of passes
:type nr_passes: int :type nr_passes: int
:param prog_plot: Type of plotting: "normal" or "progressive"
:type prog_plot: str
:return: The buffered geometry :return: The buffered geometry
:rtype: MultiPolygon or Polygon :rtype: MultiPolygon or Polygon
""" """
if follow: if follow:
geom = self.grb_obj.isolation_geometry(offset, geometry=geometry, follow=follow) geom = self.grb_obj.isolation_geometry(offset, geometry=geometry, follow=follow, prog_plot=prog_plot)
return geom return geom
else: else:
try: try:
geom = self.grb_obj.isolation_geometry(offset, geometry=geometry, iso_type=env_iso_type, geom = self.grb_obj.isolation_geometry(offset, geometry=geometry, iso_type=env_iso_type,
passes=nr_passes) passes=nr_passes, prog_plot=prog_plot)
except Exception as e: except Exception as e:
log.debug('ToolIsolation.generate_envelope() --> %s' % str(e)) log.debug('ToolIsolation.generate_envelope() --> %s' % str(e))
return 'fail' return 'fail'
@ -2769,25 +2796,30 @@ class ToolIsolation(AppTool, Gerber):
return geom return geom
@staticmethod @staticmethod
def generate_rest_geometry(geometry, tooldia, passes, overlap, invert, env_iso_type=2): def generate_rest_geometry(geometry, tooldia, passes, overlap, invert, env_iso_type=2,
prog_plot="normal", prog_plot_handler=None):
""" """
Will try to isolate the geometry and return a tuple made of list of paths made through isolation Will try to isolate the geometry and return a tuple made of list of paths made through isolation
and a list of Shapely Polygons that could not be isolated and a list of Shapely Polygons that could not be isolated
:param geometry: A list of Shapely Polygons to be isolated :param geometry: A list of Shapely Polygons to be isolated
:type geometry: list :type geometry: list
:param tooldia: The tool diameter used to do the isolation :param tooldia: The tool diameter used to do the isolation
:type tooldia: float :type tooldia: float
:param passes: Number of passes that will made the isolation :param passes: Number of passes that will made the isolation
:type passes: int :type passes: int
:param overlap: How much to overlap the previous pass; in percentage [0.00, 99.99]% :param overlap: How much to overlap the previous pass; in percentage [0.00, 99.99]%
:type overlap: float :type overlap: float
:param invert: If to invert the direction of the resulting isolated geometries :param invert: If to invert the direction of the resulting isolated geometries
:type invert: bool :type invert: bool
:param env_iso_type: can be either 0 = keep exteriors or 1 = keep interiors or 2 = keep all paths :param env_iso_type: can be either 0 = keep exteriors or 1 = keep interiors or 2 = keep all paths
:type env_iso_type: int :type env_iso_type: int
:return: Tuple made from list of isolating paths and list of not isolated Polygons :param prog_plot: kind of plotting: "progressive" or "normal"
:rtype: tuple :type prog_plot: str
:param prog_plot_handler: method used to plot shapes if plot_prog is "proggressive"
:type prog_plot_handler:
:return: Tuple made from list of isolating paths and list of not isolated Polygons
:rtype: tuple
""" """
isolated_geo = [] isolated_geo = []
@ -2819,7 +2851,10 @@ class ToolIsolation(AppTool, Gerber):
# if we had an intersection do nothing, else add the geo to the good pass isolations # if we had an intersection do nothing, else add the geo to the good pass isolations
if intersect_flag is False: if intersect_flag is False:
good_pass_iso.append(geo.buffer(iso_offset)) temp_geo = geo.buffer(iso_offset)
good_pass_iso.append(temp_geo)
if prog_plot == 'progressive':
prog_plot_handler(temp_geo)
if good_pass_iso: if good_pass_iso:
work_geo += good_pass_iso work_geo += good_pass_iso

View File

@ -23,6 +23,8 @@ CHANGELOG for FlatCAM beta
- after using Isolation Tool it will switch automatically to the Geometry UI - after using Isolation Tool it will switch automatically to the Geometry UI
- in Preferences replaced some widgets with a new one that combine a Slider with a Spinner (from David Robertson) - in Preferences replaced some widgets with a new one that combine a Slider with a Spinner (from David Robertson)
- in Preferences replaced the widgets that sets colors with a compound one (from David Robertson) - in Preferences replaced the widgets that sets colors with a compound one (from David Robertson)
- made Progressive plotting work in Isolation Tool
- fix an issue with progressive plotted shapes not being deleted on the end of the job
31.05.2020 31.05.2020

View File

@ -499,7 +499,7 @@ class Geometry(object):
self.el_count = 0 self.el_count = 0
if self.app.is_legacy is False: if self.app.is_legacy is False:
self.temp_shapes = self.app.plotcanvas.new_shape_group() self.temp_shapes = self.app.plotcanvas.new_shape_collection(layers=1)
else: else:
from AppGUI.PlotCanvasLegacy import ShapeCollectionLegacy from AppGUI.PlotCanvasLegacy import ShapeCollectionLegacy
self.temp_shapes = ShapeCollectionLegacy(obj=self, app=self.app, name='camlib.geometry') self.temp_shapes = ShapeCollectionLegacy(obj=self, app=self.app, name='camlib.geometry')
@ -915,7 +915,8 @@ class Geometry(object):
# #
# return self.flat_geometry, self.flat_geometry_rtree # return self.flat_geometry, self.flat_geometry_rtree
def isolation_geometry(self, offset, geometry=None, iso_type=2, corner=None, follow=None, passes=0): def isolation_geometry(self, offset, geometry=None, iso_type=2, corner=None, follow=None, passes=0,
prog_plot=False):
""" """
Creates contours around geometry at a given Creates contours around geometry at a given
offset distance. offset distance.
@ -928,6 +929,7 @@ class Geometry(object):
0 = round; 1 = square; 2= beveled (line that connects the ends) 0 = round; 1 = square; 2= beveled (line that connects the ends)
:param follow: whether the geometry to be isolated is a follow_geometry :param follow: whether the geometry to be isolated is a follow_geometry
:param passes: current pass out of possible multiple passes for which the isolation is done :param passes: current pass out of possible multiple passes for which the isolation is done
:param prog_plot: type of plotting: "normal" or "progressive"
:return: The buffered geometry. :return: The buffered geometry.
:rtype: Shapely.MultiPolygon or Shapely.Polygon :rtype: Shapely.MultiPolygon or Shapely.Polygon
""" """
@ -960,10 +962,13 @@ class Geometry(object):
# graceful abort requested by the user # graceful abort requested by the user
raise grace raise grace
if offset == 0: if offset == 0:
geo_iso.append(pol) temp_geo = pol
else: else:
corner_type = 1 if corner is None else corner corner_type = 1 if corner is None else corner
geo_iso.append(pol.buffer(offset, int(self.geo_steps_per_circle), join_style=corner_type)) temp_geo = pol.buffer(offset, int(self.geo_steps_per_circle), join_style=corner_type)
geo_iso.append(temp_geo)
pol_nr += 1 pol_nr += 1
# activity view update # activity view update
@ -977,10 +982,12 @@ class Geometry(object):
# taking care of the case when the self.solid_geometry is just a single Polygon, not a list or a # taking care of the case when the self.solid_geometry is just a single Polygon, not a list or a
# MultiPolygon (not an iterable) # MultiPolygon (not an iterable)
if offset == 0: if offset == 0:
geo_iso.append(working_geo) temp_geo = working_geo
else: else:
corner_type = 1 if corner is None else corner corner_type = 1 if corner is None else corner
geo_iso.append(working_geo.buffer(offset, int(self.geo_steps_per_circle), join_style=corner_type)) temp_geo = working_geo.buffer(offset, int(self.geo_steps_per_circle), join_style=corner_type)
geo_iso.append(temp_geo)
self.app.proc_container.update_view_text(' %s' % _("Buffering")) self.app.proc_container.update_view_text(' %s' % _("Buffering"))
geo_iso = unary_union(geo_iso) geo_iso = unary_union(geo_iso)
@ -989,17 +996,23 @@ class Geometry(object):
# end of replaced block # end of replaced block
if iso_type == 2: if iso_type == 2:
return geo_iso ret_geo = geo_iso
elif iso_type == 0: elif iso_type == 0:
self.app.proc_container.update_view_text(' %s' % _("Get Exteriors")) self.app.proc_container.update_view_text(' %s' % _("Get Exteriors"))
return self.get_exteriors(geo_iso) ret_geo = self.get_exteriors(geo_iso)
elif iso_type == 1: elif iso_type == 1:
self.app.proc_container.update_view_text(' %s' % _("Get Interiors")) self.app.proc_container.update_view_text(' %s' % _("Get Interiors"))
return self.get_interiors(geo_iso) ret_geo = self.get_interiors(geo_iso)
else: else:
log.debug("Geometry.isolation_geometry() --> Type of isolation not supported") log.debug("Geometry.isolation_geometry() --> Type of isolation not supported")
return "fail" return "fail"
if prog_plot == 'progressive':
for elem in ret_geo:
self.plot_temp_shapes(elem)
return ret_geo
def flatten_list(self, obj_list): def flatten_list(self, obj_list):
for item in obj_list: for item in obj_list:
if isinstance(item, Iterable) and not isinstance(item, (str, bytes)): if isinstance(item, Iterable) and not isinstance(item, (str, bytes)):