- fixed the name self-insert in save dialog file for GCode; added protection in case the save path is None
- fixed FlatCAM crash when trying to make drills GCode out of a file that have only slots. - made the shell toggle shortcut key work when focused on Selected Tab; toggle units shortcut also - changed the messages for Units COnversion
This commit is contained in:
parent
b589292c0f
commit
dedf8c09de
|
@ -1659,7 +1659,10 @@ class App(QtCore.QObject):
|
|||
return self.defaults["global_last_folder"]
|
||||
|
||||
def get_last_save_folder(self):
|
||||
return self.defaults["global_last_save_folder"]
|
||||
loc = self.defaults["global_last_save_folder"]
|
||||
if loc is None:
|
||||
loc = self.defaults["global_last_folder"]
|
||||
return loc
|
||||
|
||||
def report_usage(self, resource):
|
||||
"""
|
||||
|
@ -2070,6 +2073,8 @@ class App(QtCore.QObject):
|
|||
except:
|
||||
self.inform.emit("[ERROR_NOTCL] Failed to write defaults to file.")
|
||||
return
|
||||
|
||||
self.file_saved.emit("preferences", filename)
|
||||
self.inform.emit("[success]Exported Defaults to %s" % filename)
|
||||
|
||||
def on_preferences_open_folder(self):
|
||||
|
@ -2825,6 +2830,9 @@ class App(QtCore.QObject):
|
|||
current.to_form()
|
||||
|
||||
self.plot_all()
|
||||
self.inform.emit("[success]Converted units to %s" % self.options["units"])
|
||||
# self.ui.units_label.setText("[" + self.options["units"] + "]")
|
||||
self.set_screen_units(self.options["units"])
|
||||
else:
|
||||
# Undo toggling
|
||||
self.toggle_units_ignore = True
|
||||
|
@ -2833,11 +2841,9 @@ class App(QtCore.QObject):
|
|||
else:
|
||||
self.general_options_form.general_app_group.units_radio.set_value('MM')
|
||||
self.toggle_units_ignore = False
|
||||
self.inform.emit("[WARNING_NOTCL]Units conversion cancelled.")
|
||||
|
||||
self.options_read_form()
|
||||
self.inform.emit("Converted units to %s" % self.options["units"])
|
||||
#self.ui.units_label.setText("[" + self.options["units"] + "]")
|
||||
self.set_screen_units(self.options["units"])
|
||||
|
||||
def on_toggle_units_click(self):
|
||||
if self.options["units"] == 'MM':
|
||||
|
@ -6044,7 +6050,7 @@ class App(QtCore.QObject):
|
|||
self.defaults["global_last_folder"] = os.path.split(str(filename))[0]
|
||||
|
||||
def register_save_folder(self, filename):
|
||||
self.defaults['global_last_save_folder'] = os.path.split(str(filename))[0]
|
||||
self.defaults["global_last_save_folder"] = os.path.split(str(filename))[0]
|
||||
|
||||
def set_progress_bar(self, percentage, text=""):
|
||||
self.ui.progress_bar.setValue(int(percentage))
|
||||
|
|
|
@ -1508,6 +1508,12 @@ class FlatCAMGUI(QtWidgets.QMainWindow):
|
|||
if event.key() == QtCore.Qt.Key_3:
|
||||
self.app.on_select_tab('tool')
|
||||
|
||||
if event.key == QtCore.Qt.Key_Q:
|
||||
self.app.on_toggle_units_click()
|
||||
|
||||
if event.key() == QtCore.Qt.Key_S:
|
||||
self.app.on_toggle_shell()
|
||||
|
||||
# Show shortcut list
|
||||
if event.key() == QtCore.Qt.Key_Ampersand:
|
||||
self.app.on_shortcut_list()
|
||||
|
|
|
@ -1564,7 +1564,10 @@ class FlatCAMExcellon(FlatCAMObj, Excellon):
|
|||
return False, "Error: No tools."
|
||||
|
||||
for tool in tools:
|
||||
if tooldia > self.tools[tool]["C"]:
|
||||
# I add the 0.0001 value to account for the rounding error in converting from IN to MM and reverse
|
||||
adj_toolstable_tooldia = float('%.4f' % float(tooldia))
|
||||
adj_file_tooldia = float('%.4f' % float(self.tools[tool]["C"]))
|
||||
if adj_toolstable_tooldia > adj_file_tooldia + 0.0001:
|
||||
self.app.inform.emit("[ERROR_NOTCL] Milling tool for SLOTS is larger than hole size. Cancelled.")
|
||||
return False, "Error: Milling tool is larger than hole."
|
||||
|
||||
|
@ -1590,7 +1593,12 @@ class FlatCAMExcellon(FlatCAMObj, Excellon):
|
|||
# we add a tenth of the minimum value, meaning 0.0000001, which from our point of view is "almost zero"
|
||||
for slot in self.slots:
|
||||
if slot['tool'] in tools:
|
||||
buffer_value = (float(self.tools[slot['tool']]["C"]) / 2) - float(tooldia / 2)
|
||||
toolstable_tool = float('%.4f' % float(tooldia))
|
||||
file_tool = float('%.4f' % float(self.tools[tool]["C"]))
|
||||
|
||||
# I add the 0.0001 value to account for the rounding error in converting from IN to MM and reverse
|
||||
# for the file_tool (tooldia actually)
|
||||
buffer_value = float(file_tool / 2) - float(toolstable_tool / 2) + 0.0001
|
||||
if buffer_value == 0:
|
||||
start = slot['start']
|
||||
stop = slot['stop']
|
||||
|
@ -1729,14 +1737,16 @@ class FlatCAMExcellon(FlatCAMObj, Excellon):
|
|||
# job_obj.options["tooldia"] =
|
||||
|
||||
tools_csv = ','.join(tools)
|
||||
job_obj.generate_from_excellon_by_tool(self, tools_csv,
|
||||
drillz=self.options['drillz'],
|
||||
toolchange=self.options["toolchange"],
|
||||
toolchangez=self.options["toolchangez"],
|
||||
startz=self.options["startz"],
|
||||
endz=self.options["endz"],
|
||||
excellon_optimization_type=self.options["optimization_type"])
|
||||
|
||||
ret_val = job_obj.generate_from_excellon_by_tool(self, tools_csv,
|
||||
drillz=self.options['drillz'],
|
||||
toolchange=self.options["toolchange"],
|
||||
toolchangez=self.options["toolchangez"],
|
||||
startz=self.options["startz"],
|
||||
endz=self.options["endz"],
|
||||
excellon_optimization_type=self.app.defaults[
|
||||
"excellon_optimization_type"])
|
||||
if ret_val == 'fail':
|
||||
return 'fail'
|
||||
app_obj.progress.emit(50)
|
||||
job_obj.gcode_parse()
|
||||
|
||||
|
@ -3125,10 +3135,18 @@ class FlatCAMGeometry(FlatCAMObj, Geometry):
|
|||
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'])
|
||||
|
||||
xmin = self.options['xmin']
|
||||
ymin = self.options['ymin']
|
||||
xmax = self.options['xmax']
|
||||
ymax = self.options['ymax']
|
||||
try:
|
||||
xmin = self.options['xmin']
|
||||
ymin = self.options['ymin']
|
||||
xmax = self.options['xmax']
|
||||
ymax = self.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!
|
||||
|
@ -4267,14 +4285,17 @@ class FlatCAMCNCjob(FlatCAMObj, CNCjob):
|
|||
_filter_ = "G-Code Files (*.nc);;G-Code Files (*.txt);;G-Code Files (*.tap);;G-Code Files (*.cnc);;" \
|
||||
"G-Code Files (*.g-code);;All Files (*.*)"
|
||||
|
||||
dir_file_to_save = self.app.get_last_save_folder() + '/' + str(name)
|
||||
try:
|
||||
filename = str(QtWidgets.QFileDialog.getSaveFileName(
|
||||
filename, _ = QtWidgets.QFileDialog.getSaveFileName(
|
||||
caption="Export Machine Code ...",
|
||||
directory=self.app.get_last_save_folder() + '/' + name,
|
||||
directory=dir_file_to_save,
|
||||
filter=_filter_
|
||||
)[0])
|
||||
)
|
||||
except TypeError:
|
||||
filename = str(QtWidgets.QFileDialog.getSaveFileName(caption="Export Machine Code ...", filter=_filter_)[0])
|
||||
filename, _ = QtWidgets.QFileDialog.getSaveFileName(caption="Export Machine Code ...", filter=_filter_)
|
||||
|
||||
filename = str(filename)
|
||||
|
||||
if filename == '':
|
||||
self.app.inform.emit("[WARNING_NOTCL]Export Machine Code cancelled ...")
|
||||
|
@ -4482,6 +4503,7 @@ class FlatCAMCNCjob(FlatCAMObj, CNCjob):
|
|||
elif to_file is False:
|
||||
# Just for adding it to the recent files list.
|
||||
self.app.file_opened.emit("cncjob", filename)
|
||||
self.app.file_saved.emit("cncjob", filename)
|
||||
|
||||
self.app.inform.emit("[success] Saved to: " + filename)
|
||||
else:
|
||||
|
|
|
@ -16,6 +16,10 @@ CAD program, and create G-Code for Isolation routing.
|
|||
- fixed bug in multigeometry geometry not having the bounds in self.options and crashing the GCode generation
|
||||
- fixed bug that crashed whole application in case that the GCode editor is activated on a Tool gcode that is defective.
|
||||
- fixed bug in Excellon Slots milling: a value of a dict key was a string instead to be an int. A cast to integer solved it.
|
||||
- fixed the name self-insert in save dialog file for GCode; added protection in case the save path is None
|
||||
- fixed FlatCAM crash when trying to make drills GCode out of a file that have only slots.
|
||||
- made the shell toggle shortcut key work when focused on Selected Tab; toggle units shortcut also
|
||||
- changed the messages for Units COnversion
|
||||
|
||||
5.02.3019
|
||||
|
||||
|
|
329
camlib.py
329
camlib.py
|
@ -4549,7 +4549,7 @@ class CNCjob(Geometry):
|
|||
elif drillz == 0:
|
||||
self.app.inform.emit("[WARNING] The Cut Z parameter is zero. "
|
||||
"There will be no cut, skipping %s file" % exobj.options['name'])
|
||||
return
|
||||
return 'fail'
|
||||
else:
|
||||
self.z_cut = drillz
|
||||
|
||||
|
@ -4670,139 +4670,188 @@ class CNCjob(Geometry):
|
|||
if current_platform == '64bit':
|
||||
if excellon_optimization_type == 'M':
|
||||
log.debug("Using OR-Tools Metaheuristic Guided Local Search drill path optimization.")
|
||||
for tool in tools:
|
||||
self.tool=tool
|
||||
self.postdata['toolC']=exobj.tools[tool]["C"]
|
||||
if exobj.drills:
|
||||
for tool in tools:
|
||||
self.tool=tool
|
||||
self.postdata['toolC']=exobj.tools[tool]["C"]
|
||||
|
||||
################################################
|
||||
# Create the data.
|
||||
node_list = []
|
||||
locations = create_data_array()
|
||||
tsp_size = len(locations)
|
||||
num_routes = 1 # The number of routes, which is 1 in the TSP.
|
||||
# Nodes are indexed from 0 to tsp_size - 1. The depot is the starting node of the route.
|
||||
depot = 0
|
||||
# Create routing model.
|
||||
if tsp_size > 0:
|
||||
routing = pywrapcp.RoutingModel(tsp_size, num_routes, depot)
|
||||
search_parameters = pywrapcp.RoutingModel.DefaultSearchParameters()
|
||||
search_parameters.local_search_metaheuristic = (
|
||||
routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH)
|
||||
################################################
|
||||
# Create the data.
|
||||
node_list = []
|
||||
locations = create_data_array()
|
||||
tsp_size = len(locations)
|
||||
num_routes = 1 # The number of routes, which is 1 in the TSP.
|
||||
# Nodes are indexed from 0 to tsp_size - 1. The depot is the starting node of the route.
|
||||
depot = 0
|
||||
# Create routing model.
|
||||
if tsp_size > 0:
|
||||
routing = pywrapcp.RoutingModel(tsp_size, num_routes, depot)
|
||||
search_parameters = pywrapcp.RoutingModel.DefaultSearchParameters()
|
||||
search_parameters.local_search_metaheuristic = (
|
||||
routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH)
|
||||
|
||||
# Set search time limit in milliseconds.
|
||||
if float(self.app.defaults["excellon_search_time"]) != 0:
|
||||
search_parameters.time_limit_ms = int(
|
||||
float(self.app.defaults["excellon_search_time"]) * 1000)
|
||||
# Set search time limit in milliseconds.
|
||||
if float(self.app.defaults["excellon_search_time"]) != 0:
|
||||
search_parameters.time_limit_ms = int(
|
||||
float(self.app.defaults["excellon_search_time"]) * 1000)
|
||||
else:
|
||||
search_parameters.time_limit_ms = 3000
|
||||
|
||||
# Callback to the distance function. The callback takes two
|
||||
# arguments (the from and to node indices) and returns the distance between them.
|
||||
dist_between_locations = CreateDistanceCallback()
|
||||
dist_callback = dist_between_locations.Distance
|
||||
routing.SetArcCostEvaluatorOfAllVehicles(dist_callback)
|
||||
|
||||
# Solve, returns a solution if any.
|
||||
assignment = routing.SolveWithParameters(search_parameters)
|
||||
|
||||
if assignment:
|
||||
# Solution cost.
|
||||
log.info("Total distance: " + str(assignment.ObjectiveValue()))
|
||||
|
||||
# Inspect solution.
|
||||
# Only one route here; otherwise iterate from 0 to routing.vehicles() - 1.
|
||||
route_number = 0
|
||||
node = routing.Start(route_number)
|
||||
start_node = node
|
||||
|
||||
while not routing.IsEnd(node):
|
||||
node_list.append(node)
|
||||
node = assignment.Value(routing.NextVar(node))
|
||||
else:
|
||||
log.warning('No solution found.')
|
||||
else:
|
||||
search_parameters.time_limit_ms = 3000
|
||||
log.warning('Specify an instance greater than 0.')
|
||||
################################################
|
||||
|
||||
# Callback to the distance function. The callback takes two
|
||||
# arguments (the from and to node indices) and returns the distance between them.
|
||||
dist_between_locations = CreateDistanceCallback()
|
||||
dist_callback = dist_between_locations.Distance
|
||||
routing.SetArcCostEvaluatorOfAllVehicles(dist_callback)
|
||||
# Only if tool has points.
|
||||
if tool in points:
|
||||
# Tool change sequence (optional)
|
||||
if toolchange:
|
||||
gcode += self.doformat(p.toolchange_code,toolchangexy=(self.oldx, self.oldy))
|
||||
gcode += self.doformat(p.spindle_code) # Spindle start
|
||||
if self.dwell is True:
|
||||
gcode += self.doformat(p.dwell_code) # Dwell time
|
||||
else:
|
||||
gcode += self.doformat(p.spindle_code)
|
||||
if self.dwell is True:
|
||||
gcode += self.doformat(p.dwell_code) # Dwell time
|
||||
|
||||
# Solve, returns a solution if any.
|
||||
assignment = routing.SolveWithParameters(search_parameters)
|
||||
# Drillling!
|
||||
for k in node_list:
|
||||
locx = locations[k][0]
|
||||
locy = locations[k][1]
|
||||
|
||||
if assignment:
|
||||
# Solution cost.
|
||||
log.info("Total distance: " + str(assignment.ObjectiveValue()))
|
||||
gcode += self.doformat(p.rapid_code, x=locx, y=locy)
|
||||
gcode += self.doformat(p.down_code, x=locx, y=locy)
|
||||
gcode += self.doformat(p.up_to_zero_code, x=locx, y=locy)
|
||||
gcode += self.doformat(p.lift_code, x=locx, y=locy)
|
||||
measured_distance += abs(distance_euclidian(locx, locy, self.oldx, self.oldy))
|
||||
self.oldx = locx
|
||||
self.oldy = locy
|
||||
else:
|
||||
log.debug("camlib.CNCJob.generate_from_excellon_by_tool() --> "
|
||||
"The loaded Excellon file has no drills ...")
|
||||
self.app.inform.emit('[ERROR_NOTCL]The loaded Excellon file has no drills ...')
|
||||
return 'fail'
|
||||
|
||||
# Inspect solution.
|
||||
# Only one route here; otherwise iterate from 0 to routing.vehicles() - 1.
|
||||
route_number = 0
|
||||
node = routing.Start(route_number)
|
||||
start_node = node
|
||||
|
||||
while not routing.IsEnd(node):
|
||||
node_list.append(node)
|
||||
node = assignment.Value(routing.NextVar(node))
|
||||
else:
|
||||
log.warning('No solution found.')
|
||||
else:
|
||||
log.warning('Specify an instance greater than 0.')
|
||||
################################################
|
||||
|
||||
# Only if tool has points.
|
||||
if tool in points:
|
||||
# Tool change sequence (optional)
|
||||
if toolchange:
|
||||
gcode += self.doformat(p.toolchange_code,toolchangexy=(self.oldx, self.oldy))
|
||||
gcode += self.doformat(p.spindle_code) # Spindle start
|
||||
if self.dwell is True:
|
||||
gcode += self.doformat(p.dwell_code) # Dwell time
|
||||
else:
|
||||
gcode += self.doformat(p.spindle_code)
|
||||
if self.dwell is True:
|
||||
gcode += self.doformat(p.dwell_code) # Dwell time
|
||||
|
||||
# Drillling!
|
||||
for k in node_list:
|
||||
locx = locations[k][0]
|
||||
locy = locations[k][1]
|
||||
|
||||
gcode += self.doformat(p.rapid_code, x=locx, y=locy)
|
||||
gcode += self.doformat(p.down_code, x=locx, y=locy)
|
||||
gcode += self.doformat(p.up_to_zero_code, x=locx, y=locy)
|
||||
gcode += self.doformat(p.lift_code, x=locx, y=locy)
|
||||
measured_distance += abs(distance_euclidian(locx, locy, self.oldx, self.oldy))
|
||||
self.oldx = locx
|
||||
self.oldy = locy
|
||||
log.debug("The total travel distance with OR-TOOLS Metaheuristics is: %s" % str(measured_distance))
|
||||
elif excellon_optimization_type == 'B':
|
||||
log.debug("Using OR-Tools Basic drill path optimization.")
|
||||
for tool in tools:
|
||||
self.tool=tool
|
||||
self.postdata['toolC']=exobj.tools[tool]["C"]
|
||||
if exobj.drills:
|
||||
for tool in tools:
|
||||
self.tool=tool
|
||||
self.postdata['toolC']=exobj.tools[tool]["C"]
|
||||
|
||||
################################################
|
||||
node_list = []
|
||||
locations = create_data_array()
|
||||
tsp_size = len(locations)
|
||||
num_routes = 1 # The number of routes, which is 1 in the TSP.
|
||||
################################################
|
||||
node_list = []
|
||||
locations = create_data_array()
|
||||
tsp_size = len(locations)
|
||||
num_routes = 1 # The number of routes, which is 1 in the TSP.
|
||||
|
||||
# Nodes are indexed from 0 to tsp_size - 1. The depot is the starting node of the route.
|
||||
depot = 0
|
||||
# Nodes are indexed from 0 to tsp_size - 1. The depot is the starting node of the route.
|
||||
depot = 0
|
||||
|
||||
# Create routing model.
|
||||
if tsp_size > 0:
|
||||
routing = pywrapcp.RoutingModel(tsp_size, num_routes, depot)
|
||||
search_parameters = pywrapcp.RoutingModel.DefaultSearchParameters()
|
||||
# Create routing model.
|
||||
if tsp_size > 0:
|
||||
routing = pywrapcp.RoutingModel(tsp_size, num_routes, depot)
|
||||
search_parameters = pywrapcp.RoutingModel.DefaultSearchParameters()
|
||||
|
||||
# Callback to the distance function. The callback takes two
|
||||
# arguments (the from and to node indices) and returns the distance between them.
|
||||
dist_between_locations = CreateDistanceCallback()
|
||||
dist_callback = dist_between_locations.Distance
|
||||
routing.SetArcCostEvaluatorOfAllVehicles(dist_callback)
|
||||
# Callback to the distance function. The callback takes two
|
||||
# arguments (the from and to node indices) and returns the distance between them.
|
||||
dist_between_locations = CreateDistanceCallback()
|
||||
dist_callback = dist_between_locations.Distance
|
||||
routing.SetArcCostEvaluatorOfAllVehicles(dist_callback)
|
||||
|
||||
# Solve, returns a solution if any.
|
||||
assignment = routing.SolveWithParameters(search_parameters)
|
||||
# Solve, returns a solution if any.
|
||||
assignment = routing.SolveWithParameters(search_parameters)
|
||||
|
||||
if assignment:
|
||||
# Solution cost.
|
||||
log.info("Total distance: " + str(assignment.ObjectiveValue()))
|
||||
if assignment:
|
||||
# Solution cost.
|
||||
log.info("Total distance: " + str(assignment.ObjectiveValue()))
|
||||
|
||||
# Inspect solution.
|
||||
# Only one route here; otherwise iterate from 0 to routing.vehicles() - 1.
|
||||
route_number = 0
|
||||
node = routing.Start(route_number)
|
||||
start_node = node
|
||||
# Inspect solution.
|
||||
# Only one route here; otherwise iterate from 0 to routing.vehicles() - 1.
|
||||
route_number = 0
|
||||
node = routing.Start(route_number)
|
||||
start_node = node
|
||||
|
||||
while not routing.IsEnd(node):
|
||||
node_list.append(node)
|
||||
node = assignment.Value(routing.NextVar(node))
|
||||
while not routing.IsEnd(node):
|
||||
node_list.append(node)
|
||||
node = assignment.Value(routing.NextVar(node))
|
||||
else:
|
||||
log.warning('No solution found.')
|
||||
else:
|
||||
log.warning('No solution found.')
|
||||
else:
|
||||
log.warning('Specify an instance greater than 0.')
|
||||
################################################
|
||||
log.warning('Specify an instance greater than 0.')
|
||||
################################################
|
||||
|
||||
# Only if tool has points.
|
||||
if tool in points:
|
||||
# Tool change sequence (optional)
|
||||
if toolchange:
|
||||
gcode += self.doformat(p.toolchange_code,toolchangexy=(self.oldx, self.oldy))
|
||||
gcode += self.doformat(p.spindle_code) # Spindle start)
|
||||
if self.dwell is True:
|
||||
gcode += self.doformat(p.dwell_code) # Dwell time
|
||||
else:
|
||||
gcode += self.doformat(p.spindle_code)
|
||||
if self.dwell is True:
|
||||
gcode += self.doformat(p.dwell_code) # Dwell time
|
||||
|
||||
# Drillling!
|
||||
for k in node_list:
|
||||
locx = locations[k][0]
|
||||
locy = locations[k][1]
|
||||
gcode += self.doformat(p.rapid_code, x=locx, y=locy)
|
||||
gcode += self.doformat(p.down_code, x=locx, y=locy)
|
||||
gcode += self.doformat(p.up_to_zero_code, x=locx, y=locy)
|
||||
gcode += self.doformat(p.lift_code, x=locx, y=locy)
|
||||
measured_distance += abs(distance_euclidian(locx, locy, self.oldx, self.oldy))
|
||||
self.oldx = locx
|
||||
self.oldy = locy
|
||||
else:
|
||||
log.debug("camlib.CNCJob.generate_from_excellon_by_tool() --> "
|
||||
"The loaded Excellon file has no drills ...")
|
||||
self.app.inform.emit('[ERROR_NOTCL]The loaded Excellon file has no drills ...')
|
||||
return 'fail'
|
||||
|
||||
log.debug("The total travel distance with OR-TOOLS Basic Algorithm is: %s" % str(measured_distance))
|
||||
else:
|
||||
self.app.inform.emit("[ERROR_NOTCL] Wrong optimization type selected.")
|
||||
return 'fail'
|
||||
else:
|
||||
log.debug("Using Travelling Salesman drill path optimization.")
|
||||
for tool in tools:
|
||||
if exobj.drills:
|
||||
self.tool = tool
|
||||
self.postdata['toolC'] = exobj.tools[tool]["C"]
|
||||
|
||||
# Only if tool has points.
|
||||
if tool in points:
|
||||
# Tool change sequence (optional)
|
||||
if toolchange:
|
||||
gcode += self.doformat(p.toolchange_code,toolchangexy=(self.oldx, self.oldy))
|
||||
gcode += self.doformat(p.toolchange_code, toolchangexy=(self.oldx, self.oldy))
|
||||
gcode += self.doformat(p.spindle_code) # Spindle start)
|
||||
if self.dwell is True:
|
||||
gcode += self.doformat(p.dwell_code) # Dwell time
|
||||
|
@ -4812,52 +4861,23 @@ class CNCjob(Geometry):
|
|||
gcode += self.doformat(p.dwell_code) # Dwell time
|
||||
|
||||
# Drillling!
|
||||
for k in node_list:
|
||||
locx = locations[k][0]
|
||||
locy = locations[k][1]
|
||||
gcode += self.doformat(p.rapid_code, x=locx, y=locy)
|
||||
gcode += self.doformat(p.down_code, x=locx, y=locy)
|
||||
gcode += self.doformat(p.up_to_zero_code, x=locx, y=locy)
|
||||
gcode += self.doformat(p.lift_code, x=locx, y=locy)
|
||||
measured_distance += abs(distance_euclidian(locx, locy, self.oldx, self.oldy))
|
||||
self.oldx = locx
|
||||
self.oldy = locy
|
||||
log.debug("The total travel distance with OR-TOOLS Basic Algorithm is: %s" % str(measured_distance))
|
||||
else:
|
||||
self.app.inform.emit("[ERROR_NOTCL] Wrong optimization type selected.")
|
||||
return
|
||||
else:
|
||||
log.debug("Using Travelling Salesman drill path optimization.")
|
||||
for tool in tools:
|
||||
self.tool = tool
|
||||
self.postdata['toolC'] = exobj.tools[tool]["C"]
|
||||
altPoints = []
|
||||
for point in points[tool]:
|
||||
altPoints.append((point.coords.xy[0][0], point.coords.xy[1][0]))
|
||||
|
||||
# Only if tool has points.
|
||||
if tool in points:
|
||||
# Tool change sequence (optional)
|
||||
if toolchange:
|
||||
gcode += self.doformat(p.toolchange_code, toolchangexy=(self.oldx, self.oldy))
|
||||
gcode += self.doformat(p.spindle_code) # Spindle start)
|
||||
if self.dwell is True:
|
||||
gcode += self.doformat(p.dwell_code) # Dwell time
|
||||
for point in self.optimized_travelling_salesman(altPoints):
|
||||
gcode += self.doformat(p.rapid_code, x=point[0], y=point[1])
|
||||
gcode += self.doformat(p.down_code, x=point[0], y=point[1])
|
||||
gcode += self.doformat(p.up_to_zero_code, x=point[0], y=point[1])
|
||||
gcode += self.doformat(p.lift_code, x=point[0], y=point[1])
|
||||
measured_distance += abs(distance_euclidian(point[0], point[1], self.oldx, self.oldy))
|
||||
self.oldx = point[0]
|
||||
self.oldy = point[1]
|
||||
else:
|
||||
gcode += self.doformat(p.spindle_code)
|
||||
if self.dwell is True:
|
||||
gcode += self.doformat(p.dwell_code) # Dwell time
|
||||
|
||||
# Drillling!
|
||||
altPoints = []
|
||||
for point in points[tool]:
|
||||
altPoints.append((point.coords.xy[0][0], point.coords.xy[1][0]))
|
||||
|
||||
for point in self.optimized_travelling_salesman(altPoints):
|
||||
gcode += self.doformat(p.rapid_code, x=point[0], y=point[1])
|
||||
gcode += self.doformat(p.down_code, x=point[0], y=point[1])
|
||||
gcode += self.doformat(p.up_to_zero_code, x=point[0], y=point[1])
|
||||
gcode += self.doformat(p.lift_code, x=point[0], y=point[1])
|
||||
measured_distance += abs(distance_euclidian(point[0], point[1], self.oldx, self.oldy))
|
||||
self.oldx = point[0]
|
||||
self.oldy = point[1]
|
||||
log.debug("camlib.CNCJob.generate_from_excellon_by_tool() --> "
|
||||
"The loaded Excellon file has no drills ...")
|
||||
self.app.inform.emit('[ERROR_NOTCL]The loaded Excellon file has no drills ...')
|
||||
return 'fail'
|
||||
log.debug("The total travel distance with Travelling Salesman Algorithm is: %s" % str(measured_distance))
|
||||
|
||||
gcode += self.doformat(p.spindle_stop_code) # Spindle stop
|
||||
|
@ -4867,6 +4887,7 @@ class CNCjob(Geometry):
|
|||
log.debug("The total travel distance including travel to end position is: %s" %
|
||||
str(measured_distance) + '\n')
|
||||
self.gcode = gcode
|
||||
return 'OK'
|
||||
|
||||
def generate_from_multitool_geometry(self, geometry, append=True,
|
||||
tooldia=None, offset=0.0, tolerance=0, z_cut=1.0, z_move=2.0,
|
||||
|
|
Loading…
Reference in New Issue