From f38dab80e3da116d99c3832ac4187b23bf4579bc Mon Sep 17 00:00:00 2001 From: Marius Stanciu Date: Mon, 9 Sep 2019 05:14:44 +0300 Subject: [PATCH] - added for NCC Tool and Paint Tool a setting in the Preferences -> Tools --> (NCC Tool/ Paint Tool) that can set a progressive plotting (plot shapes as they are processed) --- FlatCAMApp.py | 71 +++++++++--------- README.md | 1 + camlib.py | 82 +++++++++++++++++--- flatcamGUI/FlatCAMGUI.py | 24 +++++- flatcamTools/ToolNonCopperClear.py | 48 +++++++++--- flatcamTools/ToolPaint.py | 115 +++++++++++++++++++++++------ 6 files changed, 262 insertions(+), 79 deletions(-) diff --git a/FlatCAMApp.py b/FlatCAMApp.py index 71081ba9..af61c8ea 100644 --- a/FlatCAMApp.py +++ b/FlatCAMApp.py @@ -614,6 +614,7 @@ class App(QtCore.QObject): "tools_ncc_offset_choice": self.ui.tools_defaults_form.tools_ncc_group.ncc_choice_offset_cb, "tools_ncc_offset_value": self.ui.tools_defaults_form.tools_ncc_group.ncc_offset_spinner, "tools_nccref": self.ui.tools_defaults_form.tools_ncc_group.reference_radio, + "tools_ncc_plotting": self.ui.tools_defaults_form.tools_ncc_group.ncc_plotting_radio, "tools_nccmilling_type": self.ui.tools_defaults_form.tools_ncc_group.milling_type_radio, "tools_ncctool_type": self.ui.tools_defaults_form.tools_ncc_group.tool_type_radio, "tools_ncccutz": self.ui.tools_defaults_form.tools_ncc_group.cutz_entry, @@ -637,6 +638,7 @@ class App(QtCore.QObject): "tools_selectmethod": self.ui.tools_defaults_form.tools_paint_group.selectmethod_combo, "tools_pathconnect": self.ui.tools_defaults_form.tools_paint_group.pathconnect_cb, "tools_paintcontour": self.ui.tools_defaults_form.tools_paint_group.contour_cb, + "tools_paint_plotting": self.ui.tools_defaults_form.tools_paint_group.paint_plotting_radio, # 2-sided Tool "tools_2sided_mirror_axis": self.ui.tools_defaults_form.tools_2sided_group.mirror_axis_radio, @@ -1004,6 +1006,7 @@ class App(QtCore.QObject): "tools_ncc_offset_choice": False, "tools_ncc_offset_value": 0.0000, "tools_nccref": 'itself', + "tools_ncc_plotting": 'normal', "tools_nccmilling_type": 'cl', "tools_ncctool_type": 'V', "tools_ncccutz": -0.001968504, @@ -1025,6 +1028,7 @@ class App(QtCore.QObject): "tools_selectmethod": "single", "tools_pathconnect": True, "tools_paintcontour": True, + "tools_paint_plotting": 'normal', "tools_2sided_mirror_axis": "X", "tools_2sided_axis_loc": "point", @@ -5733,44 +5737,12 @@ class App(QtCore.QObject): for obj in self.collection.get_list(): obj.plot() self.plotcanvas.fit_view() + self.plotcanvas.vis_disconnect('mouse_press', self.on_set_zero_click) self.worker_task.emit({'fcn': worker_task, 'params': []}) - def on_set_zero_click(event): - # this function will be available only for mouse left click - - pos_canvas = self.plotcanvas.translate_coords(event.pos) - if event.button == 1: - if self.grid_status() == True: - pos = self.geo_editor.snap(pos_canvas[0], pos_canvas[1]) - else: - pos = pos_canvas - - x = 0 - pos[0] - y = 0 - pos[1] - - def worker_task(): - with self.proc_container.new(_("Setting Origin...")): - for obj in self.collection.get_list(): - obj.offset((x, y)) - self.object_changed.emit(obj) - - # Update the object bounding box options - a, b, c, d = obj.bounds() - obj.options['xmin'] = a - obj.options['ymin'] = b - obj.options['xmax'] = c - obj.options['ymax'] = d - self.inform.emit(_('[success] Origin set ...')) - self.replot_signal.emit([]) - - self.worker_task.emit({'fcn': worker_task, 'params': []}) - - self.plotcanvas.vis_disconnect('mouse_press', on_set_zero_click) - self.should_we_save = True - self.inform.emit(_('Click to set the origin ...')) - self.plotcanvas.vis_connect('mouse_press', on_set_zero_click) + self.plotcanvas.vis_connect('mouse_press', self.on_set_zero_click) # first disconnect it as it may have been used by something else try: @@ -5779,6 +5751,37 @@ class App(QtCore.QObject): pass self.replot_signal[list].connect(origin_replot) + def on_set_zero_click(self, event): + # this function will be available only for mouse left click + + pos_canvas = self.plotcanvas.translate_coords(event.pos) + if event.button == 1: + if self.grid_status() == True: + pos = self.geo_editor.snap(pos_canvas[0], pos_canvas[1]) + else: + pos = pos_canvas + + x = 0 - pos[0] + y = 0 - pos[1] + + def worker_task(): + with self.proc_container.new(_("Setting Origin...")): + for obj in self.collection.get_list(): + obj.offset((x, y)) + self.object_changed.emit(obj) + + # Update the object bounding box options + a, b, c, d = obj.bounds() + obj.options['xmin'] = a + obj.options['ymin'] = b + obj.options['xmax'] = c + obj.options['ymax'] = d + self.inform.emit(_('[success] Origin set ...')) + self.replot_signal.emit([]) + + self.worker_task.emit({'fcn': worker_task, 'params': []}) + self.should_we_save = True + def on_jump_to(self, custom_location=None, fit_center=True): """ Jump to a location by setting the mouse cursor location diff --git a/README.md b/README.md index 5374b48a..0ff4e1eb 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ CAD program, and create G-Code for Isolation routing. - changed the triangulation type in VisPyVisuals for ShapeCollectionVisual class - added a setting in Preferences -> Gerber -> Gerber General named Buffering. If set to 'no' the Gerber objects load a lot more faster (perhaps 10 times faster than when set to 'full') but the visual look is not so great as all the aperture polygons can be seen +- added for NCC Tool and Paint Tool a setting in the Preferences -> Tools --> (NCC Tool/ Paint Tool) that can set a progressive plotting (plot shapes as they are processed) 8.09.2019 diff --git a/camlib.py b/camlib.py index 03121e45..048711ac 100644 --- a/camlib.py +++ b/camlib.py @@ -117,10 +117,22 @@ class Geometry(object): self.old_disp_number = 0 self.el_count = 0 + self.temp_shapes = self.app.plotcanvas.new_shape_group() + # if geo_steps_per_circle is None: # geo_steps_per_circle = int(Geometry.defaults["geo_steps_per_circle"]) # self.geo_steps_per_circle = geo_steps_per_circle + def plot_temp_shapes(self, element, color='red'): + + try: + for sub_el in element: + self.plot_temp_shapes(sub_el) + except TypeError: # Element is not iterable... + # self.add_shape(shape=element, color=color, visible=visible, layer=0) + self.temp_shapes.add(tolerance=float(self.app.defaults["global_tolerance"]), + shape=element, color=color, visible=True, layer=0) + def make_index(self): self.flatten() self.index = FlatCAMRTree() @@ -802,7 +814,8 @@ class Geometry(object): return boundary.difference(self.solid_geometry) - def clear_polygon(self, polygon, tooldia, steps_per_circle, overlap=0.15, connect=True, contour=True): + def clear_polygon(self, polygon, tooldia, steps_per_circle, overlap=0.15, connect=True, contour=True, + prog_plot=False): """ Creates geometry inside a polygon for a tool to cover the whole area. @@ -818,6 +831,7 @@ class Geometry(object): minimize tool lifts. :param contour: Paint around the edges. Inconsequential in this painting method. + :param prog_plot: boolean; if Ture use the progressive plotting :return: """ @@ -870,16 +884,25 @@ class Geometry(object): geoms.insert(p.exterior) for i in p.interiors: geoms.insert(i) + if prog_plot: + self.plot_temp_shapes(p) # Not a Multipolygon. Must be a Polygon except TypeError: geoms.insert(current.exterior) + if prog_plot: + self.plot_temp_shapes(current.exterior) for i in current.interiors: geoms.insert(i) + if prog_plot: + self.plot_temp_shapes(i) else: log.debug("camlib.Geometry.clear_polygon() --> Current Area is zero") break + if prog_plot: + self.temp_shapes.redraw() + # Optimization: Reduce lifts if connect: # log.debug("Reducing tool lifts...") @@ -888,7 +911,7 @@ class Geometry(object): return geoms def clear_polygon2(self, polygon_to_clear, tooldia, steps_per_circle, seedpoint=None, overlap=0.15, - connect=True, contour=True): + connect=True, contour=True, prog_plot=False): """ Creates geometry inside a polygon for a tool to cover the whole area. @@ -907,6 +930,7 @@ class Geometry(object): :param contour: Cut countour inside the polygon. :return: List of toolpaths covering polygon. :rtype: FlatCAMRTreeStorage | None + :param prog_plot: boolean; if True use the progressive plotting """ # log.debug("camlib.clear_polygon2()") @@ -952,8 +976,15 @@ class Geometry(object): try: for p in path: geoms.insert(p) + if prog_plot: + self.plot_temp_shapes(p) except TypeError: geoms.insert(path) + if prog_plot: + self.plot_temp_shapes(path) + + if prog_plot: + self.temp_shapes.redraw() radius += tooldia * (1 - overlap) @@ -969,6 +1000,11 @@ class Geometry(object): # geoms += outer_edges + inner_edges for g in outer_edges + inner_edges: geoms.insert(g) + if prog_plot: + self.plot_temp_shapes(g) + + if prog_plot: + self.temp_shapes.redraw() # Optimization connect touching paths # log.debug("Connecting paths...") @@ -981,7 +1017,8 @@ class Geometry(object): return geoms - def clear_polygon3(self, polygon, tooldia, steps_per_circle, overlap=0.15, connect=True, contour=True): + def clear_polygon3(self, polygon, tooldia, steps_per_circle, overlap=0.15, connect=True, contour=True, + prog_plot=False): """ Creates geometry inside a polygon for a tool to cover the whole area. @@ -995,6 +1032,7 @@ class Geometry(object): :param overlap: Tool path overlap percentage. :param connect: Connect lines to avoid tool lifts. :param contour: Paint around the edges. + :param prog_plot: boolean; if to use the progressive plotting :return: """ @@ -1008,11 +1046,13 @@ class Geometry(object): geoms = FlatCAMRTreeStorage() geoms.get_points = get_pts - lines = [] + lines_trimmed = [] # Bounding box left, bot, right, top = polygon.bounds + margin_poly = polygon.buffer(-tooldia / 1.99999999, (int(steps_per_circle))) + # First line y = top - tooldia / 1.99999999 while y > bot + tooldia / 1.999999999: @@ -1021,20 +1061,33 @@ class Geometry(object): raise FlatCAMApp.GracefulException line = LineString([(left, y), (right, y)]) - lines.append(line) + line = line.intersection(margin_poly) + lines_trimmed.append(line) y -= tooldia * (1 - overlap) + if prog_plot: + self.plot_temp_shapes(line) + self.temp_shapes.redraw() # Last line y = bot + tooldia / 2 line = LineString([(left, y), (right, y)]) - lines.append(line) + line = line.intersection(margin_poly) + for ll in line: + lines_trimmed.append(ll) + if prog_plot: + self.plot_temp_shapes(line) # Combine - linesgeo = unary_union(lines) + # linesgeo = unary_union(lines) # Trim to the polygon - margin_poly = polygon.buffer(-tooldia / 1.99999999, (int(steps_per_circle))) - lines_trimmed = linesgeo.intersection(margin_poly) + # margin_poly = polygon.buffer(-tooldia / 1.99999999, (int(steps_per_circle))) + # lines_trimmed = linesgeo.intersection(margin_poly) + + if prog_plot: + self.temp_shapes.redraw() + + lines_trimmed = unary_union(lines_trimmed) # Add lines to storage try: @@ -1048,13 +1101,24 @@ class Geometry(object): if contour: if isinstance(margin_poly, Polygon): geoms.insert(margin_poly.exterior) + if prog_plot: + self.plot_temp_shapes(margin_poly.exterior) for ints in margin_poly.interiors: geoms.insert(ints) + if prog_plot: + self.plot_temp_shapes(ints) elif isinstance(margin_poly, MultiPolygon): for poly in margin_poly: geoms.insert(poly.exterior) + if prog_plot: + self.plot_temp_shapes(poly.exterior) for ints in poly.interiors: geoms.insert(ints) + if prog_plot: + self.plot_temp_shapes(ints) + + if prog_plot: + self.temp_shapes.redraw() # Optimization: Reduce lifts if connect: diff --git a/flatcamGUI/FlatCAMGUI.py b/flatcamGUI/FlatCAMGUI.py index 23e599c3..09d34802 100644 --- a/flatcamGUI/FlatCAMGUI.py +++ b/flatcamGUI/FlatCAMGUI.py @@ -6663,6 +6663,17 @@ class ToolsNCCPrefGroupUI(OptionsGroupUI): grid0.addWidget(reference_label, 15, 0) grid0.addWidget(self.reference_radio, 15, 1) + # ## Plotting type + self.ncc_plotting_radio = RadioSet([{'label': _('Normal'), 'value': 'normal'}, + {"label": _("progressive"), "value": "progressive"}]) + plotting_label = QtWidgets.QLabel('%s:' % _("NCC Plotting")) + plotting_label.setToolTip( + _("- 'Normal' - normal plotting, done at the end of the NCC job\n" + "- 'Progressive' - after each shape is generated it will be plotted.") + ) + grid0.addWidget(plotting_label, 16, 0) + grid0.addWidget(self.ncc_plotting_radio, 16, 1) + self.layout.addStretch() @@ -6949,15 +6960,26 @@ class ToolsPaintPrefGroupUI(OptionsGroupUI): "- 'Reference Object' - will do non copper clearing within the area\n" "specified by another object.") ) - grid0.addWidget(selectlabel, 7, 0) self.selectmethod_combo = RadioSet([ {"label": _("Single"), "value": "single"}, {"label": _("Area"), "value": "area"}, {"label": _("All"), "value": "all"}, {"label": _("Ref."), "value": "ref"} ]) + grid0.addWidget(selectlabel, 7, 0) grid0.addWidget(self.selectmethod_combo, 7, 1) + # ## Plotting type + self.paint_plotting_radio = RadioSet([{'label': _('Normal'), 'value': 'normal'}, + {"label": _("progressive"), "value": "progressive"}]) + plotting_label = QtWidgets.QLabel('%s:' % _("Paint Plotting")) + plotting_label.setToolTip( + _("- 'Normal' - normal plotting, done at the end of the Paint job\n" + "- 'Progressive' - after each shape is generated it will be plotted.") + ) + grid0.addWidget(plotting_label, 8, 0) + grid0.addWidget(self.paint_plotting_radio, 8, 1) + self.layout.addStretch() diff --git a/flatcamTools/ToolNonCopperClear.py b/flatcamTools/ToolNonCopperClear.py index 27355d82..550a5565 100644 --- a/flatcamTools/ToolNonCopperClear.py +++ b/flatcamTools/ToolNonCopperClear.py @@ -1351,6 +1351,10 @@ class NonCopperClear(FlatCAMTool, Gerber): contour = contour if contour else self.app.defaults["tools_ncccontour"] order = order if order else self.ncc_order_radio.get_value() + # determine if to use the progressive plotting + if self.app.defaults["tools_ncc_plotting"] == 'progressive': + prog_plot = True + if tools_storage is not None: tools_storage = tools_storage else: @@ -1703,13 +1707,16 @@ class NonCopperClear(FlatCAMTool, Gerber): if isinstance(p, Polygon): if ncc_method == 'standard': cp = self.clear_polygon(p, tool, self.app.defaults["gerber_circle_steps"], - overlap=overlap, contour=contour, connect=connect) + overlap=overlap, contour=contour, connect=connect, + prog_plot=prog_plot) elif ncc_method == 'seed': cp = self.clear_polygon2(p, tool, self.app.defaults["gerber_circle_steps"], - overlap=overlap, contour=contour, connect=connect) + overlap=overlap, contour=contour, connect=connect, + prog_plot=prog_plot) else: cp = self.clear_polygon3(p, tool, self.app.defaults["gerber_circle_steps"], - overlap=overlap, contour=contour, connect=connect) + overlap=overlap, contour=contour, connect=connect, + prog_plot=prog_plot) if cp: cleared_geo += list(cp.get_objects()) elif isinstance(p, MultiPolygon): @@ -1719,17 +1726,20 @@ class NonCopperClear(FlatCAMTool, Gerber): cp = self.clear_polygon(pol, tool, self.app.defaults["gerber_circle_steps"], overlap=overlap, contour=contour, - connect=connect) + connect=connect, + prog_plot=prog_plot) elif ncc_method == 'seed': cp = self.clear_polygon2(pol, tool, self.app.defaults["gerber_circle_steps"], overlap=overlap, contour=contour, - connect=connect) + connect=connect, + prog_plot=prog_plot) else: cp = self.clear_polygon3(pol, tool, self.app.defaults["gerber_circle_steps"], overlap=overlap, contour=contour, - connect=connect) + connect=connect, + prog_plot=prog_plot) if cp: cleared_geo += list(cp.get_objects()) except Exception as e: @@ -1770,6 +1780,10 @@ class NonCopperClear(FlatCAMTool, Gerber): else: log.debug("There are no geometries in the cleared polygon.") + # clean the progressive plotted shapes if it was used + if self.app.defaults["tools_ncc_plotting"] == 'progressive': + self.temp_shapes.clear(update=True) + # delete tools with empty geometry keys_to_delete = [] # look for keys in the tools_storage dict that have 'solid_geometry' values empty @@ -2043,15 +2057,18 @@ class NonCopperClear(FlatCAMTool, Gerber): if ncc_method == 'standard': cp = self.clear_polygon(p, tool_used, self.app.defaults["gerber_circle_steps"], - overlap=overlap, contour=contour, connect=connect) + overlap=overlap, contour=contour, connect=connect, + prog_plot=prog_plot) elif ncc_method == 'seed': cp = self.clear_polygon2(p, tool_used, self.app.defaults["gerber_circle_steps"], - overlap=overlap, contour=contour, connect=connect) + overlap=overlap, contour=contour, connect=connect, + prog_plot=prog_plot) else: cp = self.clear_polygon3(p, tool_used, self.app.defaults["gerber_circle_steps"], - overlap=overlap, contour=contour, connect=connect) + overlap=overlap, contour=contour, connect=connect, + prog_plot=prog_plot) cleared_geo.append(list(cp.get_objects())) except Exception as e: log.warning("Polygon can't be cleared. %s" % str(e)) @@ -2066,17 +2083,20 @@ class NonCopperClear(FlatCAMTool, Gerber): cp = self.clear_polygon(poly, tool_used, self.app.defaults["gerber_circle_steps"], overlap=overlap, contour=contour, - connect=connect) + connect=connect, + prog_plot=prog_plot) elif ncc_method == 'seed': cp = self.clear_polygon2(poly, tool_used, self.app.defaults["gerber_circle_steps"], overlap=overlap, contour=contour, - connect=connect) + connect=connect, + prog_plot=prog_plot) else: cp = self.clear_polygon3(poly, tool_used, self.app.defaults["gerber_circle_steps"], overlap=overlap, contour=contour, - connect=connect) + connect=connect, + prog_plot=prog_plot) cleared_geo.append(list(cp.get_objects())) except Exception as e: log.warning("Polygon can't be cleared. %s" % str(e)) @@ -2138,6 +2158,10 @@ class NonCopperClear(FlatCAMTool, Gerber): geo_obj.multigeo = True geo_obj.options["cnctooldia"] = str(tool) + # clean the progressive plotted shapes if it was used + if self.app.defaults["tools_ncc_plotting"] == 'progressive': + self.temp_shapes.clear(update=True) + # check to see if geo_obj.tools is empty # it will be updated only if there is a solid_geometry for tools if geo_obj.tools: diff --git a/flatcamTools/ToolPaint.py b/flatcamTools/ToolPaint.py index ca45fd3c..da2beca8 100644 --- a/flatcamTools/ToolPaint.py +++ b/flatcamTools/ToolPaint.py @@ -518,6 +518,8 @@ class ToolPaint(FlatCAMTool, Gerber): self.paintcontour_cb.set_value(self.default_data["paintcontour"]) self.paintoverlap_entry.set_value(self.default_data["paintoverlap"]) + # make the default object type, "Geometry" + self.type_obj_combo.setCurrentIndex(2) # updated units self.units = self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().upper() @@ -1204,6 +1206,9 @@ class ToolPaint(FlatCAMTool, Gerber): self.app.inform.emit('[ERROR_NOTCL] %s' % _("Wrong value format entered, use a number.")) return + # determine if to use the progressive plotting + if self.app.defaults["tools_paint_plotting"] == 'progressive': + prog_plot = True # No polygon? if poly is None: @@ -1263,7 +1268,8 @@ class ToolPaint(FlatCAMTool, Gerber): steps_per_circle=self.app.defaults["geometry_circle_steps"], overlap=over, contour=cont, - connect=conn) + connect=conn, + prog_plot=prog_plot) elif paint_method == "lines": # Type(cp) == FlatCAMRTreeStorage | None @@ -1272,7 +1278,8 @@ class ToolPaint(FlatCAMTool, Gerber): steps_per_circle=self.app.defaults["geometry_circle_steps"], overlap=over, contour=cont, - connect=conn) + connect=conn, + prog_plot=prog_plot) else: # Type(cp) == FlatCAMRTreeStorage | None @@ -1281,7 +1288,8 @@ class ToolPaint(FlatCAMTool, Gerber): steps_per_circle=self.app.defaults["geometry_circle_steps"], overlap=over, contour=cont, - connect=conn) + connect=conn, + prog_plot=prog_plot) except FlatCAMApp.GracefulException: return "fail" except Exception as e: @@ -1349,6 +1357,10 @@ class ToolPaint(FlatCAMTool, Gerber): tools_storage[current_uid]['data']['name'] = name total_geometry[:] = [] + # clean the progressive plotted shapes if it was used + if self.app.defaults["tools_paint_plotting"] == 'progressive': + self.temp_shapes.clear(update=True) + # delete tools with empty geometry keys_to_delete = [] # look for keys in the tools_storage dict that have 'solid_geometry' values empty @@ -1462,6 +1474,10 @@ class ToolPaint(FlatCAMTool, Gerber): _("Wrong value format entered, use a number.")) return + # determine if to use the progressive plotting + if self.app.defaults["tools_paint_plotting"] == 'progressive': + prog_plot = True + proc = self.app.proc_container.new(_("Painting polygons...")) name = outname if outname is not None else self.obj_name + "_paint" @@ -1603,7 +1619,8 @@ class ToolPaint(FlatCAMTool, Gerber): steps_per_circle=self.app.defaults["geometry_circle_steps"], overlap=over, contour=cont, - connect=conn) + connect=conn, + prog_plot=prog_plot) elif paint_method == "lines": # Type(cp) == FlatCAMRTreeStorage | None @@ -1612,7 +1629,8 @@ class ToolPaint(FlatCAMTool, Gerber): steps_per_circle=self.app.defaults["geometry_circle_steps"], overlap=over, contour=cont, - connect=conn) + connect=conn, + prog_plot=prog_plot) else: # Type(cp) == FlatCAMRTreeStorage | None @@ -1621,7 +1639,8 @@ class ToolPaint(FlatCAMTool, Gerber): steps_per_circle=self.app.defaults["geometry_circle_steps"], overlap=over, contour=cont, - connect=conn) + connect=conn, + prog_plot=prog_plot) if cp is not None: total_geometry += list(cp.get_objects()) @@ -1651,6 +1670,10 @@ class ToolPaint(FlatCAMTool, Gerber): tools_storage[current_uid]['data']['name'] = name total_geometry[:] = [] + # clean the progressive plotted shapes if it was used + if self.app.defaults["tools_paint_plotting"] == 'progressive': + self.temp_shapes.clear(update=True) + # delete tools with empty geometry keys_to_delete = [] # look for keys in the tools_storage dict that have 'solid_geometry' values empty @@ -1741,19 +1764,22 @@ class ToolPaint(FlatCAMTool, Gerber): # Type(cp) == FlatCAMRTreeStorage | None cp = self.clear_polygon(poly_buf, tooldia=tool_dia, steps_per_circle=self.app.defaults["geometry_circle_steps"], - overlap=over, contour=cont, connect=conn) + overlap=over, contour=cont, connect=conn, + prog_plot=prog_plot) elif paint_method == "seed": # Type(cp) == FlatCAMRTreeStorage | None cp = self.clear_polygon2(poly_buf, tooldia=tool_dia, steps_per_circle=self.app.defaults["geometry_circle_steps"], - overlap=over, contour=cont, connect=conn) + overlap=over, contour=cont, connect=conn, + prog_plot=prog_plot) elif paint_method == "lines": # Type(cp) == FlatCAMRTreeStorage | None cp = self.clear_polygon3(poly_buf, tooldia=tool_dia, steps_per_circle=self.app.defaults["geometry_circle_steps"], - overlap=over, contour=cont, connect=conn) + overlap=over, contour=cont, connect=conn, + prog_plot=prog_plot) if cp is not None: cleared_geo += list(cp.get_objects()) @@ -1796,6 +1822,10 @@ class ToolPaint(FlatCAMTool, Gerber): geo_obj.tools.clear() geo_obj.tools = dict(tools_storage) + # clean the progressive plotted shapes if it was used + if self.app.defaults["tools_paint_plotting"] == 'progressive': + self.temp_shapes.clear(update=True) + # test if at least one tool has solid_geometry. If no tool has solid_geometry we raise an Exception has_solid_geo = 0 for tooluid in geo_obj.tools: @@ -1882,6 +1912,10 @@ class ToolPaint(FlatCAMTool, Gerber): _("Wrong value format entered, use a number.")) return + # determine if to use the progressive plotting + if self.app.defaults["tools_paint_plotting"] == 'progressive': + prog_plot = True + proc = self.app.proc_container.new(_("Painting polygons...")) name = outname if outname is not None else self.obj_name + "_paint" @@ -1960,15 +1994,21 @@ class ToolPaint(FlatCAMTool, Gerber): # this is were heavy lifting is done and creating the geometry to be painted geo_to_paint = [] - if not isinstance(obj.solid_geometry, list): - target_geo = [obj.solid_geometry] - else: - target_geo = obj.solid_geometry + target_geo = obj.solid_geometry - for poly in target_geo: - new_pol = poly.intersection(sel_obj) + if self.app.defaults["tools_paint_plotting"] == 'progressive': + target_geo = MultiPolygon(target_geo).buffer(0) + + try: + for poly in target_geo: + new_pol = poly.intersection(sel_obj) + geo_to_paint.append(new_pol) + except TypeError: + new_pol = target_geo.intersection(sel_obj) geo_to_paint.append(new_pol) + painted_area = recurse(geo_to_paint) + try: a, b, c, d = self.paint_bounds(geo_to_paint) geo_obj.options['xmin'] = a @@ -1999,7 +2039,6 @@ class ToolPaint(FlatCAMTool, Gerber): current_uid = int(k) break - painted_area = recurse(geo_to_paint) # variables to display the percentage of work done geo_len = len(painted_area) disp_number = 0 @@ -2022,7 +2061,8 @@ class ToolPaint(FlatCAMTool, Gerber): steps_per_circle=self.app.defaults["geometry_circle_steps"], overlap=over, contour=cont, - connect=conn) + connect=conn, + prog_plot=prog_plot) elif paint_method == "lines": # Type(cp) == FlatCAMRTreeStorage | None @@ -2031,7 +2071,8 @@ class ToolPaint(FlatCAMTool, Gerber): steps_per_circle=self.app.defaults["geometry_circle_steps"], overlap=over, contour=cont, - connect=conn) + connect=conn, + prog_plot=prog_plot) else: # Type(cp) == FlatCAMRTreeStorage | None @@ -2040,7 +2081,8 @@ class ToolPaint(FlatCAMTool, Gerber): steps_per_circle=self.app.defaults["geometry_circle_steps"], overlap=over, contour=cont, - connect=conn) + connect=conn, + prog_plot=prog_plot) if cp is not None: total_geometry += list(cp.get_objects()) @@ -2069,6 +2111,10 @@ class ToolPaint(FlatCAMTool, Gerber): tools_storage[current_uid]['data']['name'] = name total_geometry[:] = [] + # clean the progressive plotted shapes if it was used + if self.app.defaults["tools_paint_plotting"] == 'progressive': + self.temp_shapes.clear(update=True) + # delete tools with empty geometry keys_to_delete = [] # look for keys in the tools_storage dict that have 'solid_geometry' values empty @@ -2121,6 +2167,23 @@ class ToolPaint(FlatCAMTool, Gerber): current_uid = int(1) geo_obj.solid_geometry = [] + # this is were heavy lifting is done and creating the geometry to be painted + geo_to_paint = [] + target_geo = obj.solid_geometry + + if self.app.defaults["tools_paint_plotting"] == 'progressive': + target_geo = MultiPolygon(target_geo).buffer(0) + + try: + for poly in target_geo: + new_pol = poly.intersection(sel_obj) + geo_to_paint.append(new_pol) + except TypeError: + new_pol = target_geo.intersection(sel_obj) + geo_to_paint.append(new_pol) + + painted_area = recurse(geo_to_paint) + try: a, b, c, d = obj.bounds() geo_obj.options['xmin'] = a @@ -2141,7 +2204,6 @@ class ToolPaint(FlatCAMTool, Gerber): ) app_obj.proc_container.update_view_text(' %d%%' % 0) - painted_area = recurse(obj.solid_geometry) # variables to display the percentage of work done geo_len = len(painted_area) disp_number = 0 @@ -2159,19 +2221,22 @@ class ToolPaint(FlatCAMTool, Gerber): # Type(cp) == FlatCAMRTreeStorage | None cp = self.clear_polygon(poly_buf, tooldia=tool_dia, steps_per_circle=self.app.defaults["geometry_circle_steps"], - overlap=over, contour=cont, connect=conn) + overlap=over, contour=cont, connect=conn, + prog_plot=prog_plot) elif paint_method == "seed": # Type(cp) == FlatCAMRTreeStorage | None cp = self.clear_polygon2(poly_buf, tooldia=tool_dia, steps_per_circle=self.app.defaults["geometry_circle_steps"], - overlap=over, contour=cont, connect=conn) + overlap=over, contour=cont, connect=conn, + prog_plot=prog_plot) elif paint_method == "lines": # Type(cp) == FlatCAMRTreeStorage | None cp = self.clear_polygon3(poly_buf, tooldia=tool_dia, steps_per_circle=self.app.defaults["geometry_circle_steps"], - overlap=over, contour=cont, connect=conn) + overlap=over, contour=cont, connect=conn, + prog_plot=prog_plot) if cp is not None: cleared_geo += list(cp.get_objects()) @@ -2213,6 +2278,10 @@ class ToolPaint(FlatCAMTool, Gerber): geo_obj.tools.clear() geo_obj.tools = dict(self.paint_tools) + # clean the progressive plotted shapes if it was used + if self.app.defaults["tools_paint_plotting"] == 'progressive': + self.temp_shapes.clear(update=True) + # test if at least one tool has solid_geometry. If no tool has solid_geometry we raise an Exception has_solid_geo = 0 for tooluid in geo_obj.tools: