- added Repetier postprocessor file

- removed "added ability to regenerate objects (it's actually deletion followed by recreation)" because of the way Python pass parameters to functions by reference instead of copy
This commit is contained in:
Marius Stanciu
2019-02-22 16:54:58 +02:00
committed by Marius
parent 60b08dfec5
commit 7272b46dd9
7 changed files with 367 additions and 175 deletions

View File

@@ -352,7 +352,7 @@ class SolderPaste(FlatCAMTool):
# self.gcode_frame.setDisabled(True)
# self.save_gcode_frame.setDisabled(True)
self.tools = {}
self.tooltable_tools = {}
self.tooluid = 0
self.options = LoudDict()
@@ -363,8 +363,8 @@ class SolderPaste(FlatCAMTool):
## Signals
self.addtool_btn.clicked.connect(self.on_tool_add)
self.deltool_btn.clicked.connect(self.on_tool_delete)
self.soldergeo_btn.clicked.connect(self.on_create_geo)
self.solder_gcode_btn.clicked.connect(self.on_create_gcode)
self.soldergeo_btn.clicked.connect(self.on_create_geo_click)
self.solder_gcode_btn.clicked.connect(self.on_create_gcode_click)
self.solder_gcode_view_btn.clicked.connect(self.on_view_gcode)
self.solder_gcode_save_btn.clicked.connect(self.on_save_gcode)
@@ -424,10 +424,10 @@ class SolderPaste(FlatCAMTool):
self.tooluid = 0
self.tools.clear()
self.tooltable_tools.clear()
for tool_dia in dias:
self.tooluid += 1
self.tools.update({
self.tooltable_tools.update({
int(self.tooluid): {
'tooldia': float('%.4f' % tool_dia),
'data': deepcopy(self.options),
@@ -455,7 +455,7 @@ class SolderPaste(FlatCAMTool):
self.units = self.app.general_options_form.general_app_group.units_radio.get_value().upper()
sorted_tools = []
for k, v in self.tools.items():
for k, v in self.tooltable_tools.items():
sorted_tools.append(float('%.4f' % float(v['tooldia'])))
sorted_tools.sort(reverse=True)
@@ -464,7 +464,7 @@ class SolderPaste(FlatCAMTool):
tool_id = 0
for tool_sorted in sorted_tools:
for tooluid_key, tooluid_value in self.tools.items():
for tooluid_key, tooluid_value in self.tooltable_tools.items():
if float('%.4f' % tooluid_value['tooldia']) == tool_sorted:
tool_id += 1
id = QtWidgets.QTableWidgetItem('%d' % int(tool_id))
@@ -543,7 +543,7 @@ class SolderPaste(FlatCAMTool):
# update the form
try:
# set the form with data from the newly selected tool
for tooluid_key, tooluid_value in self.tools.items():
for tooluid_key, tooluid_value in self.tooltable_tools.items():
if int(tooluid_key) == tooluid:
self.set_form(deepcopy(tooluid_value['data']))
except Exception as e:
@@ -601,7 +601,7 @@ class SolderPaste(FlatCAMTool):
current_row = self.tools_table.currentRow()
uid = tooluid if tooluid else int(self.tools_table.item(current_row, 2).text())
for key in self.form_fields:
self.tools[uid]['data'].update({
self.tooltable_tools[uid]['data'].update({
key: self.form_fields[key].get_value()
})
@@ -618,7 +618,7 @@ class SolderPaste(FlatCAMTool):
"""
Will read all the parameters of Solder Paste Tool from the provided val parameter and update the UI
:param val: dictionary with values to store in the form
:param_type: dictionary
param_type: dictionary
:return:
"""
@@ -656,9 +656,9 @@ class SolderPaste(FlatCAMTool):
self.app.inform.emit("[WARNING_NOTCL] Please enter a tool diameter with non-zero value, in Float format.")
return
# construct a list of all 'tooluid' in the self.tools
# construct a list of all 'tooluid' in the self.tooltable_tools
tool_uid_list = []
for tooluid_key in self.tools:
for tooluid_key in self.tooltable_tools:
tool_uid_item = int(tooluid_key)
tool_uid_list.append(tool_uid_item)
@@ -670,7 +670,7 @@ class SolderPaste(FlatCAMTool):
self.tooluid = int(max_uid + 1)
tool_dias = []
for k, v in self.tools.items():
for k, v in self.tooltable_tools.items():
for tool_v in v.keys():
if tool_v == 'tooldia':
tool_dias.append(float('%.4f' % v[tool_v]))
@@ -683,7 +683,7 @@ class SolderPaste(FlatCAMTool):
else:
if muted is None:
self.app.inform.emit("[success] New Nozzle tool added to Tool Table.")
self.tools.update({
self.tooltable_tools.update({
int(self.tooluid): {
'tooldia': float('%.4f' % tool_dia),
'data': deepcopy(self.options),
@@ -697,7 +697,7 @@ class SolderPaste(FlatCAMTool):
self.ui_disconnect()
tool_dias = []
for k, v in self.tools.items():
for k, v in self.tooltable_tools.items():
for tool_v in v.keys():
if tool_v == 'tooldia':
tool_dias.append(float('%.4f' % v[tool_v]))
@@ -719,13 +719,13 @@ class SolderPaste(FlatCAMTool):
# identify the tool that was edited and get it's tooluid
if new_tool_dia not in tool_dias:
self.tools[tooluid]['tooldia'] = new_tool_dia
self.tooltable_tools[tooluid]['tooldia'] = new_tool_dia
self.app.inform.emit("[success] Nozzle tool from Tool Table was edited.")
self.build_ui()
return
else:
# identify the old tool_dia and restore the text in tool table
for k, v in self.tools.items():
for k, v in self.tooltable_tools.items():
if k == tooluid:
old_tool_dia = v['tooldia']
break
@@ -739,7 +739,7 @@ class SolderPaste(FlatCAMTool):
deleted_tools_list = []
if all:
self.tools.clear()
self.tooltable_tools.clear()
self.build_ui()
return
@@ -752,7 +752,7 @@ class SolderPaste(FlatCAMTool):
deleted_tools_list.append(rows_to_delete)
for t in deleted_tools_list:
self.tools.pop(t, None)
self.tooltable_tools.pop(t, None)
self.build_ui()
return
@@ -766,7 +766,7 @@ class SolderPaste(FlatCAMTool):
deleted_tools_list.append(tooluid_del)
for t in deleted_tools_list:
self.tools.pop(t, None)
self.tooltable_tools.pop(t, None)
except AttributeError:
self.app.inform.emit("[WARNING_NOTCL] Delete failed. Select a Nozzle tool to delete.")
@@ -795,31 +795,34 @@ class SolderPaste(FlatCAMTool):
def distance(pt1, pt2):
return sqrt((pt1[0] - pt2[0]) ** 2 + (pt1[1] - pt2[1]) ** 2)
def on_create_geo(self):
proc = self.app.proc_container.new("Creating Solder Paste dispensing geometry.")
def on_create_geo_click(self, signal):
name = self.obj_combo.currentText()
if name == '':
self.app.inform.emit("[WARNING_NOTCL] No SolderPaste mask Gerber object loaded.")
return
obj = self.app.collection.get_by_name(name)
# update the self.options
self.read_form_to_options()
obj = self.app.collection.get_by_name(name)
self.on_create_geo(name=name, work_object=obj)
if type(obj.solid_geometry) is not list and type(obj.solid_geometry) is not MultiPolygon:
obj.solid_geometry = [obj.solid_geometry]
def on_create_geo(self, name, work_object):
proc = self.app.proc_container.new("Creating Solder Paste dispensing geometry.")
obj = work_object
# Sort tools in descending order
sorted_tools = []
for k, v in self.tools.items():
for k, v in self.tooltable_tools.items():
# make sure that the tools diameter is more than zero and not zero
if float(v['tooldia']) > 0:
sorted_tools.append(float('%.4f' % float(v['tooldia'])))
sorted_tools.sort(reverse=True)
if not sorted_tools:
self.app.inform.emit("[WARNING_NOTCL] No Nozzle tools in the tool table.")
return 'fail'
def geo_init(geo_obj, app_obj):
geo_obj.options.update(self.options)
geo_obj.solid_geometry = []
@@ -830,7 +833,6 @@ class SolderPaste(FlatCAMTool):
geo_obj.special_group = 'solder_paste_tool'
def solder_line(p, offset):
xmin, ymin, xmax, ymax = p.bounds
min = [xmin, ymin]
@@ -875,21 +877,16 @@ class SolderPaste(FlatCAMTool):
rest_geo = []
tooluid = 1
if not sorted_tools:
self.app.inform.emit("[WARNING_NOTCL] No Nozzle tools in the tool table.")
return 'fail'
for tool in sorted_tools:
offset = tool / 2
for uid, v in self.tools.items():
for uid, v in self.tooltable_tools.items():
if float('%.4f' % float(v['tooldia'])) == tool:
tooluid = int(uid)
break
geo_obj.tools[tooluid] = {}
geo_obj.tools[tooluid]['tooldia'] = tool
geo_obj.tools[tooluid]['data'] = self.tools[tooluid]['data']
geo_obj.tools[tooluid]['data'] = deepcopy(self.tooltable_tools[tooluid]['data'])
geo_obj.tools[tooluid]['solid_geometry'] = []
geo_obj.tools[tooluid]['offset'] = 'Path'
geo_obj.tools[tooluid]['offset_value'] = 0.0
@@ -933,7 +930,7 @@ class SolderPaste(FlatCAMTool):
def job_thread(app_obj):
try:
app_obj.new_object("geometry", name + "_solderpaste", geo_init, overwrite=True)
app_obj.new_object("geometry", name + "_solderpaste", geo_init)
except Exception as e:
proc.done()
traceback.print_stack()
@@ -945,9 +942,126 @@ class SolderPaste(FlatCAMTool):
self.app.collection.promise(name)
# Background
self.app.worker_task.emit({'fcn': job_thread, 'params': [self.app]})
self.app.worker_task.emit({'fcn': job_thread, 'params': [self.app.paste_tool]})
# self.app.ui.notebook.setCurrentWidget(self.app.ui.project_tab)
def on_create_gcode_click(self, signal):
name = self.geo_obj_combo.currentText()
obj = self.app.collection.get_by_name(name)
if obj.special_group != 'solder_paste_tool':
self.app.inform.emit("[WARNING_NOTCL]This Geometry can't be processed. NOT a solder_paste_tool geometry.")
return 'fail'
a = 0
for tooluid_key in obj.tools:
if obj.tools[tooluid_key]['solid_geometry'] is None:
a += 1
if a == len(obj.tools):
self.app.inform.emit('[ERROR_NOTCL]Cancelled. Empty file, it has no geometry...')
return 'fail'
# use the name of the first tool selected in self.geo_tools_table which has the diameter passed as tool_dia
originar_name = obj.options['name'].rpartition('_')[0]
outname = "%s_%s" % (originar_name, 'cnc_solderpaste')
self.on_create_gcode(name=outname, workobject=obj)
def on_create_gcode(self, name, workobject, use_thread=True):
"""
Creates a multi-tool CNCJob out of this Geometry object.
:return: None
"""
obj = workobject
try:
xmin = obj.options['xmin']
ymin = obj.options['ymin']
xmax = obj.options['xmax']
ymax = obj.options['ymax']
except Exception as e:
log.debug("FlatCAMObj.FlatCAMGeometry.mtool_gen_cncjob() --> %s\n" % str(e))
msg = "[ERROR] An internal error has ocurred. See shell.\n"
msg += 'FlatCAMObj.FlatCAMGeometry.mtool_gen_cncjob() --> %s' % str(e)
msg += traceback.format_exc()
self.app.inform.emit(msg)
return
# Object initialization function for app.new_object()
# RUNNING ON SEPARATE THREAD!
def job_init(job_obj, app_obj):
assert isinstance(job_obj, FlatCAMCNCjob), \
"Initializer expected a FlatCAMCNCjob, got %s" % type(job_obj)
tool_cnc_dict = {}
# this turn on the FlatCAMCNCJob plot for multiple tools
job_obj.multitool = True
job_obj.multigeo = True
job_obj.cnc_tools.clear()
job_obj.special_group = 'solder_paste_tool'
job_obj.options['xmin'] = xmin
job_obj.options['ymin'] = ymin
job_obj.options['xmax'] = xmax
job_obj.options['ymax'] = ymax
for tooluid_key, tooluid_value in obj.tools.items():
app_obj.progress.emit(20)
# find the tool_dia associated with the tooluid_key
tool_dia = tooluid_value['tooldia']
tool_cnc_dict = deepcopy(tooluid_value)
job_obj.coords_decimals = self.app.defaults["cncjob_coords_decimals"]
job_obj.fr_decimals = self.app.defaults["cncjob_fr_decimals"]
job_obj.tool = int(tooluid_key)
# Propagate options
job_obj.options["tooldia"] = tool_dia
job_obj.options['tool_dia'] = tool_dia
### CREATE GCODE ###
res = job_obj.generate_gcode_from_solderpaste_geo(**tooluid_value)
if res == 'fail':
log.debug("FlatCAMGeometry.mtool_gen_cncjob() --> generate_from_geometry2() failed")
return 'fail'
else:
tool_cnc_dict['gcode'] = res
### PARSE GCODE ###
tool_cnc_dict['gcode_parsed'] = job_obj.gcode_parse()
# TODO this serve for bounding box creation only; should be optimized
tool_cnc_dict['solid_geometry'] = cascaded_union([geo['geom'] for geo in tool_cnc_dict['gcode_parsed']])
# tell gcode_parse from which point to start drawing the lines depending on what kind of
# object is the source of gcode
job_obj.toolchange_xy_type = "geometry"
app_obj.progress.emit(80)
job_obj.cnc_tools.update({
tooluid_key: deepcopy(tool_cnc_dict)
})
tool_cnc_dict.clear()
if use_thread:
# To be run in separate thread
def job_thread(app_obj):
with self.app.proc_container.new("Generating CNC Code"):
if app_obj.new_object("cncjob", name, job_init) != 'fail':
app_obj.inform.emit("[success]ToolSolderPaste CNCjob created: %s" % name)
app_obj.progress.emit(100)
# Create a promise with the name
self.app.collection.promise(name)
# Send to worker
self.app.worker_task.emit({'fcn': job_thread, 'params': [self.app]})
else:
self.app.new_object("cncjob", name, job_init)
def on_view_gcode(self):
time_str = "{:%A, %d %B %Y at %H:%M}".format(datetime.now())
@@ -1065,122 +1179,6 @@ class SolderPaste(FlatCAMTool):
self.app.file_saved.emit("gcode", filename)
self.app.inform.emit("[success] Solder paste dispenser GCode file saved to: %s" % filename)
def on_create_gcode(self, signal, use_thread=True):
"""
Creates a multi-tool CNCJob out of this Geometry object.
:return: None
"""
name = self.geo_obj_combo.currentText()
obj = self.app.collection.get_by_name(name)
if obj.special_group != 'solder_paste_tool':
self.app.inform.emit("[WARNING_NOTCL]This Geometry can't be processed. NOT a solder_paste_tool geometry.")
return
offset_str = ''
multitool_gcode = ''
# use the name of the first tool selected in self.geo_tools_table which has the diameter passed as tool_dia
originar_name = obj.options['name'].rpartition('_')[0]
outname = "%s_%s" % (originar_name, '_cnc_solderpaste')
try:
xmin = obj.options['xmin']
ymin = obj.options['ymin']
xmax = obj.options['xmax']
ymax = obj.options['ymax']
except Exception as e:
log.debug("FlatCAMObj.FlatCAMGeometry.mtool_gen_cncjob() --> %s\n" % str(e))
msg = "[ERROR] An internal error has ocurred. See shell.\n"
msg += 'FlatCAMObj.FlatCAMGeometry.mtool_gen_cncjob() --> %s' % str(e)
msg += traceback.format_exc()
self.app.inform.emit(msg)
return
# Object initialization function for app.new_object()
# RUNNING ON SEPARATE THREAD!
def job_init(job_obj, app_obj):
assert isinstance(job_obj, FlatCAMCNCjob), \
"Initializer expected a FlatCAMCNCjob, got %s" % type(job_obj)
tool_cnc_dict = {}
# this turn on the FlatCAMCNCJob plot for multiple tools
job_obj.multitool = True
job_obj.multigeo = True
job_obj.cnc_tools.clear()
job_obj.special_group = 'solder_paste_tool'
job_obj.options['xmin'] = xmin
job_obj.options['ymin'] = ymin
job_obj.options['xmax'] = xmax
job_obj.options['ymax'] = ymax
a = 0
for tooluid_key in obj.tools:
if obj.tools[tooluid_key]['solid_geometry'] is None:
a += 1
if a == len(obj.tools):
self.app.inform.emit('[ERROR_NOTCL]Cancelled. Empty file, it has no geometry...')
return 'fail'
for tooluid_key, tooluid_value in obj.tools.items():
app_obj.progress.emit(20)
# find the tool_dia associated with the tooluid_key
tool_dia = tooluid_value['tooldia']
tool_cnc_dict = deepcopy(tooluid_value)
job_obj.coords_decimals = self.app.defaults["cncjob_coords_decimals"]
job_obj.fr_decimals = self.app.defaults["cncjob_fr_decimals"]
job_obj.tool = int(tooluid_key)
# Propagate options
job_obj.options["tooldia"] = tool_dia
job_obj.options['tool_dia'] = tool_dia
### CREATE GCODE ###
res = job_obj.generate_gcode_from_solderpaste_geo(**tooluid_value)
if res == 'fail':
log.debug("FlatCAMGeometry.mtool_gen_cncjob() --> generate_from_geometry2() failed")
return 'fail'
else:
tool_cnc_dict['gcode'] = res
### PARSE GCODE ###
tool_cnc_dict['gcode_parsed'] = job_obj.gcode_parse()
# TODO this serve for bounding box creation only; should be optimized
tool_cnc_dict['solid_geometry'] = cascaded_union([geo['geom'] for geo in tool_cnc_dict['gcode_parsed']])
# tell gcode_parse from which point to start drawing the lines depending on what kind of
# object is the source of gcode
job_obj.toolchange_xy_type = "geometry"
app_obj.progress.emit(80)
job_obj.cnc_tools.update({
tooluid_key: deepcopy(tool_cnc_dict)
})
tool_cnc_dict.clear()
if use_thread:
# To be run in separate thread
def job_thread(app_obj):
with self.app.proc_container.new("Generating CNC Code"):
if app_obj.new_object("cncjob", outname, job_init, overwrite=True) != 'fail':
app_obj.inform.emit("[success]ToolSolderPaste CNCjob created: %s" % outname)
app_obj.progress.emit(100)
# Create a promise with the name
self.app.collection.promise(outname)
# Send to worker
self.app.worker_task.emit({'fcn': job_thread, 'params': [self.app]})
else:
self.app.new_object("cncjob", outname, job_init, overwrite=True)
def reset_fields(self):
self.obj_combo.setRootModelIndex(self.app.collection.index(0, 0, QtCore.QModelIndex()))
self.geo_obj_combo.setRootModelIndex(self.app.collection.index(2, 0, QtCore.QModelIndex()))