diff --git a/src/Mod/Path/Gui/Resources/panels/MillFaceEdit.ui b/src/Mod/Path/Gui/Resources/panels/MillFaceEdit.ui index c9bb25b85e..ec11749cf0 100644 --- a/src/Mod/Path/Gui/Resources/panels/MillFaceEdit.ui +++ b/src/Mod/Path/Gui/Resources/panels/MillFaceEdit.ui @@ -6,8 +6,8 @@ 0 0 - 323 - 482 + 518 + 754 @@ -33,8 +33,8 @@ 0 0 - 305 - 277 + 500 + 282 @@ -111,8 +111,8 @@ 0 0 - 305 - 124 + 500 + 241 @@ -192,8 +192,8 @@ 0 0 - 305 - 109 + 500 + 241 @@ -241,9 +241,9 @@ 0 - 0 - 289 - 297 + -34 + 486 + 361 @@ -263,20 +263,6 @@ QFrame::Raised - - - - - - - - - - - Use ZigZag - - - @@ -284,7 +270,14 @@ - + + + + + + + + ZigZag Angle @@ -294,54 +287,6 @@ - - - - - - - Cut Mode - - - - - - - Boundary Shape - - - - - - - - Perimeter - - - - - Boundbox - - - - - - - - - Climb - - - - - Conventional - - - - - - - @@ -410,6 +355,85 @@ + + + + + + + Cut Mode + + + + + + + + Climb + + + + + Conventional + + + + + + + + Boundary Shape + + + + + + + + Perimeter + + + + + Boundbox + + + + + + + + + ZigZag + + + + + Offset + + + + + Spiral + + + + + ZigZagOffset + + + + + + + + Pattern + + + + + + diff --git a/src/Mod/Path/PathScripts/PathContour.py b/src/Mod/Path/PathScripts/PathContour.py index e6000e25f9..99cef5a55c 100644 --- a/src/Mod/Path/PathScripts/PathContour.py +++ b/src/Mod/Path/PathScripts/PathContour.py @@ -31,6 +31,7 @@ from PathScripts.PathUtils import depth_params from PySide import QtCore import TechDraw import ArchPanel +import Part LOG_MODULE = 'PathContour' PathLog.setLevel(PathLog.Level.INFO, LOG_MODULE) @@ -131,64 +132,99 @@ class ObjectContour: obj.ClearanceHeight = 10.0 obj.SafeHeight = 8.0 - def _buildPathLibarea(self, obj, edgelist): - import PathScripts.PathKurveUtils as PathKurveUtils - PathLog.track() - # import math - # import area - output = "" - if obj.Comment != "": - output += '(' + str(obj.Comment)+')\n' + def _buildPathArea(self, obj, edgelist, start = None): - if obj.StartPoint and obj.UseStartPoint: - startpoint = obj.StartPoint - else: - startpoint = None + c = Part.Wire(edgelist) + f = Part.makeFace([c], 'Part::FaceMakerSimple') - if obj.EndPoint and obj.UseEndPoint: - endpoint = obj.EndPoint - else: - endpoint = None - - PathKurveUtils.output('mem') - PathKurveUtils.feedrate_hv(self.horizFeed, self.vertFeed) - - output = "" - output += "G0 Z" + str(obj.ClearanceHeight.Value) + "F " + PathUtils.fmt(self.vertRapid) + "\n" - curve = PathKurveUtils.makeAreaCurve(edgelist, obj.Direction, startpoint, endpoint) - - roll_radius = 2.0 - extend_at_start = 0.0 - extend_at_end = 0.0 - lead_in_line_len = 0.0 - lead_out_line_len = 0.0 - - if obj.UseComp is False: - obj.Side = 'On' - else: - if obj.Direction == 'CW': - obj.Side = 'Left' - else: - obj.Side = 'Right' + profile = Path.Area(Offset=self.radius,SectionCount=1) + profile.setPlane(Part.makeCircle(10)) + profile.add(f) + lshapes = [profile.getShape()] depthparams = depth_params( - obj.ClearanceHeight.Value, - obj.SafeHeight.Value, obj.StartDepth.Value, obj.StepDown.Value, 0.0, - obj.FinalDepth.Value, None) + clearance_height = obj.ClearanceHeight.Value, + rapid_safety_space = obj.SafeHeight.Value, + start_depth = obj.StartDepth.Value, + step_down = obj.StepDown.Value, + z_finish_step = 0.0, + final_depth = obj.FinalDepth.Value, + user_depths = None) - PathKurveUtils.profile2( - curve, obj.Side, self.radius, self.vertFeed, self.horizFeed, - self.vertRapid, self.horizRapid, obj.OffsetExtra.Value, roll_radius, - None, None, depthparams, extend_at_start, extend_at_end, - lead_in_line_len, lead_out_line_len) + print (depthparams.get_depths()) + for l in depthparams.get_depths(): + c = lshapes[0].copy() + c.Placement.Base.z = l + lshapes.append(c) - output += PathKurveUtils.retrieve_gcode() - return output + if start is None: + pp = Path.fromShapes(lshapes) + else: + pp = Path.fromShapes(lshapes, start) + return pp + + + # def _buildPathLibarea(self, obj, edgelist): + # import PathScripts.PathKurveUtils as PathKurveUtils + # PathLog.track() + # # import math + # # import area + # output = "" + # if obj.Comment != "": + # output += '(' + str(obj.Comment)+')\n' + + # if obj.StartPoint and obj.UseStartPoint: + # startpoint = obj.StartPoint + # else: + # startpoint = None + + # if obj.EndPoint and obj.UseEndPoint: + # endpoint = obj.EndPoint + # else: + # endpoint = None + + # PathKurveUtils.output('mem') + # PathKurveUtils.feedrate_hv(self.horizFeed, self.vertFeed) + + # output = "" + # output += "G0 Z" + str(obj.ClearanceHeight.Value) + "F " + PathUtils.fmt(self.vertRapid) + "\n" + # curve = PathKurveUtils.makeAreaCurve(edgelist, obj.Direction, startpoint, endpoint) + + # roll_radius = 2.0 + # extend_at_start = 0.0 + # extend_at_end = 0.0 + # lead_in_line_len = 0.0 + # lead_out_line_len = 0 # obj.FinalDepth.Value, None) + + # PathKurveUtils.profile2( + + # if obj.UseComp is False: + # obj.Side = 'On' + # else: + # if obj.Direction == 'CW': + # obj.Side = 'Left' + # else: + # obj.Side = 'Right' + + # depthparams = depth_params( + # obj.ClearanceHeight.Value, + # obj.SafeHeight.Value, obj.StartDepth.Value, obj.StepDown.Value, 0.0, + # obj.FinalDepth.Value, None) + + # PathKurveUtils.profile2( + # curve, obj.Side, self.radius, self.vertFeed, self.horizFeed, + # self.vertRapid, self.horizRapid, obj.OffsetExtra.Value, roll_radius, + # None, None, depthparams, extend_at_start, extend_at_end, + # lead_in_line_len, lead_out_line_len) + + # output += PathKurveUtils.retrieve_gcode() + # return output def execute(self, obj): PathLog.track() import Part # math #DraftGeomUtils - output = "" + commandlist = [] + #output = "" toolLoad = obj.ToolController @@ -204,16 +240,20 @@ class ObjectContour: if not tool or tool.Diameter == 0: FreeCAD.Console.PrintError("No Tool found or diameter is zero. We need a tool to build a Path.") return - #self.radius = 0.25 else: self.radius = tool.Diameter/2 - output += "(" + obj.Label + ")" + #output += "(" + obj.Label + ")" + commandlist.append(Path.Command("(" + obj.Label + ")")) + if not obj.UseComp: - output += "(Compensated Tool Path. Diameter: " + str(self.radius * 2) + ")" + #output += "(Compensated Tool Path. Diameter: " + str(self.radius * 2) + ")" + commandlist.append(Path.Command("(Compensated Tool Path. Diameter: " + str(self.radius * 2) + ")")) + else: - output += "(Uncompensated Tool Path)" + #output += "(Uncompensated Tool Path)" + commandlist.append(Path.Command("(Uncompensated Tool Path)")) parentJob = PathUtils.findParentJob(obj) if parentJob is None: @@ -234,21 +274,29 @@ class ObjectContour: edgelist = Part.__sortEdges__(edgelist) PathLog.debug("Processing panel perimeter. edges found: {}".format(len(edgelist))) # subobj.Proxy.execute(subobj) try: - output += self._buildPathLibarea(obj, edgelist) - except: + #output += self._buildPathLibarea(obj, edgelist) + commandlist.extend(self._buildPathArea(obj, edgelist).Commands) + except Exception as e: + print(e) FreeCAD.Console.PrintError("Something unexpected happened. Unable to generate a contour path. Check project and tool config.") else: - contourwire = TechDraw.findShapeOutline(baseobject.Shape, 1, Vector(0, 0, 1)) + fixbase = baseobject.Shape.copy() + fixbase.fix(0.00001,0.00001,0.00001) + contourwire = TechDraw.findShapeOutline(fixbase, 1, Vector(0, 0, 1)) edgelist = contourwire.Edges edgelist = Part.__sortEdges__(edgelist) try: - output += self._buildPathLibarea(obj, edgelist) - except: + commandlist.extend(self._buildPathArea(obj, edgelist).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(output) + path = Path.Path(commandlist) + # for c in contourcommands.Commands: + # path.addCommands(c) + obj.Path = path if obj.ViewObject: obj.ViewObject.Visibility = True diff --git a/src/Mod/Path/PathScripts/PathMillFace.py b/src/Mod/Path/PathScripts/PathMillFace.py index 7487b1b46a..9f2daed93b 100644 --- a/src/Mod/Path/PathScripts/PathMillFace.py +++ b/src/Mod/Path/PathScripts/PathMillFace.py @@ -88,6 +88,8 @@ class ObjectFace: obj.addProperty("App::PropertyFloat", "ZigZagAngle", "Face", QtCore.QT_TRANSLATE_NOOP("App::Property", "Angle of the zigzag pattern")) obj.addProperty("App::PropertyEnumeration", "BoundaryShape", "Face", QtCore.QT_TRANSLATE_NOOP("App::Property", "Shape to use for calculating Boundary")) obj.BoundaryShape = ['Perimeter', 'Boundbox'] + obj.addProperty("App::PropertyEnumeration", "OffsetPattern", "Face", QtCore.QT_TRANSLATE_NOOP("App::Property", "clearing pattern to use")) + obj.OffsetPattern = ['Offset', 'ZigZag', 'Spiral', 'ZigZagOffset'] # Start Point Properties obj.addProperty("App::PropertyVector", "StartPoint", "Start Point", QtCore.QT_TRANSLATE_NOOP("App::Property", "The start point of this path")) @@ -159,60 +161,119 @@ class ObjectFace: return self.getStock(o) return None - def buildpathlibarea(self, obj, a): - """Build the face path using libarea algorithm""" - - import PathScripts.PathAreaUtils as PathAreaUtils + def _buildPathArea(self, obj, edgelist): + """build the face path using PathArea""" from PathScripts.PathUtils import depth_params PathLog.track() - for p in a.getCurves(): - PathLog.debug(p.text()) + c = Part.Wire(edgelist) + f = Part.makeFace([c], 'Part::FaceMakerSimple') - FreeCAD.Console.PrintMessage(translate("PathMillFace", "Generating toolpath with libarea offsets.\n")) + boundary = Path.Area(PocketMode=4,SectionCount=1) + boundary.setPlane(Part.makeCircle(10)) + boundary.add(f) + #toolDiameter = 1.0 + + #use_zig_zag = obj.UseZigZag + #keep_tool_down = obj.KeepToolDown + #zig_unidirectional = obj.ZigUnidirectional + #start_point = None + #cut_mode = obj.CutMode + stepover = (self.radius * 2) * (float(obj.StepOver)/100) + + boundary.setParams(ZigAngle=obj.ZigZagAngle, + FromCenter=(obj.StartAt == "Center"), + PocketStepOver = stepover, #(self.radius * 2) * (float(obj.StepOver)/100), + PocketExtraOffset=obj.PassExtension.Value, + PocketMode=4) depthparams = depth_params( - obj.ClearanceHeight.Value, - obj.SafeHeight.Value, - obj.StartDepth.Value, - obj.StepDown, - obj.FinishDepth.Value, - obj.FinalDepth.Value) + clearance_height = obj.ClearanceHeight.Value, + rapid_safety_space = obj.SafeHeight.Value, + start_depth = obj.StartDepth.Value, + step_down = obj.StepDown, + z_finish_step = obj.FinishDepth.Value, + final_depth = obj.FinalDepth.Value, + user_depths = None) - extraoffset = - obj.PassExtension.Value - stepover = (self.radius * 2) * (float(obj.StepOver)/100) - use_zig_zag = obj.UseZigZag - zig_angle = obj.ZigZagAngle - from_center = (obj.StartAt == "Center") - keep_tool_down = obj.KeepToolDown - zig_unidirectional = obj.ZigUnidirectional - start_point = None - cut_mode = obj.CutMode + print (depthparams.get_depths()) + lshapes = [boundary.getShape()] - PathAreaUtils.flush_nc() - PathAreaUtils.output('mem') - PathAreaUtils.feedrate_hv(self.horizFeed, self.vertFeed) - if obj.UseStartPoint: - start_point = (obj.StartPoint.x, obj.StartPoint.y) + # depthparams = depth_params( + # obj.ClearanceHeight.Value, + # obj.SafeHeight.Value, + # obj.StartDepth.Value, + # obj.StepDown, + # obj.FinishDepth.Value, + # obj.FinalDepth.Value) - PathAreaUtils.pocket( - a, - self.radius, - extraoffset, - stepover, - depthparams, - from_center, - keep_tool_down, - use_zig_zag, - zig_angle, - zig_unidirectional, - start_point, - cut_mode) - return PathAreaUtils.retrieve_gcode() + for l in depthparams.get_depths(): + c = lshapes[0].copy() + c.Placement.Base.z = l + lshapes.append(c) + + #if start is None: + pp = Path.fromShapes(lshapes) + #else: + # pp = Path.fromShapes(lshapes, start) + return pp + + # def buildpathlibarea(self, obj, a): + # """Build the face path using libarea algorithm""" + + # import PathScripts.PathAreaUtils as PathAreaUtils + # from PathScripts.PathUtils import depth_params + + # PathLog.track() + # for p in a.getCurves(): + # PathLog.debug(p.text()) + + # FreeCAD.Console.PrintMessage(translate("PathMillFace", "Generating toolpath with libarea offsets.\n")) + + # depthparams = depth_params( + # obj.ClearanceHeight.Value, + # obj.SafeHeight.Value, + # obj.StartDepth.Value, + # obj.StepDown, + # obj.FinishDepth.Value, + # obj.FinalDepth.Value) + + # extraoffset = - obj.PassExtension.Value + # stepover = (self.radius * 2) * (float(obj.StepOver)/100) + # use_zig_zag = obj.UseZigZag + # zig_angle = obj.ZigZagAngle + # from_center = (obj.StartAt == "Center") + # keep_tool_down = obj.KeepToolDown + # zig_unidirectional = obj.ZigUnidirectional + # start_point = None + # cut_mode = obj.CutMode + + # PathAreaUtils.flush_nc() + # PathAreaUtils.output('mem') + # PathAreaUtils.feedrate_hv(self.horizFeed, self.vertFeed) + # if obj.UseStartPoint: + # start_point = (obj.StartPoint.x, obj.StartPoint.y) + + # PathAreaUtils.pocket( + # a, + # self.radius, + # extraoffset, + # stepover, + # depthparams, + # from_center, + # keep_tool_down, + # use_zig_zag, + # zig_angle, + # zig_unidirectional, + # start_point, + # cut_mode) + # return PathAreaUtils.retrieve_gcode() def execute(self, obj): PathLog.track() - output = "" + commandlist = [] + + #output = "" toolLoad = obj.ToolController @@ -233,8 +294,12 @@ class ObjectFace: self.radius = tool.Diameter/2 # Build preliminary comments - output = "" - output += "(" + obj.Label + ")" + # output = "" + # output += "(" + obj.Label + ")" + + + commandlist.append(Path.Command("(" + obj.Label + ")")) + # Facing is done either against base objects if obj.Base: @@ -282,20 +347,44 @@ class ObjectFace: edgelist = contourwire.Edges edgelist = Part.__sortEdges__(edgelist) - # use libarea to build the pattern - a = area.Area() - c = PathScripts.PathKurveUtils.makeAreaCurve(edgelist, 'CW') - PathLog.debug(c.text()) - a.append(c) - a.Reorder() - output += self.buildpathlibarea(obj, a) - path = Path.Path(output) - if len(path.Commands) == 0: - FreeCAD.Console.PrintMessage(translate("PathMillFace", "The selected settings did not produce a valid path.\n")) - obj.Path = path - obj.ViewObject.Visibility = True + # # use libarea to build the pattern + # a = area.Area() + # c = PathScripts.PathKurveUtils.makeAreaCurve(edgelist, 'CW') + # PathLog.debug(c.text()) + # a.append(c) + # a.Reorder() + # output += self.buildpathlibarea(obj, a) + + + try: + commandlist.extend(self._buildPathArea(obj, edgelist).Commands) + except Exception as e: + print(e) + FreeCAD.Console.PrintWarning(translate("PathMillFace", "The selected settings did not produce a valid path.\n")) + + #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(output) +# if len(path.Commands) == 0: +# FreeCAD.Console.PrintMessage(translate("PathMillFace", "The selected settings did not produce a valid path.\n")) + +# obj.Path = path +# obj.ViewObject.Visibility = True class _CommandSetFaceStartPoint: @@ -375,8 +464,8 @@ class CommandPathMillFace: FreeCADGui.doCommand('obj.StepDown = 1.0') FreeCADGui.doCommand('obj.StartDepth = ' + str(ztop + 1)) FreeCADGui.doCommand('obj.FinalDepth =' + str(ztop)) - FreeCADGui.doCommand('obj.ZigZagAngle = 0.0') - FreeCADGui.doCommand('obj.UseZigZag = True') + FreeCADGui.doCommand('obj.ZigZagAngle = 45.0') + #FreeCADGui.doCommand('obj.UseZigZag = True') FreeCADGui.doCommand('PathScripts.PathUtils.addToJob(obj)') FreeCADGui.doCommand('obj.ToolController = PathScripts.PathUtils.findToolController(obj)') snippet = ''' @@ -436,16 +525,19 @@ class TaskPanel: self.obj.PassExtension = FreeCAD.Units.Quantity(self.form.extraOffset.text()).Value if hasattr(self.obj, "CutMode"): self.obj.CutMode = str(self.form.cutMode.currentText()) - if hasattr(self.obj, "UseZigZag"): - self.obj.UseZigZag = self.form.useZigZag.isChecked() - if hasattr(self.obj, "ZigUnidirectional"): - self.obj.ZigUnidirectional = self.form.zigZagUnidirectional.isChecked() + # if hasattr(self.obj, "UseZigZag"): + # self.obj.UseZigZag = self.form.useZigZag.isChecked() + # if hasattr(self.obj, "ZigUnidirectional"): + # self.obj.ZigUnidirectional = self.form.zigZagUnidirectional.isChecked() if hasattr(self.obj, "ZigZagAngle"): self.obj.ZigZagAngle = FreeCAD.Units.Quantity(self.form.zigZagAngle.text()).Value if hasattr(self.obj, "StepOver"): self.obj.StepOver = self.form.stepOverPercent.value() if hasattr(self.obj, "BoundaryShape"): self.obj.BoundaryShape = str(self.form.boundaryShape.currentText()) + if hasattr(self.obj, "OffsetPattern"): + self.obj.OffsetPattern = str(self.form.offsetpattern.currentText()) + if hasattr(self.obj, "ToolController"): tc = PathUtils.findToolController(self.obj, self.form.uiToolController.currentText()) self.obj.ToolController = tc @@ -460,8 +552,8 @@ class TaskPanel: self.form.clearanceHeight.setText(FreeCAD.Units.Quantity(self.obj.ClearanceHeight.Value, FreeCAD.Units.Length).UserString) self.form.stepOverPercent.setValue(self.obj.StepOver) - self.form.useZigZag.setChecked(self.obj.UseZigZag) - self.form.zigZagUnidirectional.setChecked(self.obj.ZigUnidirectional) + #self.form.useZigZag.setChecked(self.obj.UseZigZag) + #self.form.zigZagUnidirectional.setChecked(self.obj.ZigUnidirectional) self.form.zigZagAngle.setValue(FreeCAD.Units.Quantity(self.obj.ZigZagAngle, FreeCAD.Units.Angle)) self.form.extraOffset.setValue(self.obj.PassExtension.Value) @@ -480,6 +572,14 @@ class TaskPanel: self.form.boundaryShape.setCurrentIndex(index) self.form.boundaryShape.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) + for i in self.obj.Base: for sub in i[1]: self.form.baseList.addItem(i[0].Name + "." + sub) @@ -616,8 +716,9 @@ class TaskPanel: self.form.extraOffset.editingFinished.connect(self.getFields) self.form.boundaryShape.currentIndexChanged.connect(self.getFields) self.form.stepOverPercent.editingFinished.connect(self.getFields) - self.form.useZigZag.clicked.connect(self.getFields) - self.form.zigZagUnidirectional.clicked.connect(self.getFields) + self.form.offsetpattern.currentIndexChanged.connect(self.getFields) + #self.form.useZigZag.clicked.connect(self.getFields) + #self.form.zigZagUnidirectional.clicked.connect(self.getFields) self.form.zigZagAngle.editingFinished.connect(self.getFields) self.form.uiToolController.currentIndexChanged.connect(self.getFields)