- some work in Milling Tool
This commit is contained in:
@@ -12,17 +12,20 @@ from appGUI.GUIElements import FCCheckBox, FCDoubleSpinner, RadioSet, FCTable, F
|
||||
FCComboBox, OptionalInputSection, FCSpinner, NumericalEvalEntry, OptionalHideInputSection, FCLabel
|
||||
from appParsers.ParseExcellon import Excellon
|
||||
|
||||
from camlib import Geometry, grace
|
||||
|
||||
from copy import deepcopy
|
||||
import math
|
||||
import simplejson as json
|
||||
import sys
|
||||
import traceback
|
||||
|
||||
from appObjects.FlatCAMObj import FlatCAMObj
|
||||
# import numpy as np
|
||||
# import math
|
||||
|
||||
# from shapely.ops import unary_union
|
||||
from shapely.geometry import Point, LineString
|
||||
from shapely.geometry import Point, LineString, box
|
||||
|
||||
from matplotlib.backend_bases import KeyEvent as mpl_key_event
|
||||
|
||||
@@ -46,6 +49,7 @@ else:
|
||||
|
||||
class ToolMilling(AppTool, Excellon):
|
||||
builduiSig = QtCore.pyqtSignal()
|
||||
launch_job = QtCore.pyqtSignal()
|
||||
|
||||
def __init__(self, app):
|
||||
self.app = app
|
||||
@@ -227,7 +231,7 @@ class ToolMilling(AppTool, Excellon):
|
||||
|
||||
self.ui.apply_param_to_all.clicked.connect(self.on_apply_param_to_all_clicked)
|
||||
self.ui.generate_cnc_button.clicked.connect(self.on_cnc_button_click)
|
||||
self.ui.tools_table.drag_drop_sig.connect(self.rebuild_ui)
|
||||
self.ui.tools_table.drag_drop_sig.connect(self.on_exc_rebuild_ui)
|
||||
|
||||
# Exclusion areas signals
|
||||
self.ui.exclusion_table.horizontalHeader().sectionClicked.connect(self.exclusion_table_toggle_all)
|
||||
@@ -238,6 +242,12 @@ class ToolMilling(AppTool, Excellon):
|
||||
self.ui.delete_sel_area_button.clicked.connect(self.on_delete_sel_areas)
|
||||
self.ui.strategy_radio.activated_custom.connect(self.on_strategy)
|
||||
|
||||
# Geo Tools Table signals
|
||||
self.ui.geo_tools_table.drag_drop_sig.connect(self.on_geo_rebuild_ui)
|
||||
self.ui.geo_tools_table.horizontalHeader().sectionClicked.connect(self.on_toggle_all_rows)
|
||||
|
||||
self.launch_job.connect(self.mtool_gen_cncjob)
|
||||
|
||||
self.ui.reset_button.clicked.connect(self.set_tool_ui)
|
||||
# Cleanup on Graceful exit (CTRL+ALT+X combo key)
|
||||
self.app.cleanup.connect(self.set_tool_ui)
|
||||
@@ -452,7 +462,7 @@ class ToolMilling(AppTool, Excellon):
|
||||
def on_plot_clicked(self, state):
|
||||
self.target_obj.options['plot'] = True if state else False
|
||||
|
||||
def rebuild_ui(self):
|
||||
def on_exc_rebuild_ui(self):
|
||||
# read the table tools uid
|
||||
current_uid_list = []
|
||||
for row in range(self.ui.tools_table.rowCount()):
|
||||
@@ -469,6 +479,26 @@ class ToolMilling(AppTool, Excellon):
|
||||
# the tools table changed therefore we need to rebuild it
|
||||
QtCore.QTimer.singleShot(20, self.build_ui)
|
||||
|
||||
def on_geo_rebuild_ui(self):
|
||||
# read the table tools uid
|
||||
current_uid_list = []
|
||||
for row in range(self.ui.geo_tools_table.rowCount()):
|
||||
uid = int(self.ui.geo_tools_table.item(row, 3).text())
|
||||
current_uid_list.append(uid)
|
||||
|
||||
new_tools = {}
|
||||
new_uid = 1
|
||||
|
||||
for current_uid in current_uid_list:
|
||||
new_tools[new_uid] = deepcopy(self.tools[current_uid])
|
||||
new_uid += 1
|
||||
|
||||
self.tools = new_tools
|
||||
|
||||
# the tools table changed therefore we need to reconnect the signals to the cellWidgets
|
||||
self.ui_disconnect()
|
||||
self.ui_connect()
|
||||
|
||||
def build_ui(self):
|
||||
self.ui_disconnect()
|
||||
|
||||
@@ -2170,6 +2200,525 @@ class ToolMilling(AppTool, Excellon):
|
||||
|
||||
return True, ""
|
||||
|
||||
def on_polish(self):
|
||||
|
||||
def job_thread(obj):
|
||||
with obj.app.proc_container.new('%s...' % _("Working")):
|
||||
tooldia = obj.ui.polish_dia_entry.get_value()
|
||||
depth = obj.ui.polish_pressure_entry.get_value()
|
||||
travelz = obj.ui.polish_travelz_entry.get_value()
|
||||
margin = obj.ui.polish_margin_entry.get_value()
|
||||
overlap = obj.ui.polish_over_entry.get_value() / 100
|
||||
paint_method = obj.ui.polish_method_combo.get_value()
|
||||
|
||||
# calculate the max uid form the keys of the self.tools
|
||||
max_uid = max(list(obj.tools.keys()))
|
||||
new_uid = max_uid + 1
|
||||
|
||||
# add a new key in the dict
|
||||
new_data = deepcopy(obj.default_data)
|
||||
new_data["travelz"] = travelz
|
||||
new_data["cutz"] = depth
|
||||
new_dict = {
|
||||
new_uid: {
|
||||
'tooldia': obj.app.dec_format(float(tooldia), obj.decimals),
|
||||
'offset': 'Path',
|
||||
'offset_value': 0.0,
|
||||
'type': _('Polish'),
|
||||
'tool_type': 'C1',
|
||||
'data': new_data,
|
||||
'solid_geometry': []
|
||||
}
|
||||
}
|
||||
obj.tools.update(new_dict)
|
||||
obj.sel_tools.update(new_dict)
|
||||
|
||||
# make a box polygon out of the bounds of the current object
|
||||
# apply the margin
|
||||
xmin, ymin, xmax, ymax = obj.bounds()
|
||||
bbox = box(xmin-margin, ymin-margin, xmax+margin, ymax+margin)
|
||||
|
||||
# paint the box
|
||||
try:
|
||||
# provide the app with a way to process the GUI events when in a blocking loop
|
||||
QtWidgets.QApplication.processEvents()
|
||||
if self.app.abort_flag:
|
||||
# graceful abort requested by the user
|
||||
raise grace
|
||||
|
||||
# Type(cpoly) == FlatCAMRTreeStorage | None
|
||||
cpoly = None
|
||||
if paint_method == 0: # Standard
|
||||
cpoly = self.clear_polygon(bbox,
|
||||
tooldia=tooldia,
|
||||
steps_per_circle=obj.circle_steps,
|
||||
overlap=overlap,
|
||||
contour=True,
|
||||
connect=True,
|
||||
prog_plot=False)
|
||||
elif paint_method == 1: # Seed
|
||||
cpoly = self.clear_polygon2(bbox,
|
||||
tooldia=tooldia,
|
||||
steps_per_circle=obj.circle_steps,
|
||||
overlap=overlap,
|
||||
contour=True,
|
||||
connect=True,
|
||||
prog_plot=False)
|
||||
elif paint_method == 2: # Lines
|
||||
cpoly = self.clear_polygon3(bbox,
|
||||
tooldia=tooldia,
|
||||
steps_per_circle=obj.circle_steps,
|
||||
overlap=overlap,
|
||||
contour=True,
|
||||
connect=True,
|
||||
prog_plot=False)
|
||||
|
||||
if not cpoly or not cpoly.objects:
|
||||
obj.app.inform.emit('[ERROR_NOTCL] %s' % _('Geometry could not be painted completely'))
|
||||
return
|
||||
|
||||
paint_geo = [g for g in cpoly.get_objects() if g and not g.is_empty]
|
||||
except grace:
|
||||
return "fail"
|
||||
except Exception as e:
|
||||
log.debug("Could not Paint the polygons. %s" % str(e))
|
||||
mssg = '[ERROR] %s\n%s' % (_("Could not do Paint. Try a different combination of parameters. "
|
||||
"Or a different method of Paint"), str(e))
|
||||
self.app.inform.emit(mssg)
|
||||
return
|
||||
|
||||
obj.sel_tools[new_uid]['solid_geometry'] = paint_geo
|
||||
|
||||
# and now create the CNCJob
|
||||
obj.launch_job.emit()
|
||||
|
||||
# Send to worker
|
||||
self.app.worker_task.emit({'fcn': job_thread, 'params': [self]})
|
||||
|
||||
def on_generatecnc_button_click(self):
|
||||
log.debug("Generating CNCJob from Geometry ...")
|
||||
self.app.defaults.report_usage("geometry_on_generatecnc_button")
|
||||
|
||||
|
||||
self.sel_tools = {}
|
||||
|
||||
try:
|
||||
if self.special_group:
|
||||
self.app.inform.emit(
|
||||
'[WARNING_NOTCL] %s %s %s.' %
|
||||
(_("This Geometry can't be processed because it is"), str(self.special_group), _("Geometry"))
|
||||
)
|
||||
return
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
# test to see if we have tools available in the tool table
|
||||
if self.ui.geo_tools_table.selectedItems():
|
||||
for x in self.ui.geo_tools_table.selectedItems():
|
||||
tooluid = int(self.ui.geo_tools_table.item(x.row(), 3).text())
|
||||
|
||||
for tooluid_key, tooluid_value in self.tools.items():
|
||||
if int(tooluid_key) == tooluid:
|
||||
self.sel_tools.update({
|
||||
tooluid: deepcopy(tooluid_value)
|
||||
})
|
||||
|
||||
if self.ui.polish_cb.get_value():
|
||||
self.on_polish()
|
||||
else:
|
||||
self.mtool_gen_cncjob()
|
||||
self.ui.geo_tools_table.clearSelection()
|
||||
|
||||
elif self.ui.geo_tools_table.rowCount() == 1:
|
||||
tooluid = int(self.ui.geo_tools_table.item(0, 3).text())
|
||||
|
||||
for tooluid_key, tooluid_value in self.tools.items():
|
||||
if int(tooluid_key) == tooluid:
|
||||
self.sel_tools.update({
|
||||
tooluid: deepcopy(tooluid_value)
|
||||
})
|
||||
if self.ui.polish_cb.get_value():
|
||||
self.on_polish()
|
||||
else:
|
||||
self.mtool_gen_cncjob()
|
||||
self.ui.geo_tools_table.clearSelection()
|
||||
else:
|
||||
self.app.inform.emit('[ERROR_NOTCL] %s' % _("Failed. No tool selected in the tool table ..."))
|
||||
|
||||
def mtool_gen_cncjob(self, outname=None, tools_dict=None, tools_in_use=None, segx=None, segy=None,
|
||||
plot=True, use_thread=True):
|
||||
"""
|
||||
Creates a multi-tool CNCJob out of this Geometry object.
|
||||
The actual work is done by the target CNCJobObject object's
|
||||
`generate_from_geometry_2()` method.
|
||||
|
||||
:param outname:
|
||||
:param tools_dict: a dictionary that holds the whole data needed to create the Gcode
|
||||
(including the solid_geometry)
|
||||
:param tools_in_use: the tools that are used, needed by some preprocessors
|
||||
:type tools_in_use list of lists, each list in the list is made out of row elements of tools table from GUI
|
||||
:param segx: number of segments on the X axis, for auto-levelling
|
||||
:param segy: number of segments on the Y axis, for auto-levelling
|
||||
:param plot: if True the generated object will be plotted; if False will not be plotted
|
||||
:param use_thread: if True use threading
|
||||
:return: None
|
||||
"""
|
||||
|
||||
# use the name of the first tool selected in self.geo_tools_table which has the diameter passed as tool_dia
|
||||
outname = "%s_%s" % (self.options["name"], 'cnc') if outname is None else outname
|
||||
|
||||
tools_dict = self.sel_tools if tools_dict is None else tools_dict
|
||||
tools_in_use = tools_in_use if tools_in_use is not None else self.get_selected_tools_table_items()
|
||||
segx = segx if segx is not None else float(self.app.defaults['geometry_segx'])
|
||||
segy = segy if segy is not None else float(self.app.defaults['geometry_segy'])
|
||||
|
||||
try:
|
||||
xmin = self.options['xmin']
|
||||
ymin = self.options['ymin']
|
||||
xmax = self.options['xmax']
|
||||
ymax = self.options['ymax']
|
||||
except Exception as e:
|
||||
log.debug("FlatCAMObj.GeometryObject.mtool_gen_cncjob() --> %s\n" % str(e))
|
||||
|
||||
msg = '[ERROR] %s' % _("An internal error has occurred. See shell.\n")
|
||||
msg += '%s' % str(e)
|
||||
msg += traceback.format_exc()
|
||||
self.app.inform.emit(msg)
|
||||
return
|
||||
|
||||
# force everything as MULTI-GEO
|
||||
# self.multigeo = True
|
||||
|
||||
# Object initialization function for app.app_obj.new_object()
|
||||
# RUNNING ON SEPARATE THREAD!
|
||||
def job_init_single_geometry(job_obj, app_obj):
|
||||
log.debug("Creating a CNCJob out of a single-geometry")
|
||||
assert job_obj.kind == 'cncjob', "Initializer expected a CNCJobObject, got %s" % type(job_obj)
|
||||
|
||||
job_obj.options['xmin'] = xmin
|
||||
job_obj.options['ymin'] = ymin
|
||||
job_obj.options['xmax'] = xmax
|
||||
job_obj.options['ymax'] = ymax
|
||||
|
||||
# count the tools
|
||||
tool_cnt = 0
|
||||
|
||||
# dia_cnc_dict = {}
|
||||
|
||||
# this turn on the FlatCAMCNCJob plot for multiple tools
|
||||
job_obj.multitool = True
|
||||
job_obj.multigeo = False
|
||||
job_obj.cnc_tools.clear()
|
||||
|
||||
job_obj.options['Tools_in_use'] = tools_in_use
|
||||
job_obj.segx = segx if segx else float(self.app.defaults["geometry_segx"])
|
||||
job_obj.segy = segy if segy else float(self.app.defaults["geometry_segy"])
|
||||
|
||||
job_obj.z_pdepth = float(self.app.defaults["geometry_z_pdepth"])
|
||||
job_obj.feedrate_probe = float(self.app.defaults["geometry_feedrate_probe"])
|
||||
|
||||
total_gcode = ''
|
||||
for tooluid_key in list(tools_dict.keys()):
|
||||
tool_cnt += 1
|
||||
|
||||
dia_cnc_dict = deepcopy(tools_dict[tooluid_key])
|
||||
tooldia_val = app_obj.dec_format(float(tools_dict[tooluid_key]['tooldia']), self.decimals)
|
||||
dia_cnc_dict.update({
|
||||
'tooldia': tooldia_val
|
||||
})
|
||||
|
||||
if dia_cnc_dict['offset'] == 'in':
|
||||
tool_offset = -dia_cnc_dict['tooldia'] / 2
|
||||
elif dia_cnc_dict['offset'].lower() == 'out':
|
||||
tool_offset = dia_cnc_dict['tooldia'] / 2
|
||||
elif dia_cnc_dict['offset'].lower() == 'custom':
|
||||
try:
|
||||
offset_value = float(self.ui.tool_offset_entry.get_value())
|
||||
except ValueError:
|
||||
# try to convert comma to decimal point. if it's still not working error message and return
|
||||
try:
|
||||
offset_value = float(self.ui.tool_offset_entry.get_value().replace(',', '.'))
|
||||
except ValueError:
|
||||
app_obj.inform.emit('[ERROR_NOTCL] %s' % _("Wrong value format entered, use a number."))
|
||||
return
|
||||
if offset_value:
|
||||
tool_offset = float(offset_value)
|
||||
else:
|
||||
app_obj.inform.emit(
|
||||
'[WARNING] %s' % _("Tool Offset is selected in Tool Table but no value is provided.\n"
|
||||
"Add a Tool Offset or change the Offset Type.")
|
||||
)
|
||||
return
|
||||
else:
|
||||
tool_offset = 0.0
|
||||
|
||||
dia_cnc_dict.update({
|
||||
'offset_value': tool_offset
|
||||
})
|
||||
|
||||
z_cut = tools_dict[tooluid_key]['data']["cutz"]
|
||||
z_move = tools_dict[tooluid_key]['data']["travelz"]
|
||||
feedrate = tools_dict[tooluid_key]['data']["feedrate"]
|
||||
feedrate_z = tools_dict[tooluid_key]['data']["feedrate_z"]
|
||||
feedrate_rapid = tools_dict[tooluid_key]['data']["feedrate_rapid"]
|
||||
multidepth = tools_dict[tooluid_key]['data']["multidepth"]
|
||||
extracut = tools_dict[tooluid_key]['data']["extracut"]
|
||||
extracut_length = tools_dict[tooluid_key]['data']["extracut_length"]
|
||||
depthpercut = tools_dict[tooluid_key]['data']["depthperpass"]
|
||||
toolchange = tools_dict[tooluid_key]['data']["toolchange"]
|
||||
toolchangez = tools_dict[tooluid_key]['data']["toolchangez"]
|
||||
toolchangexy = tools_dict[tooluid_key]['data']["toolchangexy"]
|
||||
startz = tools_dict[tooluid_key]['data']["startz"]
|
||||
endz = tools_dict[tooluid_key]['data']["endz"]
|
||||
endxy = self.options["endxy"]
|
||||
spindlespeed = tools_dict[tooluid_key]['data']["spindlespeed"]
|
||||
dwell = tools_dict[tooluid_key]['data']["dwell"]
|
||||
dwelltime = tools_dict[tooluid_key]['data']["dwelltime"]
|
||||
pp_geometry_name = tools_dict[tooluid_key]['data']["ppname_g"]
|
||||
|
||||
spindledir = self.app.defaults['geometry_spindledir']
|
||||
tool_solid_geometry = self.solid_geometry
|
||||
|
||||
job_obj.coords_decimals = self.app.defaults["cncjob_coords_decimals"]
|
||||
job_obj.fr_decimals = self.app.defaults["cncjob_fr_decimals"]
|
||||
|
||||
# Propagate options
|
||||
job_obj.options["tooldia"] = tooldia_val
|
||||
job_obj.options['type'] = 'Geometry'
|
||||
job_obj.options['tool_dia'] = tooldia_val
|
||||
|
||||
tool_lst = list(tools_dict.keys())
|
||||
is_first = True if tooluid_key == tool_lst[0] else False
|
||||
|
||||
# it seems that the tolerance needs to be a lot lower value than 0.01 and it was hardcoded initially
|
||||
# to a value of 0.0005 which is 20 times less than 0.01
|
||||
tol = float(self.app.defaults['global_tolerance']) / 20
|
||||
res, start_gcode = job_obj.generate_from_geometry_2(
|
||||
self, tooldia=tooldia_val, offset=tool_offset, tolerance=tol,
|
||||
z_cut=z_cut, z_move=z_move,
|
||||
feedrate=feedrate, feedrate_z=feedrate_z, feedrate_rapid=feedrate_rapid,
|
||||
spindlespeed=spindlespeed, spindledir=spindledir, dwell=dwell, dwelltime=dwelltime,
|
||||
multidepth=multidepth, depthpercut=depthpercut,
|
||||
extracut=extracut, extracut_length=extracut_length, startz=startz, endz=endz, endxy=endxy,
|
||||
toolchange=toolchange, toolchangez=toolchangez, toolchangexy=toolchangexy,
|
||||
pp_geometry_name=pp_geometry_name,
|
||||
tool_no=tool_cnt, is_first=is_first)
|
||||
|
||||
if res == 'fail':
|
||||
log.debug("GeometryObject.mtool_gen_cncjob() --> generate_from_geometry2() failed")
|
||||
return 'fail'
|
||||
|
||||
dia_cnc_dict['gcode'] = res
|
||||
if start_gcode != '':
|
||||
job_obj.gc_start = start_gcode
|
||||
|
||||
total_gcode += res
|
||||
|
||||
# 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"
|
||||
|
||||
self.app.inform.emit('[success] %s' % _("G-Code parsing in progress..."))
|
||||
dia_cnc_dict['gcode_parsed'] = job_obj.gcode_parse()
|
||||
app_obj.inform.emit('[success] %s' % _("G-Code parsing finished..."))
|
||||
|
||||
# commented this; there is no need for the actual GCode geometry - the original one will serve as well
|
||||
# for bounding box values
|
||||
# dia_cnc_dict['solid_geometry'] = unary_union([geo['geom'] for geo in dia_cnc_dict['gcode_parsed']])
|
||||
try:
|
||||
dia_cnc_dict['solid_geometry'] = tool_solid_geometry
|
||||
app_obj.inform.emit('[success] %s...' % _("Finished G-Code processing"))
|
||||
except Exception as er:
|
||||
app_obj.inform.emit('[ERROR] %s: %s' % (_("G-Code processing failed with error"), str(er)))
|
||||
|
||||
job_obj.cnc_tools.update({
|
||||
tooluid_key: deepcopy(dia_cnc_dict)
|
||||
})
|
||||
dia_cnc_dict.clear()
|
||||
|
||||
job_obj.source_file = job_obj.gc_start + total_gcode
|
||||
|
||||
# Object initialization function for app.app_obj.new_object()
|
||||
# RUNNING ON SEPARATE THREAD!
|
||||
def job_init_multi_geometry(job_obj, app_obj):
|
||||
log.debug("Creating a CNCJob out of a multi-geometry")
|
||||
assert job_obj.kind == 'cncjob', "Initializer expected a CNCJobObject, got %s" % type(job_obj)
|
||||
|
||||
job_obj.options['xmin'] = xmin
|
||||
job_obj.options['ymin'] = ymin
|
||||
job_obj.options['xmax'] = xmax
|
||||
job_obj.options['ymax'] = ymax
|
||||
|
||||
# count the tools
|
||||
tool_cnt = 0
|
||||
|
||||
# dia_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.options['Tools_in_use'] = tools_in_use
|
||||
job_obj.segx = segx if segx else float(self.app.defaults["geometry_segx"])
|
||||
job_obj.segy = segy if segy else float(self.app.defaults["geometry_segy"])
|
||||
|
||||
job_obj.z_pdepth = float(self.app.defaults["geometry_z_pdepth"])
|
||||
job_obj.feedrate_probe = float(self.app.defaults["geometry_feedrate_probe"])
|
||||
|
||||
# make sure that trying to make a CNCJob from an empty file is not creating an app crash
|
||||
if not self.solid_geometry:
|
||||
a = 0
|
||||
for tooluid_key in self.tools:
|
||||
if self.tools[tooluid_key]['solid_geometry'] is None:
|
||||
a += 1
|
||||
if a == len(self.tools):
|
||||
app_obj.inform.emit('[ERROR_NOTCL] %s...' % _('Cancelled. Empty file, it has no geometry'))
|
||||
return 'fail'
|
||||
|
||||
total_gcode = ''
|
||||
for tooluid_key in list(tools_dict.keys()):
|
||||
tool_cnt += 1
|
||||
dia_cnc_dict = deepcopy(tools_dict[tooluid_key])
|
||||
tooldia_val = app_obj.dec_format(float(tools_dict[tooluid_key]['tooldia']), self.decimals)
|
||||
dia_cnc_dict.update({
|
||||
'tooldia': tooldia_val
|
||||
})
|
||||
if "optimization_type" not in tools_dict[tooluid_key]['data']:
|
||||
tools_dict[tooluid_key]['data']["optimization_type"] = \
|
||||
self.app.defaults["geometry_optimization_type"]
|
||||
|
||||
# find the tool_dia associated with the tooluid_key
|
||||
# search in the self.tools for the sel_tool_dia and when found see what tooluid has
|
||||
# on the found tooluid in self.tools we also have the solid_geometry that interest us
|
||||
# for k, v in self.tools.items():
|
||||
# if float('%.*f' % (self.decimals, float(v['tooldia']))) == tooldia_val:
|
||||
# current_uid = int(k)
|
||||
# break
|
||||
|
||||
if dia_cnc_dict['offset'].lower() == 'in':
|
||||
tool_offset = -tooldia_val / 2
|
||||
elif dia_cnc_dict['offset'].lower() == 'out':
|
||||
tool_offset = tooldia_val / 2
|
||||
elif dia_cnc_dict['offset'].lower() == 'custom':
|
||||
offset_value = float(self.ui.tool_offset_entry.get_value())
|
||||
if offset_value:
|
||||
tool_offset = float(offset_value)
|
||||
else:
|
||||
self.app.inform.emit('[WARNING] %s' %
|
||||
_("Tool Offset is selected in Tool Table but "
|
||||
"no value is provided.\n"
|
||||
"Add a Tool Offset or change the Offset Type."))
|
||||
return
|
||||
else:
|
||||
tool_offset = 0.0
|
||||
|
||||
dia_cnc_dict.update({
|
||||
'offset_value': tool_offset
|
||||
})
|
||||
|
||||
# z_cut = tools_dict[tooluid_key]['data']["cutz"]
|
||||
# z_move = tools_dict[tooluid_key]['data']["travelz"]
|
||||
# feedrate = tools_dict[tooluid_key]['data']["feedrate"]
|
||||
# feedrate_z = tools_dict[tooluid_key]['data']["feedrate_z"]
|
||||
# feedrate_rapid = tools_dict[tooluid_key]['data']["feedrate_rapid"]
|
||||
# multidepth = tools_dict[tooluid_key]['data']["multidepth"]
|
||||
# extracut = tools_dict[tooluid_key]['data']["extracut"]
|
||||
# extracut_length = tools_dict[tooluid_key]['data']["extracut_length"]
|
||||
# depthpercut = tools_dict[tooluid_key]['data']["depthperpass"]
|
||||
# toolchange = tools_dict[tooluid_key]['data']["toolchange"]
|
||||
# toolchangez = tools_dict[tooluid_key]['data']["toolchangez"]
|
||||
# toolchangexy = tools_dict[tooluid_key]['data']["toolchangexy"]
|
||||
# startz = tools_dict[tooluid_key]['data']["startz"]
|
||||
# endz = tools_dict[tooluid_key]['data']["endz"]
|
||||
# endxy = self.options["endxy"]
|
||||
# spindlespeed = tools_dict[tooluid_key]['data']["spindlespeed"]
|
||||
# dwell = tools_dict[tooluid_key]['data']["dwell"]
|
||||
# dwelltime = tools_dict[tooluid_key]['data']["dwelltime"]
|
||||
# pp_geometry_name = tools_dict[tooluid_key]['data']["ppname_g"]
|
||||
#
|
||||
# spindledir = self.app.defaults['geometry_spindledir']
|
||||
tool_solid_geometry = self.tools[tooluid_key]['solid_geometry']
|
||||
|
||||
job_obj.coords_decimals = self.app.defaults["cncjob_coords_decimals"]
|
||||
job_obj.fr_decimals = self.app.defaults["cncjob_fr_decimals"]
|
||||
|
||||
# Propagate options
|
||||
job_obj.options["tooldia"] = tooldia_val
|
||||
job_obj.options['type'] = 'Geometry'
|
||||
job_obj.options['tool_dia'] = tooldia_val
|
||||
|
||||
# it seems that the tolerance needs to be a lot lower value than 0.01 and it was hardcoded initially
|
||||
# to a value of 0.0005 which is 20 times less than 0.01
|
||||
tol = float(self.app.defaults['global_tolerance']) / 20
|
||||
|
||||
tool_lst = list(tools_dict.keys())
|
||||
is_first = True if tooluid_key == tool_lst[0] else False
|
||||
is_last = True if tooluid_key == tool_lst[-1] else False
|
||||
res, start_gcode = job_obj.geometry_tool_gcode_gen(tooluid_key, tools_dict, first_pt=(0, 0),
|
||||
tolerance=tol,
|
||||
is_first=is_first, is_last=is_last,
|
||||
toolchange=True)
|
||||
if res == 'fail':
|
||||
log.debug("GeometryObject.mtool_gen_cncjob() --> generate_from_geometry2() failed")
|
||||
return 'fail'
|
||||
else:
|
||||
dia_cnc_dict['gcode'] = res
|
||||
total_gcode += res
|
||||
|
||||
if start_gcode != '':
|
||||
job_obj.gc_start = start_gcode
|
||||
|
||||
app_obj.inform.emit('[success] %s' % _("G-Code parsing in progress..."))
|
||||
dia_cnc_dict['gcode_parsed'] = job_obj.gcode_parse()
|
||||
app_obj.inform.emit('[success] %s' % _("G-Code parsing finished..."))
|
||||
|
||||
# commented this; there is no need for the actual GCode geometry - the original one will serve as well
|
||||
# for bounding box values
|
||||
# geo_for_bound_values = unary_union([
|
||||
# geo['geom'] for geo in dia_cnc_dict['gcode_parsed'] if geo['geom'].is_valid is True
|
||||
# ])
|
||||
try:
|
||||
dia_cnc_dict['solid_geometry'] = deepcopy(tool_solid_geometry)
|
||||
app_obj.inform.emit('[success] %s...' % _("Finished G-Code processing"))
|
||||
except Exception as ee:
|
||||
app_obj.inform.emit('[ERROR] %s: %s' % (_("G-Code processing failed with error"), str(ee)))
|
||||
|
||||
# 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"
|
||||
|
||||
job_obj.cnc_tools.update({
|
||||
tooluid_key: deepcopy(dia_cnc_dict)
|
||||
})
|
||||
dia_cnc_dict.clear()
|
||||
|
||||
job_obj.source_file = total_gcode
|
||||
|
||||
if use_thread:
|
||||
# To be run in separate thread
|
||||
def job_thread(a_obj):
|
||||
if self.multigeo is False:
|
||||
with self.app.proc_container.new('%s...' % _("Generating")):
|
||||
ret_val = a_obj.app_obj.new_object("cncjob", outname, job_init_single_geometry, plot=plot)
|
||||
if ret_val != 'fail':
|
||||
a_obj.inform.emit('[success] %s: %s' % (_("CNCjob created"), outname))
|
||||
else:
|
||||
with self.app.proc_container.new('%s...' % _("Generating")):
|
||||
ret_val = a_obj.app_obj.new_object("cncjob", outname, job_init_multi_geometry, plot=plot)
|
||||
if ret_val != 'fail':
|
||||
a_obj.inform.emit('[success] %s: %s' % (_("CNCjob created"), outname))
|
||||
|
||||
# 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:
|
||||
if self.solid_geometry:
|
||||
self.app.app_obj.new_object("cncjob", outname, job_init_single_geometry, plot=plot)
|
||||
else:
|
||||
self.app.app_obj.new_object("cncjob", outname, job_init_multi_geometry, plot=plot)
|
||||
|
||||
def on_pp_changed(self):
|
||||
current_pp = self.ui.pp_geo_name_cb.get_value()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user