From ae1aeb5a0d3dbddbd7927dca2ed303fc7560d178 Mon Sep 17 00:00:00 2001 From: sliptonic Date: Wed, 17 Oct 2018 11:31:03 -0500 Subject: [PATCH] Path: ordering works reasonably well Splitting works reasonably well --- src/Mod/Path/Gui/Resources/panels/PathEdit.ui | 12 +- src/Mod/Path/PathScripts/PathFixture.py | 8 +- src/Mod/Path/PathScripts/PathPost.py | 129 ++++++++++++++++-- src/Mod/Path/PathScripts/PathPostProcessor.py | 4 +- 4 files changed, 130 insertions(+), 23 deletions(-) diff --git a/src/Mod/Path/Gui/Resources/panels/PathEdit.ui b/src/Mod/Path/Gui/Resources/panels/PathEdit.ui index 6159a4239c..63964c629c 100644 --- a/src/Mod/Path/Gui/Resources/panels/PathEdit.ui +++ b/src/Mod/Path/Gui/Resources/panels/PathEdit.ui @@ -112,8 +112,8 @@ 0 0 - 96 - 26 + 456 + 1203 @@ -386,8 +386,8 @@ 0 0 - 356 - 893 + 456 + 1203 @@ -1105,8 +1105,8 @@ 0 0 - 325 - 180 + 456 + 1203 diff --git a/src/Mod/Path/PathScripts/PathFixture.py b/src/Mod/Path/PathScripts/PathFixture.py index 9dd94f3d91..23cf80215a 100644 --- a/src/Mod/Path/PathScripts/PathFixture.py +++ b/src/Mod/Path/PathScripts/PathFixture.py @@ -25,7 +25,8 @@ import FreeCAD import FreeCADGui import Path -from PySide import QtCore, QtGui +import PathScripts.PathUtils as PathUtils +from PySide import QtCore#, QtGui # Qt tanslation handling def translate(context, text, disambig=None): @@ -46,7 +47,10 @@ class Fixture: obj.Path = Path.Path(str(obj.Fixture)) obj.Label = "Fixture" + str(fixture) if obj.Active: - obj.Path = Path.Path(str(obj.Fixture)) + job = PathUtils.findParentJob(obj) + c1 = Path.Command(str(obj.Fixture)) + c2 = Path.Command("G0" + str(job.Stock.Shape.BoundBox.ZMax)) + obj.Path = Path.Path([c1, c2]) obj.ViewObject.Visibility = True else: obj.Path = Path.Path("(inactive operation)") diff --git a/src/Mod/Path/PathScripts/PathPost.py b/src/Mod/Path/PathScripts/PathPost.py index 71ed227f7a..013f1e7eb5 100644 --- a/src/Mod/Path/PathScripts/PathPost.py +++ b/src/Mod/Path/PathScripts/PathPost.py @@ -31,7 +31,6 @@ import Path import PathScripts.PathJob as PathJob import PathScripts.PathLog as PathLog import PathScripts.PathPreferences as PathPreferences -#import PathScripts.PathToolController as PathToolController import PathScripts.PathUtil as PathUtil import PathScripts.PathUtils as PathUtils import os @@ -43,12 +42,20 @@ from PySide import QtCore, QtGui LOG_MODULE = PathLog.thisModule() PathLog.setLevel(PathLog.Level.DEBUG, LOG_MODULE) -#PathLog.trackModule(LOG_MODULE) + # Qt tanslation handling def translate(context, text, disambig=None): return QtCore.QCoreApplication.translate(context, text, disambig) + +class _TempObject: + Path = None + Name = "Fixture" + InList = [] + Label = "Fixture" + + class DlgSelectPostProcessor: def __init__(self, parent=None): @@ -84,13 +91,16 @@ class DlgSelectPostProcessor: return posts[0].text() return None + class CommandPathPost: + subpart = 1 def resolveFileName(self, job): path = PathPreferences.defaultOutputFile() if job.PostProcessorOutputFile: path = job.PostProcessorOutputFile filename = path + if '%D' in filename: D = FreeCAD.ActiveDocument.FileName if D: @@ -116,6 +126,13 @@ class CommandPathPost: M = pref.GetString("MacroPath", FreeCAD.getUserAppDataDir()) filename = filename.replace('%M', M) + if '%s' in filename: + if job.SplitOutput: + filename = filename.replace('%s', '_'+str(self.subpart)) + self.subpart += 1 + else: + filename = filename.replace('%s', '') + policy = PathPreferences.defaultOutputPolicy() openDialog = policy == 'Open File Dialog' @@ -156,7 +173,6 @@ class CommandPathPost: dlg = DlgSelectPostProcessor() return dlg.exec_() - def GetResources(self): return {'Pixmap': 'Path-Post', 'MenuText': QtCore.QT_TRANSLATE_NOOP("Path_Post", "Post Process"), @@ -172,7 +188,7 @@ class CommandPathPost: return False - def exportObjectsWith(self, objs, job, needFilename = True): + def exportObjectsWith(self, objs, job, needFilename=True, filepart=None): PathLog.track() # check if the user has a project and has set the default post and # output filename @@ -249,41 +265,128 @@ class CommandPathPost: wcslist = job.Fixtures else: wcslist = ['G54'] - PathLog.debug("processing fixtures: {}".format(wcslist)) if hasattr(job, "OrderOutputBy"): orderby = job.OrderOutputBy else: orderby = "Operation" - PathLog.debug("Order Output by: {}".format(orderby)) if hasattr(job, "SplitOutput"): split = job.SplitOutput else: split = False - PathLog.debug("Splitting Output: {}".format(split)) postlist = [] if orderby == 'Fixture': + PathLog.debug("Ordering by Fixture") + # Order by fixture means all operations and tool changes will be completed in one + # fixture before moving to the next. + + currTool = None for f in wcslist: + # create an object to serve as the fixture path + fobj = _TempObject() c1 = Path.Command(f) c2 = Path.Command("G0 Z" + str(job.Stock.Shape.BoundBox.ZMax)) - postlist.append(Path.Path([c1, c2])) + fobj.Path = Path.Path([c1, c2]) + fobj.InList.append(job) + sublist = [fobj] - currTool = None + # Now generate the gcode for obj in job.Operations.Group: - PathLog.debug("obj: {}".format(obj.Name)) tc = PathUtil.toolControllerForOp(obj) if tc is not None: if tc.ToolNumber != currTool: - postlist.append(tc) + sublist.append(tc) + PathLog.debug("Appending TC: {}".format(tc.Name)) currTool = tc.ToolNumber - postlist.append(obj) + sublist.append(obj) + postlist.append(sublist) + + elif orderby == 'Tool': + PathLog.debug("Ordering by Tool") + # Order by tool means tool changes are minimized. + # all operations with the current tool are processed in the current + # fixture before moving to the next fixture. + + currTool = None + fixturelist = [] + for f in wcslist: + # create an object to serve as the fixture path + fobj = _TempObject() + c1 = Path.Command(f) + c2 = Path.Command("G0 Z" + str(job.Stock.Shape.BoundBox.ZMax)) + fobj.Path = Path.Path([c1, c2]) + fobj.InList.append(job) + fixturelist.append(fobj) + + # Now generate the gcode + curlist = [] # list of ops for tool, will repeat for each fixture + sublist = [] # list of ops for output splitting + + for idx, obj in enumerate(job.Operations.Group): + tc = PathUtil.toolControllerForOp(obj) + if tc is None or tc.ToolNumber == currTool: + curlist.append(obj) + elif tc.ToolNumber != currTool and currTool is None: # first TC + sublist.append(tc) + curlist.append(obj) + currTool = tc.ToolNumber + elif tc.ToolNumber != currTool and currTool is not None: # TC + for fixture in fixturelist: + sublist.append(fixture) + sublist.extend(curlist) + postlist.append(sublist) + sublist = [tc] + curlist = [obj] + currTool = tc.ToolNumber + + if idx == len(job.Operations.Group) - 1: # Last operation. + for fixture in fixturelist: + sublist.append(fixture) + sublist.extend(curlist) + postlist.append(sublist) + + elif orderby == 'Operation': + PathLog.debug("Ordering by Operation") + # Order by operation means ops are done in each fixture in + # sequence. + currTool = None + fixturelist = [] + for f in wcslist: + # create an object to serve as the fixture path + fobj = _TempObject() + c1 = Path.Command(f) + c2 = Path.Command("G0 Z" + str(job.Stock.Shape.BoundBox.ZMax)) + fobj.Path = Path.Path([c1, c2]) + fobj.InList.append(job) + fixturelist.append(fobj) + + # Now generate the gcode + for obj in job.Operations.Group: + sublist = [] + PathLog.debug("obj: {}".format(obj.Name)) + for fixture in fixturelist: + sublist.append(fixture) + tc = PathUtil.toolControllerForOp(obj) + if tc is not None: + if tc.ToolNumber != currTool: + sublist.append(tc) + currTool = tc.ToolNumber + sublist.append(obj) + postlist.append(sublist) fail = True rc = '' - (fail, rc) = self.exportObjectsWith(postlist, job) + if split: + for slist in postlist: + (fail, rc) = self.exportObjectsWith(slist, job) + else: + finalpostlist = [item for slist in postlist for item in slist] + (fail, rc) = self.exportObjectsWith(finalpostlist, job) + + self.subpart = 1 if fail: FreeCAD.ActiveDocument.abortTransaction() diff --git a/src/Mod/Path/PathScripts/PathPostProcessor.py b/src/Mod/Path/PathScripts/PathPostProcessor.py index 7676a0a777..c8eb427990 100644 --- a/src/Mod/Path/PathScripts/PathPostProcessor.py +++ b/src/Mod/Path/PathScripts/PathPostProcessor.py @@ -45,11 +45,11 @@ class PostProcessor: postname = processor + "_post" namespace = {} - + #can't modify function local scope with exec in python3 exec("import %s as current_post" % postname, namespace) current_post = namespace['current_post'] - + # make sure the script is reloaded if it was previously loaded # should the script have been imported for the first time above # then the initialization code of the script gets executed twice