- 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:
parent
60b08dfec5
commit
7272b46dd9
|
@ -149,7 +149,7 @@ class App(QtCore.QObject):
|
|||
# Emitted by new_object() and passes the new object as argument, plot flag.
|
||||
# on_object_created() adds the object to the collection, plots on appropriate flag
|
||||
# and emits new_object_available.
|
||||
object_created = QtCore.pyqtSignal(object, bool, bool, bool)
|
||||
object_created = QtCore.pyqtSignal(object, bool, bool)
|
||||
|
||||
# Emitted when a object has been changed (like scaled, mirrored)
|
||||
object_changed = QtCore.pyqtSignal(object)
|
||||
|
@ -2298,7 +2298,7 @@ class App(QtCore.QObject):
|
|||
# Re-buid the recent items menu
|
||||
self.setup_recent_items()
|
||||
|
||||
def new_object(self, kind, name, initialize, active=True, fit=True, plot=True, autoselected=True, overwrite=False):
|
||||
def new_object(self, kind, name, initialize, active=True, fit=True, plot=True, autoselected=True):
|
||||
"""
|
||||
Creates a new specalized FlatCAMObj and attaches it to the application,
|
||||
this is, updates the GUI accordingly, any other records and plots it.
|
||||
|
@ -2325,7 +2325,6 @@ class App(QtCore.QObject):
|
|||
App.log.debug("new_object()")
|
||||
obj_plot = plot
|
||||
obj_autoselected = autoselected
|
||||
obj_overwrite = overwrite
|
||||
|
||||
t0 = time.time() # Debug
|
||||
|
||||
|
@ -2414,7 +2413,7 @@ class App(QtCore.QObject):
|
|||
|
||||
# Move the object to the main thread and let the app know that it is available.
|
||||
obj.moveToThread(QtWidgets.QApplication.instance().thread())
|
||||
self.object_created.emit(obj, obj_plot, obj_autoselected, obj_overwrite)
|
||||
self.object_created.emit(obj, obj_plot, obj_autoselected)
|
||||
|
||||
return obj
|
||||
|
||||
|
@ -2431,7 +2430,7 @@ class App(QtCore.QObject):
|
|||
|
||||
self.new_object('geometry', 'new_g', initialize, plot=False)
|
||||
|
||||
def on_object_created(self, obj, plot, autoselect, overwrite):
|
||||
def on_object_created(self, obj, plot, autoselect):
|
||||
"""
|
||||
Event callback for object creation.
|
||||
|
||||
|
@ -2442,7 +2441,7 @@ class App(QtCore.QObject):
|
|||
self.log.debug("on_object_created()")
|
||||
|
||||
# The Collection might change the name if there is a collision
|
||||
self.collection.append(obj, overwrite=overwrite)
|
||||
self.collection.append(obj)
|
||||
|
||||
# after adding the object to the collection always update the list of objects that are in the collection
|
||||
self.all_objects_list = self.collection.get_list()
|
||||
|
|
|
@ -5000,20 +5000,21 @@ class FlatCAMCNCjob(FlatCAMObj, CNCjob):
|
|||
|
||||
try:
|
||||
for key in self.cnc_tools:
|
||||
if self.cnc_tools[key]['data']['ppname_g'] == 'marlin':
|
||||
ppg = self.cnc_tools[key]['data']['ppname_g']
|
||||
if ppg == 'marlin' or ppg == 'Repetier':
|
||||
marlin = True
|
||||
break
|
||||
if self.cnc_tools[key]['data']['ppname_g'] == 'hpgl':
|
||||
if ppg == 'hpgl':
|
||||
hpgl = True
|
||||
break
|
||||
if "toolchange_probe" in self.cnc_tools[key]['data']['ppname_g'].lower():
|
||||
if "toolchange_probe" in ppg.lower():
|
||||
probe_pp = True
|
||||
break
|
||||
except Exception as e:
|
||||
log.debug("FlatCAMCNCJob.gcode_header() error: --> %s" % str(e))
|
||||
|
||||
try:
|
||||
if self.options['ppname_e'] == 'marlin':
|
||||
if self.options['ppname_e'] == 'marlin' or self.options['ppname_e'] == 'Repetier':
|
||||
marlin = True
|
||||
except Exception as e:
|
||||
log.debug("FlatCAMCNCJob.gcode_header(): --> There is no such self.option: %s" % str(e))
|
||||
|
@ -5025,7 +5026,7 @@ class FlatCAMCNCjob(FlatCAMObj, CNCjob):
|
|||
log.debug("FlatCAMCNCJob.gcode_header(): --> There is no such self.option: %s" % str(e))
|
||||
|
||||
if marlin is True:
|
||||
gcode = ';Marlin G-CODE GENERATED BY FLATCAM v%s - www.flatcam.org - Version Date: %s\n' % \
|
||||
gcode = ';Marlin(Repetier) G-CODE GENERATED BY FLATCAM v%s - www.flatcam.org - Version Date: %s\n' % \
|
||||
(str(self.app.version), str(self.app.version_date)) + '\n'
|
||||
|
||||
gcode += ';Name: ' + str(self.options['name']) + '\n'
|
||||
|
|
|
@ -642,7 +642,7 @@ class ObjectCollection(QtCore.QAbstractItemModel):
|
|||
|
||||
# return QtWidgets.QAbstractItemModel.flags(self, index)
|
||||
|
||||
def append(self, obj, active=False, overwrite=False):
|
||||
def append(self, obj, active=False):
|
||||
FlatCAMApp.App.log.debug(str(inspect.stack()[1][3]) + " --> OC.append()")
|
||||
|
||||
name = obj.options["name"]
|
||||
|
@ -653,12 +653,6 @@ class ObjectCollection(QtCore.QAbstractItemModel):
|
|||
# FlatCAMApp.App.log.debug("Promised object %s became available." % name)
|
||||
# FlatCAMApp.App.log.debug("%d promised objects remaining." % len(self.promises))
|
||||
|
||||
# first delete the old object
|
||||
if overwrite:
|
||||
if name in self.get_names():
|
||||
self.set_active(name)
|
||||
self.delete_active(select_project=False)
|
||||
|
||||
# Prevent same name
|
||||
while name in self.get_names():
|
||||
## Create a new name
|
||||
|
|
|
@ -11,7 +11,9 @@ CAD program, and create G-Code for Isolation routing.
|
|||
|
||||
22.02.2019
|
||||
|
||||
-
|
||||
- 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
|
||||
-
|
||||
|
||||
21.02.2019
|
||||
|
||||
|
|
|
@ -5723,8 +5723,8 @@ class CNCjob(Geometry):
|
|||
command['Z'] = 1
|
||||
else:
|
||||
command['Z'] = 0
|
||||
elif self.pp_solderpaste is not None:
|
||||
if 'Paste' in self.pp_solderpaste:
|
||||
elif self.pp_solderpaste_name is not None:
|
||||
if 'Paste' in self.pp_solderpaste_name:
|
||||
match_paste = re.search(r"X([\+-]?\d+.[\+-]?\d+)\s*Y([\+-]?\d+.[\+-]?\d+)", gline)
|
||||
if match_paste:
|
||||
command['X'] = float(match_paste.group(1).replace(" ", ""))
|
||||
|
|
|
@ -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()))
|
||||
|
|
|
@ -0,0 +1,198 @@
|
|||
from FlatCAMPostProc import *
|
||||
|
||||
|
||||
class Repetier(FlatCAMPostProc):
|
||||
|
||||
coordinate_format = "%.*f"
|
||||
feedrate_format = '%.*f'
|
||||
feedrate_rapid_format = feedrate_format
|
||||
|
||||
def start_code(self, p):
|
||||
units = ' ' + str(p['units']).lower()
|
||||
coords_xy = p['toolchange_xy']
|
||||
gcode = ''
|
||||
|
||||
xmin = '%.*f' % (p.coords_decimals, p['options']['xmin'])
|
||||
xmax = '%.*f' % (p.coords_decimals, p['options']['xmax'])
|
||||
ymin = '%.*f' % (p.coords_decimals, p['options']['ymin'])
|
||||
ymax = '%.*f' % (p.coords_decimals, p['options']['ymax'])
|
||||
|
||||
if str(p['options']['type']) == 'Geometry':
|
||||
gcode += ';TOOL DIAMETER: ' + str(p['options']['tool_dia']) + units + '\n' + '\n'
|
||||
|
||||
gcode += ';Feedrate: ' + str(p['feedrate']) + units + '/min' + '\n'
|
||||
|
||||
if str(p['options']['type']) == 'Geometry':
|
||||
gcode += ';Feedrate_Z: ' + str(p['feedrate_z']) + units + '/min' + '\n'
|
||||
|
||||
gcode += ';Feedrate rapids ' + str(p['feedrate_rapid']) + units + '/min' + '\n' + '\n'
|
||||
gcode += ';Z_Cut: ' + str(p['z_cut']) + units + '\n'
|
||||
|
||||
if str(p['options']['type']) == 'Geometry':
|
||||
if p['multidepth'] is True:
|
||||
gcode += ';DepthPerCut: ' + str(p['depthpercut']) + units + ' <=>' + \
|
||||
str(math.ceil(abs(p['z_cut']) / p['depthpercut'])) + ' passes' + '\n'
|
||||
|
||||
gcode += ';Z_Move: ' + str(p['z_move']) + units + '\n'
|
||||
gcode += ';Z Toolchange: ' + str(p['toolchangez']) + units + '\n'
|
||||
|
||||
if coords_xy is not None:
|
||||
gcode += ';X,Y Toolchange: ' + "%.4f, %.4f" % (coords_xy[0], coords_xy[1]) + units + '\n'
|
||||
else:
|
||||
gcode += ';X,Y Toolchange: ' + "None" + units + '\n'
|
||||
|
||||
gcode += ';Z Start: ' + str(p['startz']) + units + '\n'
|
||||
gcode += ';Z End: ' + str(p['endz']) + units + '\n'
|
||||
gcode += ';Steps per circle: ' + str(p['steps_per_circle']) + '\n'
|
||||
|
||||
if str(p['options']['type']) == 'Excellon' or str(p['options']['type']) == 'Excellon Geometry':
|
||||
gcode += ';Postprocessor Excellon: ' + str(p['pp_excellon_name']) + '\n'
|
||||
else:
|
||||
gcode += ';Postprocessor Geometry: ' + str(p['pp_geometry_name']) + '\n' + '\n'
|
||||
|
||||
gcode += ';X range: ' + '{: >9s}'.format(xmin) + ' ... ' + '{: >9s}'.format(xmax) + ' ' + units + '\n'
|
||||
gcode += ';Y range: ' + '{: >9s}'.format(ymin) + ' ... ' + '{: >9s}'.format(ymax) + ' ' + units + '\n\n'
|
||||
|
||||
gcode += ';Spindle Speed: ' + str(p['spindlespeed']) + ' RPM' + '\n' + '\n'
|
||||
|
||||
gcode += ('G20' if p.units.upper() == 'IN' else 'G21') + "\n"
|
||||
gcode += 'G90\n'
|
||||
|
||||
return gcode
|
||||
|
||||
def startz_code(self, p):
|
||||
if p.startz is not None:
|
||||
return 'G0 Z' + self.coordinate_format % (p.coords_decimals, p.startz)
|
||||
else:
|
||||
return ''
|
||||
|
||||
def lift_code(self, p):
|
||||
return 'G0 Z' + self.coordinate_format%(p.coords_decimals, p.z_move) + " " + self.feedrate_rapid_code(p)
|
||||
|
||||
def down_code(self, p):
|
||||
return 'G1 Z' + self.coordinate_format%(p.coords_decimals, p.z_cut) + " " + self.end_feedrate_code(p)
|
||||
|
||||
def toolchange_code(self, p):
|
||||
toolchangez = p.toolchangez
|
||||
toolchangexy = p.toolchange_xy
|
||||
f_plunge = p.f_plunge
|
||||
gcode = ''
|
||||
|
||||
if toolchangexy is not None:
|
||||
toolchangex = toolchangexy[0]
|
||||
toolchangey = toolchangexy[1]
|
||||
|
||||
no_drills = 1
|
||||
|
||||
if int(p.tool) == 1 and p.startz is not None:
|
||||
toolchangez = p.startz
|
||||
|
||||
if p.units.upper() == 'MM':
|
||||
toolC_formatted = format(p.toolC, '.2f')
|
||||
else:
|
||||
toolC_formatted = format(p.toolC, '.4f')
|
||||
|
||||
if str(p['options']['type']) == 'Excellon':
|
||||
for i in p['options']['Tools_in_use']:
|
||||
if i[0] == p.tool:
|
||||
no_drills = i[2]
|
||||
|
||||
if toolchangexy is not None:
|
||||
gcode = """
|
||||
G0 Z{toolchangez}
|
||||
G0 X{toolchangex} Y{toolchangey}
|
||||
M84
|
||||
@pause Change to Tool Dia = {toolC}, Total drills for tool T{tool} = {t_drills}
|
||||
""".format(toolchangex=self.coordinate_format % (p.coords_decimals, toolchangex),
|
||||
toolchangey=self.coordinate_format % (p.coords_decimals, toolchangey),
|
||||
toolchangez=self.coordinate_format % (p.coords_decimals, toolchangez),
|
||||
tool=int(p.tool),
|
||||
t_drills=no_drills,
|
||||
toolC=toolC_formatted)
|
||||
else:
|
||||
gcode = """
|
||||
G0 Z{toolchangez}
|
||||
M84
|
||||
@pause Change to Tool Dia = {toolC}, Total drills for tool T{tool} = {t_drills}
|
||||
""".format(toolchangez=self.coordinate_format % (p.coords_decimals, toolchangez),
|
||||
tool=int(p.tool),
|
||||
t_drills=no_drills,
|
||||
toolC=toolC_formatted)
|
||||
|
||||
if f_plunge is True:
|
||||
gcode += '\nG0 Z%.*f' % (p.coords_decimals, p.z_move)
|
||||
|
||||
return gcode
|
||||
|
||||
else:
|
||||
if toolchangexy is not None:
|
||||
gcode = """
|
||||
G0 Z{toolchangez}
|
||||
G0 X{toolchangex} Y{toolchangey}
|
||||
M84
|
||||
@pause Change to tool T{tool} with Tool Dia = {toolC}
|
||||
""".format(toolchangex=self.coordinate_format % (p.coords_decimals, toolchangex),
|
||||
toolchangey=self.coordinate_format % (p.coords_decimals, toolchangey),
|
||||
toolchangez=self.coordinate_format % (p.coords_decimals, toolchangez),
|
||||
tool=int(p.tool),
|
||||
toolC=toolC_formatted)
|
||||
else:
|
||||
gcode = """
|
||||
G0 Z{toolchangez}
|
||||
M84
|
||||
@pause Change to tool T{tool} with Tool Dia = {toolC}
|
||||
""".format(toolchangez=self.coordinate_format%(p.coords_decimals, toolchangez),
|
||||
tool=int(p.tool),
|
||||
toolC=toolC_formatted)
|
||||
|
||||
if f_plunge is True:
|
||||
gcode += '\nG0 Z%.*f' % (p.coords_decimals, p.z_move)
|
||||
|
||||
return gcode
|
||||
|
||||
def up_to_zero_code(self, p):
|
||||
return 'G1 Z0' + " " + self.feedrate_code(p)
|
||||
|
||||
def position_code(self, p):
|
||||
return ('X' + self.coordinate_format + ' Y' + self.coordinate_format) % \
|
||||
(p.coords_decimals, p.x, p.coords_decimals, p.y)
|
||||
|
||||
def rapid_code(self, p):
|
||||
return ('G0 ' + self.position_code(p)).format(**p) + " " + self.feedrate_rapid_code(p)
|
||||
|
||||
def linear_code(self, p):
|
||||
return ('G1 ' + self.position_code(p)).format(**p) + " " + self.end_feedrate_code(p)
|
||||
|
||||
def end_code(self, p):
|
||||
coords_xy = p['toolchange_xy']
|
||||
gcode = ('G0 Z' + self.feedrate_format %(p.fr_decimals, p.endz) + " " + self.feedrate_rapid_code(p) + "\n")
|
||||
|
||||
if coords_xy is not None:
|
||||
gcode += 'G0 X{x} Y{y}'.format(x=coords_xy[0], y=coords_xy[1]) + " " + self.feedrate_rapid_code(p) + "\n"
|
||||
|
||||
return gcode
|
||||
|
||||
def feedrate_code(self, p):
|
||||
return 'G1 F' + str(self.feedrate_format %(p.fr_decimals, p.feedrate))
|
||||
|
||||
def end_feedrate_code(self, p):
|
||||
return 'F' + self.feedrate_format %(p.fr_decimals, p.feedrate)
|
||||
|
||||
def feedrate_z_code(self, p):
|
||||
return 'G1 F' + str(self.feedrate_format %(p.fr_decimals, p.feedrate_z))
|
||||
|
||||
def feedrate_rapid_code(self, p):
|
||||
return 'F' + self.feedrate_rapid_format % (p.fr_decimals, p.feedrate_rapid)
|
||||
|
||||
def spindle_code(self,p):
|
||||
if p.spindlespeed:
|
||||
return 'M106 S%d' % p.spindlespeed
|
||||
else:
|
||||
return 'M106'
|
||||
|
||||
def dwell_code(self, p):
|
||||
if p.dwelltime:
|
||||
return 'G4 P' + str(p.dwelltime)
|
||||
|
||||
def spindle_stop_code(self,p):
|
||||
return 'M107'
|
Loading…
Reference in New Issue