diff --git a/FlatCAMObj.py b/FlatCAMObj.py index 45624daf..97114303 100644 --- a/FlatCAMObj.py +++ b/FlatCAMObj.py @@ -51,6 +51,9 @@ class FlatCAMObj(QtCore.QObject): # The app should set this value. app = None + # signal to plot a single object + plot_single_object = pyqtSignal() + def __init__(self, name): """ Constructor. @@ -96,6 +99,8 @@ class FlatCAMObj(QtCore.QObject): # self.units = 'IN' self.units = self.app.ui.general_defaults_form.general_app_group.units_radio.get_value().upper() + self.plot_single_object.connect(self.single_object_plot) + # assert isinstance(self.ui, ObjectUI) # self.ui.name_entry.returnPressed.connect(self.on_name_activate) # self.ui.offset_button.clicked.connect(self.on_offset_button_click) @@ -326,6 +331,14 @@ class FlatCAMObj(QtCore.QObject): self.clear() return True + def single_object_plot(self): + def plot_task(): + with self.app.proc_container.new('%s...' % _("Plotting")): + self.plot() + self.app.object_changed.emit(self) + + self.app.worker_task.emit({'fcn': plot_task, 'params': []}) + def serialize(self): """ Returns a representation of the object as a dictionary so @@ -600,6 +613,16 @@ class FlatCAMGerber(FlatCAMObj, Gerber): 'Advanced' )) + if self.app.defaults["gerber_buffering"] == 'no': + self.ui.create_buffer_button.show() + try: + self.ui.create_buffer_button.clicked.disconnect(self.on_generate_buffer) + except TypeError: + pass + self.ui.create_buffer_button.clicked.connect(self.on_generate_buffer) + else: + self.ui.create_buffer_button.hide() + # add the shapes storage for marking apertures for ap_code in self.apertures: self.mark_shapes[ap_code] = self.app.plotcanvas.new_shape_collection(layers=2) @@ -775,6 +798,21 @@ class FlatCAMGerber(FlatCAMObj, Gerber): except (TypeError, AttributeError): pass + def on_generate_buffer(self): + self.app.inform.emit('[WARNING_NOTCL] %s...' % _("Buffering solid geometry")) + + def buffer_task(): + with self.app.proc_container.new('%s...' % _("Buffering")): + if isinstance(self.solid_geometry, list): + self.solid_geometry = MultiPolygon(self.solid_geometry) + + self.solid_geometry = self.solid_geometry.buffer(0.0000001) + self.solid_geometry = self.solid_geometry.buffer(-0.0000001) + self.app.inform.emit('[success] %s.' % _("Done")) + self.plot_single_object.emit() + + self.app.worker_task.emit({'fcn': buffer_task, 'params': []}) + def on_generatenoncopper_button_click(self, *args): self.app.report_usage("gerber_on_generatenoncopper_button") diff --git a/README.md b/README.md index 0ff4e1eb..a3908f14 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,8 @@ 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) +- some fixes in Paint Tool when done over the Gerber objects in case that the progressive plotting is selected +- some fixes in Gerber isolation in case that the progressive plotting is selected; added a 'Buffer solid geometry' button shown only when progressive plotting for Gerber object is selected. It will buffer the entire geometry of the object and plot it, in a threaded way. 8.09.2019 diff --git a/flatcamGUI/ObjectUI.py b/flatcamGUI/ObjectUI.py index c9c6d598..22a2429f 100644 --- a/flatcamGUI/ObjectUI.py +++ b/flatcamGUI/ObjectUI.py @@ -381,16 +381,25 @@ class GerberObjectUI(ObjectUI): ) grid1.addWidget(self.gen_iso_label, 6, 0, 1, 3) + self.create_buffer_button = QtWidgets.QPushButton(_('Buffer Solid Geometry')) + self.create_buffer_button.setToolTip( + _("This button is shown only when the Gerber file\n" + "is loaded without buffering.\n" + "Clicking this will create the buffered geometry\n" + "required for isolation.") + ) + grid1.addWidget(self.create_buffer_button, 7, 0, 1, 3) + self.generate_iso_button = QtWidgets.QPushButton(_('FULL Geo')) self.generate_iso_button.setToolTip( _("Create the Geometry Object\n" "for isolation routing. It contains both\n" "the interiors and exteriors geometry.") ) - grid1.addWidget(self.generate_iso_button, 7, 0) + grid1.addWidget(self.generate_iso_button, 8, 0) hlay_1 = QtWidgets.QHBoxLayout() - grid1.addLayout(hlay_1, 7, 1, 1, 2) + grid1.addLayout(hlay_1, 8, 1, 1, 2) self.generate_ext_iso_button = QtWidgets.QPushButton(_('Ext Geo')) self.generate_ext_iso_button.setToolTip( @@ -420,7 +429,7 @@ class GerberObjectUI(ObjectUI): self.ois_iso = OptionalInputSection(self.follow_cb, [self.generate_int_iso_button, self.generate_ext_iso_button], logic=False) - grid1.addWidget(QtWidgets.QLabel(''), 8, 0) + grid1.addWidget(QtWidgets.QLabel(''), 9, 0) # ########################################### # ########## NEW GRID ####################### diff --git a/flatcamTools/ToolPaint.py b/flatcamTools/ToolPaint.py index da2beca8..b0b5c9e9 100644 --- a/flatcamTools/ToolPaint.py +++ b/flatcamTools/ToolPaint.py @@ -1190,6 +1190,23 @@ class ToolPaint(FlatCAMTool, Gerber): # Which polygon. # poly = find_polygon(self.solid_geometry, inside_pt) + if isinstance(obj, FlatCAMGerber): + if self.app.defaults["gerber_buffering"] == 'no': + self.app.inform.emit('%s %s' % + (_("Paint Tool. Normal painting polygon task started."), + _("Buffering geometry..."))) + else: + self.app.inform.emit(_("Paint Tool. Normal painting polygon task started.")) + else: + self.app.inform.emit(_("Paint Tool. Normal painting polygon task started.")) + + if isinstance(obj, FlatCAMGerber): + if self.app.defaults["tools_paint_plotting"] == 'progressive': + if isinstance(obj.solid_geometry, list): + obj.solid_geometry = MultiPolygon(obj.solid_geometry).buffer(0) + else: + obj.solid_geometry = obj.solid_geometry.buffer(0) + poly = self.find_polygon(point=inside_pt, geoset=obj.solid_geometry) paint_method = method if method is None else self.paintmethod_combo.get_value() @@ -1209,6 +1226,8 @@ class ToolPaint(FlatCAMTool, Gerber): # determine if to use the progressive plotting if self.app.defaults["tools_paint_plotting"] == 'progressive': prog_plot = True + else: + prog_plot = False # No polygon? if poly is None: @@ -1477,6 +1496,8 @@ class ToolPaint(FlatCAMTool, Gerber): # determine if to use the progressive plotting if self.app.defaults["tools_paint_plotting"] == 'progressive': prog_plot = True + else: + prog_plot = False proc = self.app.proc_container.new(_("Painting polygons...")) name = outname if outname is not None else self.obj_name + "_paint" @@ -1557,7 +1578,15 @@ class ToolPaint(FlatCAMTool, Gerber): # "Initializer expected a FlatCAMGeometry, got %s" % type(geo_obj) log.debug("Paint Tool. Normal painting all task started.") - app_obj.inform.emit(_("Paint Tool. Normal painting all task started.")) + if isinstance(obj, FlatCAMGerber): + if app_obj.defaults["gerber_buffering"] == 'no': + app_obj.inform.emit('%s %s' % + (_("Paint Tool. Normal painting all task started."), + _("Buffering geometry..."))) + else: + app_obj.inform.emit(_("Paint Tool. Normal painting all task started.")) + else: + app_obj.inform.emit(_("Paint Tool. Normal painting all task started.")) tool_dia = None if order == 'fwd': @@ -1567,6 +1596,13 @@ class ToolPaint(FlatCAMTool, Gerber): else: pass + if isinstance(obj, FlatCAMGerber): + if self.app.defaults["tools_paint_plotting"] == 'progressive': + if isinstance(obj.solid_geometry, list): + obj.solid_geometry = MultiPolygon(obj.solid_geometry).buffer(0) + else: + obj.solid_geometry = obj.solid_geometry.buffer(0) + try: a, b, c, d = obj.bounds() geo_obj.options['xmin'] = a @@ -1717,7 +1753,15 @@ class ToolPaint(FlatCAMTool, Gerber): "Initializer expected a FlatCAMGeometry, got %s" % type(geo_obj) log.debug("Paint Tool. Rest machining painting all task started.") - app_obj.inform.emit(_("Paint Tool. Rest machining painting all task started.")) + if isinstance(obj, FlatCAMGerber): + if app_obj.defaults["gerber_buffering"] == 'no': + app_obj.inform.emit('%s %s' % + (_("Paint Tool. Rest machining painting all task started."), + _("Buffering geometry..."))) + else: + app_obj.inform.emit(_("Paint Tool. Rest machining painting all task started.")) + else: + app_obj.inform.emit(_("Paint Tool. Rest machining painting all task started.")) tool_dia = None sorted_tools.sort(reverse=True) @@ -1726,6 +1770,13 @@ class ToolPaint(FlatCAMTool, Gerber): current_uid = int(1) geo_obj.solid_geometry = [] + if isinstance(obj, FlatCAMGerber): + if self.app.defaults["tools_paint_plotting"] == 'progressive': + if isinstance(obj.solid_geometry, list): + obj.solid_geometry = MultiPolygon(obj.solid_geometry).buffer(0) + else: + obj.solid_geometry = obj.solid_geometry.buffer(0) + try: a, b, c, d = obj.bounds() geo_obj.options['xmin'] = a @@ -1915,6 +1966,8 @@ class ToolPaint(FlatCAMTool, Gerber): # determine if to use the progressive plotting if self.app.defaults["tools_paint_plotting"] == 'progressive': prog_plot = True + else: + prog_plot = False proc = self.app.proc_container.new(_("Painting polygons...")) name = outname if outname is not None else self.obj_name + "_paint" @@ -1982,7 +2035,15 @@ class ToolPaint(FlatCAMTool, Gerber): # "Initializer expected a FlatCAMGeometry, got %s" % type(geo_obj) log.debug("Paint Tool. Normal painting area task started.") - app_obj.inform.emit(_("Paint Tool. Normal painting area task started.")) + if isinstance(obj, FlatCAMGerber): + if app_obj.defaults["gerber_buffering"] == 'no': + app_obj.inform.emit('%s %s' % + (_("Paint Tool. Normal painting area task started."), + _("Buffering geometry..."))) + else: + app_obj.inform.emit(_("Paint Tool. Normal painting area task started.")) + else: + app_obj.inform.emit(_("Paint Tool. Normal painting area task started.")) tool_dia = None if order == 'fwd': @@ -1993,19 +2054,16 @@ class ToolPaint(FlatCAMTool, Gerber): pass # 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) + if isinstance(obj, FlatCAMGerber): + if self.app.defaults["tools_paint_plotting"] == 'progressive': + if isinstance(target_geo, list): + target_geo = MultiPolygon(target_geo).buffer(0) + else: + target_geo = 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) + geo_to_paint = target_geo.intersection(sel_obj) painted_area = recurse(geo_to_paint) @@ -2158,7 +2216,15 @@ class ToolPaint(FlatCAMTool, Gerber): "Initializer expected a FlatCAMGeometry, got %s" % type(geo_obj) log.debug("Paint Tool. Rest machining painting area task started.") - app_obj.inform.emit(_("Paint Tool. Rest machining painting area task started.")) + if isinstance(obj, FlatCAMGerber): + if app_obj.defaults["gerber_buffering"] == 'no': + app_obj.inform.emit('%s %s' % + (_("Paint Tool. Rest machining painting area task started."), + _("Buffering geometry..."))) + else: + app_obj.inform.emit(_("Paint Tool. Rest machining painting area task started.")) + else: + app_obj.inform.emit(_("Paint Tool. Rest machining painting area task started.")) tool_dia = None sorted_tools.sort(reverse=True) @@ -2168,19 +2234,16 @@ class ToolPaint(FlatCAMTool, Gerber): 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) + if isinstance(obj, FlatCAMGerber): + if self.app.defaults["tools_paint_plotting"] == 'progressive': + if isinstance(target_geo, list): + target_geo = MultiPolygon(target_geo).buffer(0) + else: + target_geo = 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) + geo_to_paint = target_geo.intersection(sel_obj) painted_area = recurse(geo_to_paint)