From cc4abd21b91d013ad88dfe0d72c66aa012dc952d Mon Sep 17 00:00:00 2001 From: sliptonic Date: Fri, 2 Jun 2017 16:00:41 -0500 Subject: [PATCH] Path: usecomp setting toggles the availability of the side property --- .../Path/Gui/Resources/panels/ProfileEdit.ui | 36 +----- src/Mod/Path/PathScripts/PathContour.py | 67 ++++++----- src/Mod/Path/PathScripts/PathMillFace.py | 22 ++-- src/Mod/Path/PathScripts/PathPocket.py | 57 ++++----- src/Mod/Path/PathScripts/PathProfile.py | 110 +++++++++--------- src/Mod/Path/PathScripts/PathProfileEdges.py | 31 ++++- src/Mod/Path/PathScripts/PathUtils.py | 43 ++++--- 7 files changed, 194 insertions(+), 172 deletions(-) diff --git a/src/Mod/Path/Gui/Resources/panels/ProfileEdit.ui b/src/Mod/Path/Gui/Resources/panels/ProfileEdit.ui index 5964a1104e..29a8b48385 100644 --- a/src/Mod/Path/Gui/Resources/panels/ProfileEdit.ui +++ b/src/Mod/Path/Gui/Resources/panels/ProfileEdit.ui @@ -33,8 +33,8 @@ 0 0 - 381 - 381 + 285 + 277 @@ -111,8 +111,8 @@ 0 0 - 381 - 381 + 120 + 96 @@ -178,8 +178,8 @@ 0 0 - 381 - 381 + 154 + 68 @@ -343,13 +343,6 @@ - - - - Roll Radius - - - @@ -360,16 +353,6 @@ - - - - 0.000000000000000 - - - mm - - - @@ -390,13 +373,6 @@ - - - - Use End Point - - - diff --git a/src/Mod/Path/PathScripts/PathContour.py b/src/Mod/Path/PathScripts/PathContour.py index 34f2e48d4a..3c1ab1870d 100644 --- a/src/Mod/Path/PathScripts/PathContour.py +++ b/src/Mod/Path/PathScripts/PathContour.py @@ -34,8 +34,8 @@ from PathScripts.PathUtils import waiting_effects from PathScripts.PathUtils import makeWorkplane LOG_MODULE = 'PathContour' -PathLog.setLevel(PathLog.Level.INFO, LOG_MODULE) -#PathLog.trackModule('PathContour') +PathLog.setLevel(PathLog.Level.DEBUG, LOG_MODULE) +PathLog.trackModule('PathContour') FreeCAD.setLogLevel('Path.Area', 0) if FreeCAD.GuiUp: @@ -77,9 +77,9 @@ class ObjectContour: obj.addProperty("App::PropertyEnumeration", "Direction", "Contour", QtCore.QT_TRANSLATE_NOOP("App::Property", "The direction that the toolpath should go around the part ClockWise CW or CounterClockWise CCW")) obj.Direction = ['CW', 'CCW'] # this is the direction that the Contour runs obj.addProperty("App::PropertyBool", "UseComp", "Contour", QtCore.QT_TRANSLATE_NOOP("App::Property", "make True, if using Cutter Radius Compensation")) - obj.addProperty("App::PropertyEnumeration", "Side", "Contour", QtCore.QT_TRANSLATE_NOOP("App::Property", "Side of edge that tool should cut")) - obj.Side = ['Left', 'Right', 'On'] # side of profile that cutter is on in relation to direction of profile - obj.setEditorMode('Side', 2) # hide + # obj.addProperty("App::PropertyEnumeration", "Side", "Contour", QtCore.QT_TRANSLATE_NOOP("App::Property", "Side of edge that tool should cut")) + # obj.Side = ['Left', 'Right'] # side of profile that cutter is on in relation to direction of profile + # obj.setEditorMode('Side', 2) # hide obj.addProperty("App::PropertyDistance", "OffsetExtra", "Contour", QtCore.QT_TRANSLATE_NOOP("App::Property", "Extra value to stay away from final Contour- good for roughing toolpath")) @@ -94,8 +94,11 @@ class ObjectContour: def onChanged(self, obj, prop): pass - # if prop in ['ClearanceHeight', 'StartPoint']: - # obj.StartPoint.z = obj.ClearanceHeight.Value + # if prop == "UseComp": + # if not obj.UseComp: + # obj.setEditorMode('Side', 2) + # else: + # obj.setEditorMode('Side', 0) def setDepths(proxy, obj): PathLog.track() @@ -171,22 +174,22 @@ class ObjectContour: PathLog.debug('pp: {}, end vector: {}'.format(pp, end_vector)) self.endVector = end_vector - if True: - from PathScripts.PathUtils import CollisionTester - parentJob = PathUtils.findParentJob(obj) - if parentJob is None: - pass - base = parentJob.Base - if base is None: - pass +# if True: +# from PathScripts.PathUtils import CollisionTester +# parentJob = PathUtils.findParentJob(obj) +# if parentJob is None: +# pass +# base = parentJob.Base +# if base is None: +# pass - profileparams['Thicken'] = True #{'Fill':0, 'Coplanar':0, 'Project':True, 'SectionMode':2, 'Thicken':True} - profileparams['ToolRadius']= self.radius - self.radius *.005 - profile.setParams(**profileparams) - sec = profile.makeSections(heights=[0.0])[0].getShape() - cutPath = sec.extrude(FreeCAD.Vector(0,0,baseobject.BoundBox.ZMax)) - c = CollisionTester() - c.getCollisionSim(base.Shape, cutPath) +# profileparams['Thicken'] = True #{'Fill':0, 'Coplanar':0, 'Project':True, 'SectionMode':2, 'Thicken':True} +# profileparams['ToolRadius']= self.radius - self.radius *.005 +# profile.setParams(**profileparams) +# sec = profile.makeSections(heights=[0.0])[0].getShape() +# cutPath = sec.extrude(FreeCAD.Vector(0,0,baseobject.BoundBox.ZMax)) +# c = CollisionTester() +# c.getCollisionSim(base.Shape, cutPath) return pp @@ -194,6 +197,12 @@ class ObjectContour: PathLog.track() self.endVector = None + if not obj.Active: + path = Path.Path("(inactive operation)") + obj.Path = path + obj.ViewObject.Visibility = False + return + commandlist = [] toolLoad = obj.ToolController @@ -244,22 +253,16 @@ class ObjectContour: FreeCAD.Console.PrintError("Something unexpected happened. Unable to generate a contour path. Check project and tool config.") else: bb = baseobject.Shape.BoundBox - env = PathUtils.getEnvelope(partshape=baseobject.Shape, stockheight=bb.ZLength + (obj.StartDepth.Value-bb.ZMax)) + env = PathUtils.getEnvelope(partshape=baseobject.Shape, subshape=None, stockheight=bb.ZLength + (obj.StartDepth.Value-bb.ZMax)) try: commandlist.extend(self._buildPathArea(obj, env, start=obj.StartPoint).Commands) except Exception as e: print(e) FreeCAD.Console.PrintError("Something unexpected happened. Unable to generate a contour path. Check project and tool config.") - if obj.Active: - path = Path.Path(commandlist) - obj.Path = path - if obj.ViewObject: - obj.ViewObject.Visibility = True - else: - path = Path.Path("(inactive operation)") - obj.Path = path - obj.ViewObject.Visibility = False + path = Path.Path(commandlist) + obj.Path = path + obj.ViewObject.Visibility = True class _ViewProviderContour: diff --git a/src/Mod/Path/PathScripts/PathMillFace.py b/src/Mod/Path/PathScripts/PathMillFace.py index b221dd2a46..8c224aeb1c 100644 --- a/src/Mod/Path/PathScripts/PathMillFace.py +++ b/src/Mod/Path/PathScripts/PathMillFace.py @@ -226,6 +226,12 @@ class ObjectFace: def execute(self, obj): PathLog.track() + if not obj.Active: + path = Path.Path("(inactive operation)") + obj.Path = path + obj.ViewObject.Visibility = False + return + commandlist = [] toolLoad = obj.ToolController @@ -288,18 +294,12 @@ class ObjectFace: try: commandlist.extend(self._buildPathArea(obj, env).Commands) except Exception as e: - print(e) - FreeCAD.Console.PrintWarning(translate("Path_MillFace", "The selected settings did not produce a valid path.\n")) + FreeCAD.Console.PrintError(e) + FreeCAD.Console.PrintError(translate("Path_MillFace", "The selected settings did not produce a valid path.\n")) - if obj.Active: - path = Path.Path(commandlist) - obj.Path = path - if obj.ViewObject: - obj.ViewObject.Visibility = True - else: - path = Path.Path("(inactive operation)") - obj.Path = path - obj.ViewObject.Visibility = False + path = Path.Path(commandlist) + obj.Path = path + obj.ViewObject.Visibility = True class _CommandSetFaceStartPoint: diff --git a/src/Mod/Path/PathScripts/PathPocket.py b/src/Mod/Path/PathScripts/PathPocket.py index c34a8c2c97..358bec96bc 100644 --- a/src/Mod/Path/PathScripts/PathPocket.py +++ b/src/Mod/Path/PathScripts/PathPocket.py @@ -37,14 +37,16 @@ if FreeCAD.GuiUp: """Path Pocket object and FreeCAD command""" LOG_MODULE = 'PathPocket' -PathLog.setLevel(PathLog.Level.DEBUG, LOG_MODULE) -PathLog.trackModule('PathPocket') -FreeCAD.setLogLevel('Path.Area',0) +PathLog.setLevel(PathLog.Level.INFO, LOG_MODULE) +#PathLog.trackModule('PathPocket') +FreeCAD.setLogLevel('Path.Area', 0) + # Qt tanslation handling def translate(context, text, disambig=None): return QtCore.QCoreApplication.translate(context, text, disambig) + class ObjectPocket: def __init__(self, obj): @@ -75,7 +77,6 @@ class ObjectPocket: 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'] - # 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")) @@ -163,11 +164,11 @@ class ObjectPocket: return None @waiting_effects - def _buildPathArea(self, obj, baseobject): + def _buildPathArea(self, obj, envelopeshape): PathLog.track() pocket = Path.Area() pocket.setPlane(Part.makeCircle(10)) - pocket.add(baseobject) + pocket.add(envelopeshape) stepover = (self.radius * 2) * (float(obj.StepOver)/100) @@ -205,16 +206,11 @@ class ObjectPocket: 'resume_height': obj.StepDown.Value, 'retraction': obj.ClearanceHeight.Value} - - # if obj.UseStartPoint is True and obj.StartPoint is not None: - # params['start'] = obj.StartPoint - pp = Path.fromShapes(**params) PathLog.debug("Generating Path with params: {}".format(params)) PathLog.debug(pp) return pp - def execute(self, obj): PathLog.track() commandlist = [] @@ -225,6 +221,13 @@ class ObjectPocket: obj.ViewObject.Visibility = False return + parentJob = PathUtils.findParentJob(obj) + if parentJob is None: + return + baseobject = parentJob.Base + if baseobject is None: + return + toolLoad = obj.ToolController if toolLoad is None or toolLoad.ToolNumber == 0: FreeCAD.Console.PrintError("No Tool Controller is selected. We need a tool to build a Path.") @@ -251,25 +254,20 @@ class ObjectPocket: edges = [getattr(b[0].Shape, sub) for sub in b[1]] shape = Part.makeFace(edges, 'Part::FaceMakerSimple') - env = PathUtils.getEnvelope(shape, obj.StartDepth) + env = PathUtils.getEnvelope(baseobject.Shape, subshape=shape, stockheight=obj.StartDepth) try: - commandlist.extend(self._buildPathArea(obj, env.cut(b[0].Shape)).Commands) + commandlist.extend(self._buildPathArea(obj, env.cut(baseobject.Shape)).Commands) except Exception as e: - print(e) + FreeCAD.Console.PrintError(e) FreeCAD.Console.PrintError("Something unexpected happened. Unable to generate a pocket path. Check project and tool config.") else: # process the job base object as a whole PathLog.debug("processing the whole job base object") - parentJob = PathUtils.findParentJob(obj) - if parentJob is None: - return - baseobject = parentJob.Base - if baseobject is None: - return - env = PathUtils.getEnvelope(baseobject.Shape, obj.StartDepth) + + env = PathUtils.getEnvelope(baseobject.Shape, subshape=None, stockheight=obj.StartDepth) try: commandlist.extend(self._buildPathArea(obj, env.cut(baseobject.Shape)).Commands) except Exception as e: - print(e) + FreeCAD.Console.PrintError(e) FreeCAD.Console.PrintError("Something unexpected happened. Unable to generate a pocket path. Check project and tool config.") path = Path.Path(commandlist) @@ -362,7 +360,7 @@ class CommandPathPocket: FreeCADGui.doCommand('obj.ToolController = PathScripts.PathUtils.findToolController(obj)') FreeCAD.ActiveDocument.commitTransaction() - #FreeCAD.ActiveDocument.recompute() + # FreeCAD.ActiveDocument.recompute() FreeCADGui.doCommand('obj.ViewObject.startEditing()') @@ -403,6 +401,8 @@ class TaskPanel: self.obj.UseStartPoint = self.form.useStartPoint.isChecked() if hasattr(self.obj, "CutMode"): self.obj.CutMode = str(self.form.cutMode.currentText()) + if hasattr(self.obj, "OffsetPattern"): + self.obj.OffsetPattern = str(self.form.offsetpattern.currentText()) if hasattr(self.obj, "ZigZagAngle"): self.obj.ZigZagAngle = FreeCAD.Units.Quantity(self.form.zigZagAngle.text()).Value if hasattr(self.obj, "StepOver"): @@ -425,11 +425,12 @@ class TaskPanel: self.form.zigZagAngle.setText(FreeCAD.Units.Quantity(self.obj.ZigZagAngle, FreeCAD.Units.Angle).UserString) self.form.stepOverPercent.setValue(self.obj.StepOver) - # index = self.form.algorithmSelect.findText(self.obj.Algorithm, QtCore.Qt.MatchFixedString) - # if index >= 0: - # self.form.algorithmSelect.blockSignals(True) - # self.form.algorithmSelect.setCurrentIndex(index) - # self.form.algorithmSelect.blockSignals(False) + index = self.form.offsetpattern.findText( + self.obj.OffsetPattern, QtCore.Qt.MatchFixedString) + if index >= 0: + self.form.offsetpattern.blockSignals(True) + self.form.offsetpattern.setCurrentIndex(index) + self.form.offsetpattern.blockSignals(False) index = self.form.cutMode.findText( self.obj.CutMode, QtCore.Qt.MatchFixedString) diff --git a/src/Mod/Path/PathScripts/PathProfile.py b/src/Mod/Path/PathScripts/PathProfile.py index 4b2b7f0fd4..215264e2ba 100644 --- a/src/Mod/Path/PathScripts/PathProfile.py +++ b/src/Mod/Path/PathScripts/PathProfile.py @@ -34,7 +34,7 @@ import PathScripts.PathLog as PathLog LOG_MODULE = 'PathProfile' PathLog.setLevel(PathLog.Level.INFO, LOG_MODULE) -# PathLog.trackModule('PathProfile') +PathLog.trackModule('PathProfile') FreeCAD.setLogLevel('Path.Area', 0) if FreeCAD.GuiUp: @@ -76,7 +76,7 @@ class ObjectProfile: # Profile Properties obj.addProperty("App::PropertyEnumeration", "Side", "Profile", QtCore.QT_TRANSLATE_NOOP("App::Property", "Side of edge that tool should cut")) - obj.Side = ['Left', 'Right', 'On'] # side of profile that cutter is on in relation to direction of profile + obj.Side = ['Left', 'Right'] # side of profile that cutter is on in relation to direction of profile obj.addProperty("App::PropertyEnumeration", "Direction", "Profile", QtCore.QT_TRANSLATE_NOOP("App::Property", "The direction that the toolpath should go around the part ClockWise CW or CounterClockWise CCW")) obj.Direction = ['CW', 'CCW'] # this is the direction that the profile runs obj.addProperty("App::PropertyBool", "UseComp", "Profile", QtCore.QT_TRANSLATE_NOOP("App::Property", "make True, if using Cutter Radius Compensation")) @@ -94,7 +94,11 @@ class ObjectProfile: return None def onChanged(self, obj, prop): - pass + if prop == "UseComp": + if not obj.UseComp: + obj.setEditorMode('Side', 2) + else: + obj.setEditorMode('Side', 0) def addprofilebase(self, obj, ss, sub=""): baselist = obj.Base @@ -135,22 +139,29 @@ class ObjectProfile: obj.Base = baselist self.execute(obj) - def _buildPathArea(self, obj, baseobject, isHole, start=None): + def _buildPathArea(self, obj, baseobject, isHole=False, start=None): PathLog.track() profile = Path.Area() profile.setPlane(Part.makeCircle(10)) profile.add(baseobject) profileparams = {'Fill': 0, - 'Coplanar': 0, + 'Coplanar': 2, 'Offset': 0.0, 'SectionCount': -1} + offsetval = 0 + if obj.UseComp: - if isHole: - profileparams['Offset'] = 0 - self.radius+obj.OffsetExtra.Value - else: - profileparams['Offset'] = self.radius+obj.OffsetExtra.Value + offsetval = self.radius+obj.OffsetExtra.Value + + if obj.Side == 'Right': + offsetval = 0 - offsetval + + if isHole: + offsetval = 0 - offsetval + + profileparams['Offset'] = offsetval profile.setParams(**profileparams) # PathLog.debug("About to profile with params: {}".format(profileparams)) @@ -175,7 +186,7 @@ class ObjectProfile: 'resume_height': obj.StepDown.Value, 'retraction': obj.ClearanceHeight.Value} - # Reverse the direction for holes + #Reverse the direction for holes if isHole: direction = "CW" if obj.Direction == "CCW" else "CCW" else: @@ -197,8 +208,14 @@ class ObjectProfile: def execute(self, obj): import Part - commandlist = [] + if not obj.Active: + path = Path.Path("(inactive operation)") + obj.Path = path + obj.ViewObject.Visibility = False + return + + commandlist = [] toolLoad = obj.ToolController if toolLoad is None or toolLoad.ToolNumber == 0: FreeCAD.Console.PrintError("No Tool Controller is selected. We need a tool to build a Path.") @@ -222,7 +239,14 @@ class ObjectProfile: else: commandlist.append(Path.Command("(Uncompensated Tool Path)")) - if obj.Base: + parentJob = PathUtils.findParentJob(obj) + if parentJob is None: + return + baseobject = parentJob.Base + if baseobject is None: + return + + if obj.Base: # The user has selected subobjects from the base. Process each. holes = [] faces = [] for b in obj.Base: @@ -233,46 +257,34 @@ class ObjectProfile: if numpy.isclose(abs(shape.normalAt(0, 0).z), 1): # horizontal face holes += shape.Wires[1:] else: - print ("found a base object which is not a face. Can't continue.") + FreeCAD.Console.PrintWarning ("found a base object which is not a face. Can't continue.") return if obj.processHoles: for wire in holes: f = Part.makeFace(wire, 'Part::FaceMakerSimple') + drillable = PathUtils.isDrillable(baseobject.Shape, wire) + if (drillable and obj.processCircles) or (not drillable and obj.processHoles): - # shift the compound to the bottom of the base object for - # proper sectioning - zShift = b[0].Shape.BoundBox.ZMin - f.BoundBox.ZMin - newPlace = FreeCAD.Placement(FreeCAD.Vector(0, 0, zShift), f.Placement.Rotation) - f.Placement = newPlace - env = PathUtils.getEnvelope(f, obj.StartDepth) - try: - commandlist.extend(self._buildPathArea(obj, baseobject=env, isHole=True, start=None).Commands) - except Exception as e: - print(e) - FreeCAD.Console.PrintError("Something unexpected happened. Unable to generate a contour path. Check project and tool config.") + env = PathUtils.getEnvelope(baseobject.Shape, subshape=f, stockheight=obj.StartDepth) + try: + commandlist.extend(self._buildPathArea(obj, baseobject=env, isHole=True, start=None).Commands) + except Exception as e: + FreeCAD.Console.PrintError(e) + FreeCAD.Console.PrintError("Something unexpected happened. Unable to generate a contour path. Check project and tool config.") - profileshape = Part.makeCompound(faces) - zShift = b[0].Shape.BoundBox.ZMin - profileshape.BoundBox.ZMin - newPlace = FreeCAD.Placement(FreeCAD.Vector(0, 0, zShift), profileshape.Placement.Rotation) - profileshape.Placement = newPlace + if len(faces) > 0: + profileshape = Part.makeCompound(faces) if obj.processPerimeter: - env = PathUtils.getEnvelope(profileshape, obj.StartDepth) + env = PathUtils.getEnvelope(baseobject.Shape, subshape=profileshape, stockheight=obj.StartDepth) try: - commandlist.extend(self._buildPathArea(obj, baseobject=env, isHole=False, start=None).Commands) + commandlist.extend(self._buildPathArea(obj, baseobject=env, start=None).Commands) except Exception as e: - print(e) + FreeCAD.Console.PrintError(e) FreeCAD.Console.PrintError("Something unexpected happened. Unable to generate a contour path. Check project and tool config.") - else: # Try to build targets frorm the job base - parentJob = PathUtils.findParentJob(obj) - if parentJob is None: - return - baseobject = parentJob.Base - if baseobject is None: - return - + else: # Try to build targets from the job base if hasattr(baseobject, "Proxy"): if isinstance(baseobject.Proxy, ArchPanel.PanelSheet): # process the sheet if obj.processPerimeter: @@ -280,11 +292,11 @@ class ObjectProfile: for shape in shapes: for wire in shape.Wires: f = Part.makeFace(wire, 'Part::FaceMakerSimple') - env = PathUtils.getEnvelope(f, obj.StartDepth) + env = PathUtils.getEnvelope(baseobject.Shape, subshape=f, stockheight=obj.StartDepth) try: commandlist.extend(self._buildPathArea(obj, baseobject=env, isHole=False, start=None).Commands) except Exception as e: - print(e) + FreeCAD.Console.PrintError(e) FreeCAD.Console.PrintError("Something unexpected happened. Unable to generate a contour path. Check project and tool config.") shapes = baseobject.Proxy.getHoles(baseobject, transform=True) @@ -293,22 +305,16 @@ class ObjectProfile: drillable = PathUtils.isDrillable(baseobject.Proxy, wire) if (drillable and obj.processCircles) or (not drillable and obj.processHoles): f = Part.makeFace(wire, 'Part::FaceMakerSimple') - env = PathUtils.getEnvelope(f, obj.StartDepth) + env = PathUtils.getEnvelope(baseobject.Shape, subshape=f, stockheight=obj.StartDepth) try: commandlist.extend(self._buildPathArea(obj, baseobject=env, isHole=True, start=None).Commands) except Exception as e: - print(e) + FreeCAD.Console.PrintError(e) FreeCAD.Console.PrintError("Something unexpected happened. Unable to generate a contour path. Check project and tool config.") - if obj.Active: - path = Path.Path(commandlist) - obj.Path = path - obj.ViewObject.Visibility = True - - else: - path = Path.Path("(inactive operation)") - obj.Path = path - obj.ViewObject.Visibility = False + path = Path.Path(commandlist) + obj.Path = path + obj.ViewObject.Visibility = True class _ViewProviderProfile: diff --git a/src/Mod/Path/PathScripts/PathProfileEdges.py b/src/Mod/Path/PathScripts/PathProfileEdges.py index 4add9e0148..f58d502913 100644 --- a/src/Mod/Path/PathScripts/PathProfileEdges.py +++ b/src/Mod/Path/PathScripts/PathProfileEdges.py @@ -28,6 +28,7 @@ import Part from PathScripts import PathUtils from PathScripts.PathUtils import depth_params from DraftGeomUtils import findWires +from DraftGeomUtils import isReallyClosed import PathScripts.PathLog as PathLog from PathScripts.PathUtils import waiting_effects @@ -92,7 +93,11 @@ class ObjectProfile: return None def onChanged(self, obj, prop): - pass + if prop == "UseComp": + if not obj.UseComp: + obj.setEditorMode('Side', 2) + else: + obj.setEditorMode('Side', 0) def addprofilebase(self, obj, ss, sub=""): baselist = obj.Base @@ -218,6 +223,12 @@ class ObjectProfile: obj.ViewObject.Visibility = False return + parentJob = PathUtils.findParentJob(obj) + if parentJob is None: + return + baseobject = parentJob.Base + if baseobject is None: + return toolLoad = obj.ToolController if toolLoad is None or toolLoad.ToolNumber == 0: @@ -235,12 +246,12 @@ class ObjectProfile: self.radius = tool.Diameter/2 commandlist.append(Path.Command("(" + obj.Label + ")")) - + if obj.UseComp: commandlist.append(Path.Command("(Compensated Tool Path. Diameter: " + str(self.radius * 2) + ")")) else: commandlist.append(Path.Command("(Uncompensated Tool Path)")) - + if obj.Base: wires = [] @@ -258,14 +269,14 @@ class ObjectProfile: zShift = b[0].Shape.BoundBox.ZMin - f.BoundBox.ZMin newPlace = FreeCAD.Placement(FreeCAD.Vector(0, 0, zShift), f.Placement.Rotation) f.Placement = newPlace - env = PathUtils.getEnvelope(f, obj.StartDepth) + env = PathUtils.getEnvelope(baseobject.Shape, subshape=f, stockheight=obj.StartDepth) try: # commandlist.extend(self._buildPathArea(obj, wire).Commands) commandlist.extend(self._buildPathArea(obj, baseobject=env, start=None).Commands) - + except Exception as e: - print(e) + FreeCAD.Console.PrintError(e) FreeCAD.Console.PrintError("Something unexpected happened. Unable to generate a contour path. Check project and tool config.") path = Path.Path(commandlist) @@ -492,6 +503,14 @@ class TaskPanel: if not selection[0].SubObjects[0].ShapeType == "Edge": FreeCAD.Console.PrintError(translate("PathProject", "Please select one or more edges from the Base model\n")) return + try: + theWire = Part.Wire(sel.SubObjects) + except: + FreeCAD.Console.PrintError(translate("PathProject", "The selected edges don't form a closed loop\n")) + return + if not isReallyClosed(theWire): + FreeCAD.Console.PrintError(translate("PathProject", "The selected edges don't form a closed loop\n")) + return for i in sel.SubElementNames: self.obj.Proxy.addprofilebase(self.obj, sel.Object, i) diff --git a/src/Mod/Path/PathScripts/PathUtils.py b/src/Mod/Path/PathScripts/PathUtils.py index 54b8e5cb1f..7325da3573 100644 --- a/src/Mod/Path/PathScripts/PathUtils.py +++ b/src/Mod/Path/PathScripts/PathUtils.py @@ -38,7 +38,7 @@ from PySide import QtGui LOG_MODULE = 'PathUtils' PathLog.setLevel(PathLog.Level.INFO, LOG_MODULE) -PathLog.trackModule('PathUtils') +#PathLog.trackModule('PathUtils') FreeCAD.setLogLevel('Path.Area', 0) def waiting_effects(function): @@ -236,34 +236,51 @@ def makeWorkplane(shape): return c -def getEnvelope(partshape, stockheight=None): +def getEnvelope(partshape, subshape=None, stockheight=None): ''' - getEnvelop(partshape, stockheight=None) + getEnvelope(partshape, stockheight=None) returns a shape corresponding to the partshape silhouette extruded to height. if stockheight is given, the returned shape is extruded to that height otherwise the returned shape is the height of the original shape boundbox partshape = solid object - stockheight = float + stockheight = float - Absolute Z height of the top of material before cutting. ''' - PathLog.track(partshape, stockheight) - area = Path.Area(Fill=1, Coplanar=0).add(partshape) - # loc = FreeCAD.Vector(partshape.BoundBox.Center.x, - # partshape.BoundBox.Center.y, - # partshape.BoundBox.ZMin) - area.setPlane(makeWorkplane(partshape)) - sec = area.makeSections(heights=[1.0], project=True)[0].getShape() + PathLog.track(partshape, subshape, stockheight) + + # if partshape.Volume == 0.0: #Not a 3D object + # return None + + if subshape is not None: + if isinstance(subshape, Part.Face): + PathLog.debug('processing a face') + sec = Part.makeCompound([subshape]) + else: + area = Path.Area(Fill=2, Coplanar=0).add(subshape) + area.setPlane(makeWorkplane(partshape)) + PathLog.debug("About to section with params: {}".format(area.getParams())) + sec = area.makeSections(heights=[0.0], project=True)[0].getShape() + + zShift = partshape.BoundBox.ZMin - subshape.BoundBox.ZMin + PathLog.debug('partshapeZmin: {}, subshapeZMin: {}, zShift: {}'.format(partshape.BoundBox.ZMin, subshape.BoundBox.ZMin, zShift)) + newPlace = FreeCAD.Placement(FreeCAD.Vector(0, 0, zShift), sec.Placement.Rotation) + sec.Placement = newPlace + + else: + area = Path.Area(Fill=2, Coplanar=0).add(partshape) + area.setPlane(makeWorkplane(partshape)) + sec = area.makeSections(heights=[0.0], project=True)[0].getShape() if stockheight is not None: eLength = float(stockheight)-partshape.BoundBox.ZMin + PathLog.debug('boundbox zMIN: {} elength: {}'.format(partshape.BoundBox.ZMin, eLength)) envelopeshape = sec.extrude(FreeCAD.Vector(0, 0, eLength)) else: envelopeshape = sec.extrude(FreeCAD.Vector(0, 0, partshape.BoundBox.ZLength)) if PathLog.getLevel(PathLog.thisModule()) == PathLog.Level.DEBUG: - removalshape=FreeCAD.ActiveDocument.addObject("Part::Feature","RemovedMaterial") + removalshape=FreeCAD.ActiveDocument.addObject("Part::Feature","Envelope") removalshape.Shape = envelopeshape return envelopeshape - def reverseEdge(e): if geomType(e) == "Circle": arcstpt = e.valueAt(e.FirstParameter)