- remade the Paint Tool - single polygon painting; now it can single paint a list of polygons that are clicked onto (right click will start the actual painting)
This commit is contained in:
parent
07fb663e7b
commit
c025d6ad79
@ -623,7 +623,7 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
|
||||
# Mouse events
|
||||
self.mr = None
|
||||
|
||||
# dict to store the polygons selected for isolation; key is the shape added to be ploted and value is the poly
|
||||
# dict to store the polygons selected for isolation; key is the shape added to be plotted and value is the poly
|
||||
self.poly_dict = dict()
|
||||
|
||||
# store the status of grid snapping
|
||||
@ -1045,7 +1045,7 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
|
||||
if iso_scope == 'all':
|
||||
self.isolate(iso_type=iso_type)
|
||||
else:
|
||||
# disengage the grid snapping since it will be hard to find the drills on grid
|
||||
# disengage the grid snapping since it may be hard to click on polygons with grid snapping on
|
||||
if self.app.ui.grid_snap_btn.isChecked():
|
||||
self.grid_status_memory = True
|
||||
self.app.ui.grid_snap_btn.trigger()
|
||||
@ -1059,7 +1059,7 @@ class FlatCAMGerber(FlatCAMObj, Gerber):
|
||||
else:
|
||||
self.app.plotcanvas.graph_event_disconnect(self.app.mr)
|
||||
|
||||
self.app.inform.emit('[WARNING_NOTCL] %s' % _("Click on polygon to isolate it."))
|
||||
self.app.inform.emit('[WARNING_NOTCL] %s' % _("Click on a polygon to isolate it."))
|
||||
|
||||
def on_mouse_click_release(self, event):
|
||||
if self.app.is_legacy is False:
|
||||
|
@ -18,6 +18,7 @@ CAD program, and create G-Code for Isolation routing.
|
||||
- clicking to add a polygon when doing Single type isolation will add a blue shape marking the selected polygon, second click will remove that shape
|
||||
- fixed bugs in Paint Tool when painting single polygon
|
||||
- in Gerber isolation added the option to selectively isolate only certain polygons - made it to work for Legacy(2D) graphic mode
|
||||
- remade the Paint Tool - single polygon painting; now it can single paint a list of polygons that are clicked onto (right click will start the actual painting)
|
||||
|
||||
23.11.2019
|
||||
|
||||
|
@ -395,6 +395,12 @@ class ToolPaint(FlatCAMTool, Gerber):
|
||||
|
||||
self.sel_rect = []
|
||||
|
||||
# store here if the grid snapping is active
|
||||
self.grid_status_memory = False
|
||||
|
||||
# dict to store the polygons selected for painting; key is the shape added to be plotted and value is the poly
|
||||
self.poly_dict = dict()
|
||||
|
||||
# store here the default data for Geometry Data
|
||||
self.default_data = {}
|
||||
self.default_data.update({
|
||||
@ -1017,36 +1023,16 @@ class ToolPaint(FlatCAMTool, Gerber):
|
||||
contour=self.contour)
|
||||
|
||||
elif self.select_method == "single":
|
||||
self.app.inform.emit('[WARNING_NOTCL] %s' %
|
||||
_("Click inside the desired polygon."))
|
||||
self.app.inform.emit('[WARNING_NOTCL] %s' % _("Click on a polygon to paint it."))
|
||||
|
||||
# use the first tool in the tool table; get the diameter
|
||||
# tooldia = float('%.4f' % float(self.tools_table.item(0, 1).text()))
|
||||
|
||||
# To be called after clicking on the plot.
|
||||
def doit(event):
|
||||
# do paint single only for left mouse clicks
|
||||
if event.button == 1:
|
||||
self.app.inform.emit(_("Painting polygon..."))
|
||||
if self.app.is_legacy is False:
|
||||
self.app.plotcanvas.graph_event_disconnect('mouse_press', doit)
|
||||
# disengage the grid snapping since it may be hard to click on polygons with grid snapping on
|
||||
if self.app.ui.grid_snap_btn.isChecked():
|
||||
self.grid_status_memory = True
|
||||
self.app.ui.grid_snap_btn.trigger()
|
||||
else:
|
||||
self.app.plotcanvas.graph_event_disconnect(self.mp)
|
||||
self.grid_status_memory = False
|
||||
|
||||
pos = self.app.plotcanvas.translate_coords(event.pos)
|
||||
if self.app.grid_status() == True:
|
||||
pos = self.app.geo_editor.snap(pos[0], pos[1])
|
||||
|
||||
self.paint_poly(self.paint_obj,
|
||||
inside_pt=[pos[0], pos[1]],
|
||||
tooldia=self.tooldia_list,
|
||||
overlap=self.overlap,
|
||||
connect=self.connect,
|
||||
contour=self.contour)
|
||||
self.app.mp = self.app.plotcanvas.graph_event_connect('mouse_press',
|
||||
self.app.on_mouse_click_over_plot)
|
||||
self.app.mr = self.app.plotcanvas.graph_event_connect('mouse_release',
|
||||
self.app.on_mouse_click_release_over_plot)
|
||||
self.mr = self.app.plotcanvas.graph_event_connect('mouse_release', self.on_single_poly_mouse_release)
|
||||
|
||||
if self.app.is_legacy is False:
|
||||
self.app.plotcanvas.graph_event_disconnect('mouse_release', self.app.on_mouse_click_release_over_plot)
|
||||
@ -1055,11 +1041,8 @@ class ToolPaint(FlatCAMTool, Gerber):
|
||||
self.app.plotcanvas.graph_event_disconnect(self.app.mr)
|
||||
self.app.plotcanvas.graph_event_disconnect(self.app.mp)
|
||||
|
||||
self.mp = self.app.plotcanvas.graph_event_connect('mouse_press', doit)
|
||||
|
||||
elif self.select_method == "area":
|
||||
self.app.inform.emit('[WARNING_NOTCL] %s' %
|
||||
_("Click the start point of the paint area."))
|
||||
self.app.inform.emit('[WARNING_NOTCL] %s' % _("Click the start point of the paint area."))
|
||||
|
||||
if self.app.is_legacy is False:
|
||||
self.app.plotcanvas.graph_event_disconnect('mouse_press', self.app.on_mouse_click_over_plot)
|
||||
@ -1072,7 +1055,6 @@ class ToolPaint(FlatCAMTool, Gerber):
|
||||
|
||||
self.mr = self.app.plotcanvas.graph_event_connect('mouse_release', self.on_mouse_release)
|
||||
self.mm = self.app.plotcanvas.graph_event_connect('mouse_move', self.on_mouse_move)
|
||||
|
||||
elif self.select_method == 'ref':
|
||||
self.bound_obj_name = self.box_combo.currentText()
|
||||
# Get source object.
|
||||
@ -1092,6 +1074,91 @@ class ToolPaint(FlatCAMTool, Gerber):
|
||||
connect=self.connect,
|
||||
contour=self.contour)
|
||||
|
||||
# To be called after clicking on the plot.
|
||||
def on_single_poly_mouse_release(self, event):
|
||||
if self.app.is_legacy is False:
|
||||
event_pos = event.pos
|
||||
right_button = 2
|
||||
event_is_dragging = self.app.event_is_dragging
|
||||
else:
|
||||
event_pos = (event.xdata, event.ydata)
|
||||
right_button = 3
|
||||
event_is_dragging = self.app.ui.popMenu.mouse_is_panning
|
||||
|
||||
try:
|
||||
x = float(event_pos[0])
|
||||
y = float(event_pos[1])
|
||||
except TypeError:
|
||||
return
|
||||
|
||||
event_pos = (x, y)
|
||||
curr_pos = self.app.plotcanvas.translate_coords(event_pos)
|
||||
|
||||
# do paint single only for left mouse clicks
|
||||
if event.button == 1:
|
||||
clicked_poly = self.find_polygon(point=(curr_pos[0], curr_pos[1]), geoset=self.paint_obj.solid_geometry)
|
||||
|
||||
if clicked_poly:
|
||||
if clicked_poly not in self.poly_dict.values():
|
||||
shape_id = self.app.tool_shapes.add(tolerance=self.paint_obj.drawing_tolerance,
|
||||
layer=0,
|
||||
shape=clicked_poly,
|
||||
color=self.app.defaults['global_sel_draw_color'] + 'AF',
|
||||
face_color=self.app.defaults['global_sel_draw_color'] + 'AF',
|
||||
visible=True)
|
||||
self.poly_dict[shape_id] = clicked_poly
|
||||
self.app.inform.emit(
|
||||
'%s: %d. %s' % (_("Added polygon"),
|
||||
int(len(self.poly_dict)),
|
||||
_("Click to add next polygon or right click to start painting."))
|
||||
)
|
||||
else:
|
||||
try:
|
||||
for k, v in list(self.poly_dict.items()):
|
||||
if v == clicked_poly:
|
||||
self.app.tool_shapes.remove(k)
|
||||
self.poly_dict.pop(k)
|
||||
break
|
||||
except TypeError:
|
||||
return
|
||||
self.app.inform.emit(
|
||||
'%s. %s' % (_("Removed polygon"),
|
||||
_("Click to add/remove next polygon or right click to start painting."))
|
||||
)
|
||||
|
||||
self.app.tool_shapes.redraw()
|
||||
else:
|
||||
self.app.inform.emit(_("No polygon detected under click position."))
|
||||
|
||||
elif event.button == right_button and event_is_dragging is False:
|
||||
# restore the Grid snapping if it was active before
|
||||
if self.grid_status_memory is True:
|
||||
self.app.ui.grid_snap_btn.trigger()
|
||||
|
||||
if self.app.is_legacy is False:
|
||||
self.app.plotcanvas.graph_event_disconnect('mouse_release', self.on_single_poly_mouse_release)
|
||||
else:
|
||||
self.app.plotcanvas.graph_event_disconnect(self.mr)
|
||||
|
||||
self.app.mp = self.app.plotcanvas.graph_event_connect('mouse_press',
|
||||
self.app.on_mouse_click_over_plot)
|
||||
self.app.mr = self.app.plotcanvas.graph_event_connect('mouse_release',
|
||||
self.app.on_mouse_click_release_over_plot)
|
||||
|
||||
self.app.tool_shapes.clear(update=True)
|
||||
|
||||
if self.poly_dict:
|
||||
poly_list = deepcopy(list(self.poly_dict.values()))
|
||||
self.paint_poly(self.paint_obj,
|
||||
poly_list=poly_list,
|
||||
tooldia=self.tooldia_list,
|
||||
overlap=self.overlap,
|
||||
connect=self.connect,
|
||||
contour=self.contour)
|
||||
self.poly_dict.clear()
|
||||
else:
|
||||
self.app.inform.emit('[ERROR_NOTCL] %s' % _("List of single polygons is empty. Aborting."))
|
||||
|
||||
# To be called after clicking on the plot.
|
||||
def on_mouse_release(self, event):
|
||||
if self.app.is_legacy is False:
|
||||
@ -1229,6 +1296,7 @@ class ToolPaint(FlatCAMTool, Gerber):
|
||||
|
||||
def paint_poly(self, obj,
|
||||
inside_pt=None,
|
||||
poly_list=None,
|
||||
tooldia=None,
|
||||
overlap=None,
|
||||
order=None,
|
||||
@ -1260,19 +1328,15 @@ class ToolPaint(FlatCAMTool, Gerber):
|
||||
:return: None
|
||||
"""
|
||||
|
||||
# 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 %s' %
|
||||
(_("Paint Tool."), _("Normal painting polygon task started."),
|
||||
_("Buffering geometry...")))
|
||||
else:
|
||||
self.app.inform.emit('%s %s' %
|
||||
(_("Paint Tool."), _("Normal painting polygon task started.")))
|
||||
self.app.inform.emit('%s %s' % (_("Paint Tool."), _("Normal painting polygon task started.")))
|
||||
else:
|
||||
self.app.inform.emit('%s %s' %
|
||||
(_("Paint Tool."), _("Normal painting polygon task started.")))
|
||||
self.app.inform.emit('%s %s' % (_("Paint Tool."), _("Normal painting polygon task started.")))
|
||||
|
||||
if isinstance(obj, FlatCAMGerber):
|
||||
if self.app.defaults["tools_paint_plotting"] == 'progressive':
|
||||
@ -1281,37 +1345,29 @@ class ToolPaint(FlatCAMTool, Gerber):
|
||||
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 not None else self.paintmethod_combo.get_value()
|
||||
|
||||
if margin is not None:
|
||||
paint_margin = margin
|
||||
else:
|
||||
paint_margin = float(self.paintmargin_entry.get_value())
|
||||
|
||||
# determine if to use the progressive plotting
|
||||
if self.app.defaults["tools_paint_plotting"] == 'progressive':
|
||||
prog_plot = True
|
||||
else:
|
||||
prog_plot = False
|
||||
polygon_list = None
|
||||
if inside_pt and poly_list is None:
|
||||
polygon_list = [self.find_polygon(point=inside_pt, geoset=obj.solid_geometry)]
|
||||
elif inside_pt is None and poly_list:
|
||||
polygon_list = poly_list
|
||||
|
||||
# No polygon?
|
||||
if poly is None:
|
||||
if polygon_list is None:
|
||||
self.app.log.warning('No polygon found.')
|
||||
self.app.inform.emit('[WARNING] %s' % _('No polygon found.'))
|
||||
return
|
||||
|
||||
proc = self.app.proc_container.new(_("Painting polygon..."))
|
||||
self.app.inform.emit('%s %s: %s' %
|
||||
(_("Paint Tool."), _("Painting polygon at location"), str(inside_pt)))
|
||||
paint_method = method if method is not None else self.paintmethod_combo.get_value()
|
||||
paint_margin = float(self.paintmargin_entry.get_value()) if margin is None else margin
|
||||
# determine if to use the progressive plotting
|
||||
prog_plot = True if self.app.defaults["tools_paint_plotting"] == 'progressive' else False
|
||||
|
||||
name = outname if outname is not None else self.obj_name + "_paint"
|
||||
|
||||
over = overlap if overlap is not None else float(self.app.defaults["tools_paintoverlap"])
|
||||
conn = connect if connect is not None else self.app.defaults["tools_pathconnect"]
|
||||
cont = contour if contour is not None else self.app.defaults["tools_paintcontour"]
|
||||
order = order if order is not None else self.order_radio.get_value()
|
||||
tools_storage = self.paint_tools if tools_storage is None else tools_storage
|
||||
|
||||
sorted_tools = []
|
||||
if tooldia is not None:
|
||||
@ -1326,24 +1382,17 @@ class ToolPaint(FlatCAMTool, Gerber):
|
||||
for row in range(self.tools_table.rowCount()):
|
||||
sorted_tools.append(float(self.tools_table.item(row, 1).text()))
|
||||
|
||||
if tools_storage is not None:
|
||||
tools_storage = tools_storage
|
||||
else:
|
||||
tools_storage = self.paint_tools
|
||||
|
||||
# Initializes the new geometry object
|
||||
def gen_paintarea(geo_obj, app_obj):
|
||||
# assert isinstance(geo_obj, FlatCAMGeometry), \
|
||||
# "Initializer expected a FlatCAMGeometry, got %s" % type(geo_obj)
|
||||
# assert isinstance(app_obj, App)
|
||||
|
||||
tool_dia = None
|
||||
# sort the tools if we have an order selected in the UI
|
||||
if order == 'fwd':
|
||||
sorted_tools.sort(reverse=False)
|
||||
elif order == 'rev':
|
||||
sorted_tools.sort(reverse=True)
|
||||
else:
|
||||
pass
|
||||
|
||||
proc = self.app.proc_container.new(_("Painting polygon..."))
|
||||
|
||||
# Initializes the new geometry object
|
||||
def gen_paintarea(geo_obj, app_obj):
|
||||
geo_obj.solid_geometry = list()
|
||||
|
||||
def paint_p(polyg, tooldiameter):
|
||||
cpoly = None
|
||||
@ -1390,21 +1439,8 @@ class ToolPaint(FlatCAMTool, Gerber):
|
||||
_('Geometry could not be painted completely'))
|
||||
return None
|
||||
|
||||
try:
|
||||
a, b, c, d = poly.bounds
|
||||
geo_obj.options['xmin'] = a
|
||||
geo_obj.options['ymin'] = b
|
||||
geo_obj.options['xmax'] = c
|
||||
geo_obj.options['ymax'] = d
|
||||
except Exception as e:
|
||||
log.debug("ToolPaint.paint_poly.gen_paintarea() bounds error --> %s" % str(e))
|
||||
return
|
||||
|
||||
total_geometry = []
|
||||
current_uid = int(1)
|
||||
|
||||
geo_obj.solid_geometry = []
|
||||
|
||||
tool_dia = None
|
||||
for tool_dia in sorted_tools:
|
||||
# find the tooluid associated with the current tool_dia so we know where to add the tool solid_geometry
|
||||
for k, v in tools_storage.items():
|
||||
@ -1413,19 +1449,20 @@ class ToolPaint(FlatCAMTool, Gerber):
|
||||
break
|
||||
|
||||
try:
|
||||
poly_buf = poly.buffer(-paint_margin)
|
||||
if isinstance(poly_buf, MultiPolygon):
|
||||
cp = []
|
||||
poly_buf = [pol.buffer(-paint_margin) for pol in polygon_list]
|
||||
cp = list()
|
||||
try:
|
||||
for pp in poly_buf:
|
||||
cp.append(paint_p(pp, tooldiameter=tool_dia))
|
||||
else:
|
||||
except TypeError:
|
||||
cp = paint_p(poly_buf, tooldiameter=tool_dia)
|
||||
|
||||
if cp is not None:
|
||||
if isinstance(cp, list):
|
||||
total_geometry = list()
|
||||
if cp:
|
||||
try:
|
||||
for x in cp:
|
||||
total_geometry += list(x.get_objects())
|
||||
else:
|
||||
except TypeError:
|
||||
total_geometry = list(cp.get_objects())
|
||||
except FlatCAMApp.GracefulException:
|
||||
return "fail"
|
||||
@ -1444,36 +1481,44 @@ class ToolPaint(FlatCAMTool, Gerber):
|
||||
tools_storage[current_uid]['solid_geometry'] = deepcopy(total_geometry)
|
||||
|
||||
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
|
||||
for uid in tools_storage:
|
||||
for uid in list(tools_storage.keys()):
|
||||
# if the solid_geometry (type=list) is empty
|
||||
if not tools_storage[uid]['solid_geometry']:
|
||||
keys_to_delete.append(uid)
|
||||
|
||||
# actual delete of keys from the tools_storage dict
|
||||
for k in keys_to_delete:
|
||||
tools_storage.pop(k, None)
|
||||
tools_storage.pop(uid, None)
|
||||
|
||||
geo_obj.options["cnctooldia"] = str(tool_dia)
|
||||
# this turn on the FlatCAMCNCJob plot for multiple tools
|
||||
|
||||
# this will turn on the FlatCAMCNCJob plot for multiple tools
|
||||
geo_obj.multigeo = True
|
||||
geo_obj.multitool = True
|
||||
geo_obj.tools.clear()
|
||||
geo_obj.tools = dict(tools_storage)
|
||||
|
||||
geo_obj.solid_geometry = cascaded_union(tools_storage[current_uid]['solid_geometry'])
|
||||
|
||||
try:
|
||||
a, b, c, d = geo_obj.solid_geometry.bounds
|
||||
geo_obj.options['xmin'] = a
|
||||
geo_obj.options['ymin'] = b
|
||||
geo_obj.options['xmax'] = c
|
||||
geo_obj.options['ymax'] = d
|
||||
except Exception as e:
|
||||
log.debug("ToolPaint.paint_poly.gen_paintarea() bounds error --> %s" % str(e))
|
||||
return
|
||||
|
||||
# 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:
|
||||
if geo_obj.tools[tooluid]['solid_geometry']:
|
||||
has_solid_geo += 1
|
||||
|
||||
if has_solid_geo == 0:
|
||||
self.app.inform.emit('[ERROR] %s' %
|
||||
_("There is no Painting Geometry in the file.\n"
|
||||
@ -1481,6 +1526,7 @@ class ToolPaint(FlatCAMTool, Gerber):
|
||||
"Change the painting parameters and try again."))
|
||||
return
|
||||
|
||||
total_geometry[:] = []
|
||||
self.app.inform.emit('[success] %s' % _("Paint Single Done."))
|
||||
|
||||
# Experimental...
|
||||
|
Loading…
Reference in New Issue
Block a user