diff --git a/src/Mod/Path/PathScripts/PathContour.py b/src/Mod/Path/PathScripts/PathContour.py index e7cd85783a..cbc3858b9d 100644 --- a/src/Mod/Path/PathScripts/PathContour.py +++ b/src/Mod/Path/PathScripts/PathContour.py @@ -85,8 +85,12 @@ class ObjectContour: obj.addProperty("App::PropertyDistance", "OffsetExtra", "Contour", QtCore.QT_TRANSLATE_NOOP("App::Property", "Extra value to stay away from final Contour- good for roughing toolpath")) # Debug Parameters - # obj.addProperty("App::PropertyString", "AreaParams", "Debug", QtCore.QT_TRANSLATE_NOOP("App::Property", "parameters used by PathArea")) - # obj.setEditorMode('AreaParams', 2) # hide + obj.addProperty("App::PropertyString", "AreaParams", "Path")#, QtCore.QT_TRANSLATE_NOOP("App::Property", "parameters used by PathArea")) + obj.setEditorMode('AreaParams', 2) # hide + obj.addProperty("App::PropertyString", "PathParams", "Path")#, QtCore.QT_TRANSLATE_NOOP("App::Property", "parameters used by PathArea")) + obj.setEditorMode('PathParams', 2) # hide + obj.addProperty("Part::PropertyPartShape", "removalshape", "Path")#, QtCore.QT_TRANSLATE_NOOP("App::Property", "The material to be removed")) + obj.setEditorMode('removalshape', 2) # hide if FreeCAD.GuiUp: _ViewProviderContour(obj.ViewObject) @@ -96,7 +100,8 @@ class ObjectContour: def onChanged(self, obj, prop): PathLog.track('prop: {} state: {}'.format(prop, obj.State)) - #pass + if prop in ['AreaParams', 'PathParams', 'removalshape']: + obj.setEditorMode(prop, 2) def __getstate__(self): PathLog.track() @@ -145,7 +150,7 @@ class ObjectContour: heights = [i for i in self.depthparams] PathLog.debug('depths: {}'.format(heights)) profile.setParams(**profileparams) - #obj.AreaParams = str(profile.getParams()) + obj.AreaParams = str(profile.getParams()) PathLog.debug("Contour with params: {}".format(profile.getParams())) sections = profile.makeSections(mode=0, project=True, heights=heights) @@ -169,8 +174,9 @@ class ObjectContour: elif start is not None: params['start'] = start + obj.PathParams = str(params) + (pp, end_vector) = Path.fromShapes(**params) - PathLog.debug("Generating Path with params: {}".format(params)) PathLog.debug('pp: {}, end vector: {}'.format(pp, end_vector)) self.endVector = end_vector @@ -207,6 +213,7 @@ class ObjectContour: user_depths=None) if toolLoad is None or toolLoad.ToolNumber == 0: + FreeCAD.Console.PrintError("No Tool Controller is selected. We need a tool to build a Path.") return else: @@ -229,6 +236,7 @@ class ObjectContour: commandlist.append(Path.Command("(Uncompensated Tool Path)")) parentJob = PathUtils.findParentJob(obj) + if parentJob is None: return baseobject = parentJob.Base @@ -237,6 +245,7 @@ class ObjectContour: # Let's always start by rapid to clearance...just for safety commandlist.append(Path.Command("G0", {"Z": obj.ClearanceHeight.Value})) + PathLog.track() isPanel = False if hasattr(baseobject, "Proxy"): @@ -268,6 +277,7 @@ class ObjectContour: # Let's finish by rapid to clearance...just for safety commandlist.append(Path.Command("G0", {"Z": obj.ClearanceHeight.Value})) + PathLog.track() path = Path.Path(commandlist) obj.Path = path #obj.ViewObject.Visibility = True diff --git a/src/Mod/Path/PathScripts/PathMillFace.py b/src/Mod/Path/PathScripts/PathMillFace.py index 40371e0018..610d1696a5 100644 --- a/src/Mod/Path/PathScripts/PathMillFace.py +++ b/src/Mod/Path/PathScripts/PathMillFace.py @@ -95,9 +95,12 @@ class ObjectFace: obj.addProperty("App::PropertyBool", "UseStartPoint", "Start Point", QtCore.QT_TRANSLATE_NOOP("App::Property", "make True, if specifying a Start Point")) # Debug Parameters - obj.addProperty("App::PropertyString", "AreaParams", "Debug", QtCore.QT_TRANSLATE_NOOP("App::Property", "parameters used by PathArea")) + obj.addProperty("App::PropertyString", "AreaParams", "Path")#, QtCore.QT_TRANSLATE_NOOP("App::Property", "parameters used by PathArea")) obj.setEditorMode('AreaParams', 2) # hide - obj.addProperty("Part::PropertyPartShape", "removalshape", "Debug", QtCore.QT_TRANSLATE_NOOP("App::Property", "The material to be removed")) + obj.addProperty("App::PropertyString", "PathParams", "Path")#, QtCore.QT_TRANSLATE_NOOP("App::Property", "parameters used by PathArea")) + obj.setEditorMode('PathParams', 2) # hide + obj.addProperty("Part::PropertyPartShape", "removalshape", "Path")#, QtCore.QT_TRANSLATE_NOOP("App::Property", "The material to be removed")) + obj.setEditorMode('removalshape', 2) # hide if FreeCAD.GuiUp: _ViewProviderFace(obj.ViewObject) @@ -109,6 +112,8 @@ class ObjectFace: if prop == "StepOver": if obj.StepOver == 0: obj.StepOver = 1 + if prop in ['AreaParams', 'PathParams', 'removalshape']: + obj.setEditorMode(prop, 2) def __getstate__(self): return None @@ -199,28 +204,32 @@ class ObjectFace: heights = [i for i in self.depthparams] boundary.setParams(**pocketparams) obj.AreaParams = str(boundary.getParams()) - #PathLog.track('areaparams: {}'.format(obj.AreaParams)) - PathLog.track('height: {}'.format(heights)) sections = boundary.makeSections(mode=0, project=False, heights=heights) - shapelist = [sec.getShape() for sec in sections] - params = {'shapes': shapelist, - 'feedrate': self.horizFeed, + params = {'feedrate': self.horizFeed, 'feedrate_v': self.vertFeed, 'verbose': True, 'resume_height': obj.StepDown, 'retraction': obj.ClearanceHeight.Value} pp = [] + if obj.UseStartPoint: params['start'] = obj.StartPoint # pp.append(Path.Command("G0", {"X":obj.StartPoint.x, "Y":obj.StartPoint.y, "Z":obj.StartPoint.z})) - + #store the params for debugging. Don't need the shape. + obj.PathParams = str(params) PathLog.debug("Generating Path with params: {}".format(params)) - respath = Path.fromShapes(**params) - pp.extend(respath.Commands) - respath.Commands = pp + + for sec in sections: + shape = sec.getShape() + respath = Path.fromShapes(shape, **params) + #Insert any entry code to the layer + + #append the layer path + pp.extend(respath.Commands) + respath.Commands = pp return respath @@ -380,7 +389,7 @@ class CommandPathMillFace: FreeCADGui.doCommand('obj.Active = True') FreeCADGui.doCommand('obj.StepOver = 50') - #FreeCADGui.doCommand('obj.StepDown = 1.0') + FreeCADGui.doCommand('obj.StepDown = 1.0') FreeCADGui.doCommand('obj.ZigZagAngle = 45.0') FreeCAD.ActiveDocument.commitTransaction() diff --git a/src/Mod/Path/PathScripts/PathPocket.py b/src/Mod/Path/PathScripts/PathPocket.py index 1926bf9f4d..82cb7ac141 100644 --- a/src/Mod/Path/PathScripts/PathPocket.py +++ b/src/Mod/Path/PathScripts/PathPocket.py @@ -77,21 +77,28 @@ class ObjectPocket: obj.addProperty("App::PropertyFloat", "ZigZagAngle", "Pocket", QtCore.QT_TRANSLATE_NOOP("App::Property", "Angle of the zigzag pattern")) obj.addProperty("App::PropertyEnumeration", "OffsetPattern", "Face", QtCore.QT_TRANSLATE_NOOP("App::Property", "clearing pattern to use")) obj.OffsetPattern = ['ZigZag', 'Offset', 'Spiral', 'ZigZagOffset', 'Line', 'Grid', 'Triangle'] + obj.addProperty("App::PropertyBool", "MinTravel", "Pocket", QtCore.QT_TRANSLATE_NOOP("App::Property", "Use 3D Sorting of Path")) # Start Point Properties obj.addProperty("App::PropertyVector", "StartPoint", "Start Point", QtCore.QT_TRANSLATE_NOOP("App::Property", "The start point of this path")) obj.addProperty("App::PropertyBool", "UseStartPoint", "Start Point", QtCore.QT_TRANSLATE_NOOP("App::Property", "make True, if specifying a Start Point")) # Debug Parameters - obj.addProperty("App::PropertyString", "AreaParams", "Debug", QtCore.QT_TRANSLATE_NOOP("App::Property", "parameters used by PathArea")) + obj.addProperty("App::PropertyString", "AreaParams", "Path")#, QtCore.QT_TRANSLATE_NOOP("App::Property", "parameters used by PathArea")) obj.setEditorMode('AreaParams', 2) # hide + obj.addProperty("App::PropertyString", "PathParams", "Path")#, QtCore.QT_TRANSLATE_NOOP("App::Property", "parameters used by PathArea")) + obj.setEditorMode('PathParams', 2) # hide + obj.addProperty("Part::PropertyPartShape", "removalshape", "Path")#, QtCore.QT_TRANSLATE_NOOP("App::Property", "The material to be removed")) + obj.setEditorMode('removalshape', 2) # hide if FreeCAD.GuiUp: ViewProviderPocket(obj.ViewObject) obj.Proxy = self def onChanged(self, obj, prop): - pass + if prop in ['AreaParams', 'PathParams', 'removalshape']: + obj.setEditorMode(prop, 2) + def __getstate__(self): return None @@ -211,6 +218,17 @@ class ObjectPocket: 'resume_height': obj.StepDown.Value, 'retraction': obj.ClearanceHeight.Value} + if obj.UseStartPoint: + params['start'] = obj.StartPoint + + #if MinTravel is turned on, set path sorting to 3DSort + # 3DSort shouldn't be used without a valid start point. Can cause + # tool crash without it. + if obj.MinTravel: + params['sort_mode'] = 2 + + storeparams = {key: value for key, value in params.items() if key != 'shapes'} + obj.PathParams = str(storeparams) pp = Path.fromShapes(**params) PathLog.debug("Generating Path with params: {}".format(params)) PathLog.debug(pp) @@ -282,14 +300,10 @@ class ObjectPocket: shape = Part.makeFace(edges, 'Part::FaceMakerSimple') env = PathUtils.getEnvelope(baseobject.Shape, subshape=shape, depthparams=self.depthparams) - removal = env.cut(baseobject.Shape) - - if PathLog.getLevel(PathLog.thisModule()) == PathLog.Level.DEBUG: - removalshape=FreeCAD.ActiveDocument.addObject("Part::Feature","removalshape") - removalshape.Shape = removal + obj.removalshape = env.cut(baseobject.Shape) try: - (pp, sim) = self._buildPathArea(obj, removal, getsim=getsim) + (pp, sim) = self._buildPathArea(obj, obj.removalshape, getsim=getsim) if sim is not None: simlist.append(sim) commandlist.extend(pp.Commands) @@ -300,12 +314,9 @@ class ObjectPocket: PathLog.debug("processing the whole job base object") env = PathUtils.getEnvelope(baseobject.Shape, subshape=None, depthparams=self.depthparams) - removal = env.cut(baseobject.Shape) - if PathLog.getLevel(PathLog.thisModule()) == PathLog.Level.DEBUG: - removalshape=FreeCAD.ActiveDocument.addObject("Part::Feature","removalshape") - removalshape.Shape = removal + obj.removalshape = env.cut(baseobject.Shape) try: - (pp, sim) = self._buildPathArea(obj, removal, getsim=getsim) + (pp, sim) = self._buildPathArea(obj, obj.removalshape, getsim=getsim) commandlist.extend(pp.Commands) if sim is not None: simlist.append(sim) diff --git a/src/Mod/Path/PathTests/TestPathPost.py b/src/Mod/Path/PathTests/TestPathPost.py index 7327ce0449..6129a50ca4 100644 --- a/src/Mod/Path/PathTests/TestPathPost.py +++ b/src/Mod/Path/PathTests/TestPathPost.py @@ -34,20 +34,15 @@ import difflib import unittest class PathPostTestCases(unittest.TestCase): + def setUp(self): self.doc = FreeCAD.newDocument("PathPostTest") - - def tearDown(self): - FreeCAD.closeDocument("PathPostTest") - - def testLinuxCNC(self): - # first create something to generate a path for box = self.doc.addObject("Part::Box", "Box") # Create job and setup tool library + default tool - job = self.doc.addObject("Path::FeatureCompoundPython", "Job") - PathScripts.PathJob.ObjectPathJob(job, box, None) - PathScripts.PathToolController.CommandPathToolController.Create(job.Name, False) + self.job = self.doc.addObject("Path::FeatureCompoundPython", "Job") + PathScripts.PathJob.ObjectPathJob(self.job, box, None) + PathScripts.PathToolController.CommandPathToolController.Create(self.job.Name, False) tool1 = Path.Tool() tool1.Diameter = 5.0 tool1.Name = "Default Tool" @@ -82,11 +77,17 @@ class PathPostTestCases(unittest.TestCase): PathScripts.PathContour.ObjectContour.setDepths(contour.Proxy, contour) self.doc.recompute() - job.PostProcessor = 'linuxcnc' - job.PostProcessorArgs = '--no-header --no-line-numbers --no-comments --no-show-editor --output-precision=2' + def tearDown(self): + FreeCAD.closeDocument("PathPostTest") + + def testLinuxCNC(self): + # first create something to generate a path for + + self.job.PostProcessor = 'linuxcnc' + self.job.PostProcessorArgs = '--no-header --no-line-numbers --no-comments --no-show-editor --output-precision=2' post = PathScripts.PathPost.CommandPathPost() - (fail, gcode) = post.exportObjectsWith([job], job, False) + (fail, gcode) = post.exportObjectsWith([self.job], self.job, False) self.assertFalse(fail) referenceFile = FreeCAD.getHomePath() + 'Mod/Path/PathTests/test_linuxcnc_00.ngc'