From 0a9bf1c5f0f64976a5d62dd52f521e51d89242ca Mon Sep 17 00:00:00 2001 From: sliptonic Date: Sat, 20 Feb 2021 11:22:20 -0600 Subject: [PATCH] Add useoutline property to op if doesn't exist --- src/Mod/Path/PathScripts/PathAdaptive.py | 237 ++++++++++++----------- 1 file changed, 121 insertions(+), 116 deletions(-) diff --git a/src/Mod/Path/PathScripts/PathAdaptive.py b/src/Mod/Path/PathScripts/PathAdaptive.py index ed9f876976..7ca8fe8892 100644 --- a/src/Mod/Path/PathScripts/PathAdaptive.py +++ b/src/Mod/Path/PathScripts/PathAdaptive.py @@ -41,21 +41,23 @@ TechDraw = LazyLoader('TechDraw', globals(), 'TechDraw') __doc__ = "Class and implementation of the Adaptive path operation." + def convertTo2d(pathArray): output = [] for path in pathArray: pth2 = [] for edge in path: for pt in edge: - pth2.append([pt[0],pt[1]]) + pth2.append([pt[0], pt[1]]) output.append(pth2) return output sceneGraph = None -scenePathNodes = [] #for scene cleanup aftewards +scenePathNodes = [] # for scene cleanup aftewards topZ = 10 + def sceneDrawPath(path, color=(0, 0, 1)): coPoint = coin.SoCoordinate3() @@ -73,7 +75,8 @@ def sceneDrawPath(path, color=(0, 0, 1)): pathNode.addChild(ma) pathNode.addChild(li) sceneGraph.addChild(pathNode) - scenePathNodes.append(pathNode) #for scene cleanup afterwards + scenePathNodes.append(pathNode) # for scene cleanup afterwards + def sceneClean(): for n in scenePathNodes: @@ -81,13 +84,15 @@ def sceneClean(): del scenePathNodes[:] -def discretize(edge, flipDirection = False): - pts = edge.discretize(Deflection = 0.0001) + +def discretize(edge, flipDirection=False): + pts = edge.discretize(Deflection=0.0001) if flipDirection: pts.reverse() return pts + def CalcHelixConePoint(height, cur_z, radius, angle): x = ((height - cur_z) / height) * radius * math.cos(math.radians(angle)*cur_z) y = ((height - cur_z) / height) * radius * math.sin(math.radians(angle)*cur_z) @@ -95,7 +100,8 @@ def CalcHelixConePoint(height, cur_z, radius, angle): return {'X': x, 'Y': y, 'Z': z} -def GenerateGCode(op,obj,adaptiveResults, helixDiameter): + +def GenerateGCode(op, obj, adaptiveResults, helixDiameter): # pylint: disable=unused-argument if len(adaptiveResults) == 0 or len(adaptiveResults[0]["AdaptivePaths"]) == 0: return @@ -103,16 +109,16 @@ def GenerateGCode(op,obj,adaptiveResults, helixDiameter): # minLiftDistance = op.tool.Diameter helixRadius = 0 for region in adaptiveResults: - p1 = region["HelixCenterPoint"] - p2 = region["StartPoint"] - r =math.sqrt((p1[0]-p2[0]) * (p1[0]-p2[0]) + (p1[1]-p2[1]) * (p1[1]-p2[1])) + p1 = region["HelixCenterPoint"] + p2 = region["StartPoint"] + r = math.sqrt((p1[0]-p2[0]) * (p1[0]-p2[0]) + (p1[1] - p2[1]) * (p1[1] - p2[1])) if r > helixRadius: helixRadius = r stepDown = obj.StepDown.Value - passStartDepth=obj.StartDepth.Value + passStartDepth = obj.StartDepth.Value - if stepDown < 0.1 : + if stepDown < 0.1: stepDown = 0.1 length = 2*math.pi * helixRadius @@ -121,13 +127,13 @@ def GenerateGCode(op,obj,adaptiveResults, helixDiameter): obj.HelixAngle = 1 if float(obj.HelixAngle) > 89: obj.HelixAngle = 89 - + if float(obj.HelixConeAngle) < 0: obj.HelixConeAngle = 0 helixAngleRad = math.pi * float(obj.HelixAngle) / 180.0 depthPerOneCircle = length * math.tan(helixAngleRad) - #print("Helix circle depth: {}".format(depthPerOneCircle)) + # print("Helix circle depth: {}".format(depthPerOneCircle)) stepUp = obj.LiftDistance.Value if stepUp < 0: @@ -146,12 +152,11 @@ def GenerateGCode(op,obj,adaptiveResults, helixDiameter): final_depth=obj.FinalDepth.Value, user_depths=None) - # ml: this is dangerous because it'll hide all unused variables hence forward # however, I don't know what lx and ly signify so I'll leave them for now # pylint: disable=unused-variable - lx = adaptiveResults[0]["HelixCenterPoint"][0] - ly = adaptiveResults[0]["HelixCenterPoint"][1] + # lx = adaptiveResults[0]["HelixCenterPoint"][0] + # ly = adaptiveResults[0]["HelixCenterPoint"][1] lz = passStartDepth step = 0 @@ -161,28 +166,28 @@ def GenerateGCode(op,obj,adaptiveResults, helixDiameter): for region in adaptiveResults: startAngle = math.atan2(region["StartPoint"][1] - region["HelixCenterPoint"][1], region["StartPoint"][0] - region["HelixCenterPoint"][0]) - lx = region["HelixCenterPoint"][0] - ly = region["HelixCenterPoint"][1] + # lx = region["HelixCenterPoint"][0] + # ly = region["HelixCenterPoint"][1] passDepth = (passStartDepth - passEndDepth) p1 = region["HelixCenterPoint"] p2 = region["StartPoint"] - helixRadius = math.sqrt((p1[0]-p2[0]) * (p1[0]-p2[0]) + (p1[1]-p2[1]) * (p1[1]-p2[1])) + helixRadius = math.sqrt((p1[0]-p2[0]) * (p1[0]-p2[0]) + (p1[1]-p2[1]) * (p1[1]-p2[1])) # Helix ramp if helixRadius > 0.01: r = helixRadius - 0.01 - maxfi = passDepth / depthPerOneCircle * 2 * math.pi + maxfi = passDepth / depthPerOneCircle * 2 * math.pi fi = 0 offsetFi = -maxfi + startAngle-math.pi/16 helixStart = [region["HelixCenterPoint"][0] + r * math.cos(offsetFi), region["HelixCenterPoint"][1] + r * math.sin(offsetFi)] - op.commandlist.append(Path.Command("(Helix to depth: %f)"%passEndDepth)) + op.commandlist.append(Path.Command("(Helix to depth: %f)" % passEndDepth)) - if obj.UseHelixArcs == False: + if obj.UseHelixArcs is False: # rapid move to start point op.commandlist.append(Path.Command("G0", {"Z": obj.ClearanceHeight.Value})) op.commandlist.append(Path.Command("G0", {"X": helixStart[0], "Y": helixStart[1], "Z": obj.ClearanceHeight.Value})) @@ -198,10 +203,10 @@ def GenerateGCode(op,obj,adaptiveResults, helixDiameter): x = region["HelixCenterPoint"][0] + r * math.cos(fi+offsetFi) y = region["HelixCenterPoint"][1] + r * math.sin(fi+offsetFi) z = passStartDepth - fi / maxfi * (passStartDepth - passEndDepth) - op.commandlist.append(Path.Command("G1", { "X": x, "Y":y, "Z":z, "F": op.vertFeed})) - lx = x - ly = y - fi=fi+math.pi/16 + op.commandlist.append(Path.Command("G1", {"X": x, "Y": y, "Z": z, "F": op.vertFeed})) + # lx = x + # ly = y + fi = fi + math.pi / 16 # one more circle at target depth to make sure center is cleared maxfi = maxfi + 2*math.pi @@ -209,18 +214,18 @@ def GenerateGCode(op,obj,adaptiveResults, helixDiameter): x = region["HelixCenterPoint"][0] + r * math.cos(fi+offsetFi) y = region["HelixCenterPoint"][1] + r * math.sin(fi+offsetFi) z = passEndDepth - op.commandlist.append(Path.Command("G1", { "X": x, "Y":y, "Z":z, "F": op.horizFeed})) - lx = x - ly = y + op.commandlist.append(Path.Command("G1", {"X": x, "Y": y, "Z": z, "F": op.horizFeed})) + # lx = x + # ly = y fi = fi + math.pi/16 - + else: # Cone _HelixAngle = 360 - (float(obj.HelixAngle) * 4) if obj.HelixConeAngle > 6: obj.HelixConeAngle = 6 - + helixRadius *= 0.9 # Calculate everything @@ -241,29 +246,29 @@ def GenerateGCode(op,obj,adaptiveResults, helixDiameter): z_step = 0.025 if _HelixAngle > 240: z_step = 0.015 - + p = None # Calculate conical helix while(z >= passEndDepth): if z < passEndDepth: z = passEndDepth - + p = CalcHelixConePoint(helix_full_height, i, HelixTopRadius, _HelixAngle) - op.commandlist.append(Path.Command("G1", { "X": p['X'] + region["HelixCenterPoint"][0], "Y": p['Y'] + region["HelixCenterPoint"][1], "Z": z, "F": op.vertFeed})) + op.commandlist.append(Path.Command("G1", {"X": p['X'] + region["HelixCenterPoint"][0], "Y": p['Y'] + region["HelixCenterPoint"][1], "Z": z, "F": op.vertFeed})) z = z - z_step i = i + z_step - + # Calculate some stuff for arcs at bottom - p['X'] = p['X'] + region["HelixCenterPoint"][0] - p['Y'] = p['Y'] + region["HelixCenterPoint"][1] - x_m = region["HelixCenterPoint"][0] - p['X'] + region["HelixCenterPoint"][0] - y_m = region["HelixCenterPoint"][1] - p['Y'] + region["HelixCenterPoint"][1] + p['X'] = p['X'] + region["HelixCenterPoint"][0] + p['Y'] = p['Y'] + region["HelixCenterPoint"][1] + x_m = region["HelixCenterPoint"][0] - p['X'] + region["HelixCenterPoint"][0] + y_m = region["HelixCenterPoint"][1] - p['Y'] + region["HelixCenterPoint"][1] i_off = (x_m - p['X']) / 2 j_off = (y_m - p['Y']) / 2 # One more circle at target depth to make sure center is cleared - op.commandlist.append(Path.Command("G3", { "X": x_m, "Y": y_m, "Z": passEndDepth, "I": i_off, "J": j_off, "F": op.horizFeed})) - op.commandlist.append(Path.Command("G3", { "X": p['X'], "Y": p['Y'], "Z": passEndDepth, "I": -i_off, "J": -j_off, "F": op.horizFeed})) + op.commandlist.append(Path.Command("G3", {"X": x_m, "Y": y_m, "Z": passEndDepth, "I": i_off, "J": j_off, "F": op.horizFeed})) + op.commandlist.append(Path.Command("G3", {"X": p['X'], "Y": p['Y'], "Z": passEndDepth, "I": -i_off, "J": -j_off, "F": op.horizFeed})) else: # Use arcs for helix - no conical shape support @@ -284,40 +289,40 @@ def GenerateGCode(op,obj,adaptiveResults, helixDiameter): curDep = passStartDepth while curDep > (passEndDepth + depthPerOneCircle): - op.commandlist.append(Path.Command("G2", { "X": x - (2*r), "Y": y, "Z": curDep - (depthPerOneCircle/2), "I": -r, "F": op.vertFeed})) - op.commandlist.append(Path.Command("G2", { "X": x, "Y": y, "Z": curDep - depthPerOneCircle, "I": r, "F": op.vertFeed})) + op.commandlist.append(Path.Command("G2", {"X": x - (2*r), "Y": y, "Z": curDep - (depthPerOneCircle/2), "I": -r, "F": op.vertFeed})) + op.commandlist.append(Path.Command("G2", {"X": x, "Y": y, "Z": curDep - depthPerOneCircle, "I": r, "F": op.vertFeed})) curDep = curDep - depthPerOneCircle lastStep = curDep - passEndDepth if lastStep > (depthPerOneCircle/2): - op.commandlist.append(Path.Command("G2", { "X": x - (2*r), "Y": y, "Z": curDep - (lastStep/2), "I": -r, "F": op.vertFeed})) - op.commandlist.append(Path.Command("G2", { "X": x, "Y": y, "Z": passEndDepth, "I": r, "F": op.vertFeed})) + op.commandlist.append(Path.Command("G2", {"X": x - (2*r), "Y": y, "Z": curDep - (lastStep/2), "I": -r, "F": op.vertFeed})) + op.commandlist.append(Path.Command("G2", {"X": x, "Y": y, "Z": passEndDepth, "I": r, "F": op.vertFeed})) else: - op.commandlist.append(Path.Command("G2", { "X": x - (2*r), "Y": y, "Z": passEndDepth, "I": -r, "F": op.vertFeed})) + op.commandlist.append(Path.Command("G2", {"X": x - (2*r), "Y": y, "Z": passEndDepth, "I": -r, "F": op.vertFeed})) op.commandlist.append(Path.Command("G1", {"X": x, "Y": y, "Z": passEndDepth, "F": op.vertFeed})) # one more circle at target depth to make sure center is cleared - op.commandlist.append(Path.Command("G2", { "X": x - (2*r), "Y": y, "Z": passEndDepth, "I": -r, "F": op.horizFeed})) - op.commandlist.append(Path.Command("G2", { "X": x, "Y": y, "Z": passEndDepth, "I": r, "F": op.horizFeed})) - lx = x - ly = y + op.commandlist.append(Path.Command("G2", {"X": x - (2*r), "Y": y, "Z": passEndDepth, "I": -r, "F": op.horizFeed})) + op.commandlist.append(Path.Command("G2", {"X": x, "Y": y, "Z": passEndDepth, "I": r, "F": op.horizFeed})) + # lx = x + # ly = y - else: # no helix entry + else: # no helix entry # rapid move to clearance height op.commandlist.append(Path.Command("G0", {"Z": obj.ClearanceHeight.Value})) op.commandlist.append(Path.Command("G0", {"X": region["StartPoint"][0], "Y": region["StartPoint"][1], "Z": obj.ClearanceHeight.Value})) # straight plunge to target depth - op.commandlist.append(Path.Command("G1", {"X":region["StartPoint"][0], "Y": region["StartPoint"][1], "Z": passEndDepth,"F": op.vertFeed})) + op.commandlist.append(Path.Command("G1", {"X": region["StartPoint"][0], "Y": region["StartPoint"][1], "Z": passEndDepth, "F": op.vertFeed})) lz = passEndDepth z = obj.ClearanceHeight.Value - op.commandlist.append(Path.Command("(Adaptive - depth: %f)"%passEndDepth)) + op.commandlist.append(Path.Command("(Adaptive - depth: %f)" % passEndDepth)) # add adaptive paths for pth in region["AdaptivePaths"]: - motionType = pth[0] #[0] contains motion type + motionType = pth[0] # [0] contains motion type - for pt in pth[1]: #[1] contains list of points + for pt in pth[1]: # [1] contains list of points x = pt[0] y = pt[1] @@ -326,37 +331,37 @@ def GenerateGCode(op,obj,adaptiveResults, helixDiameter): if motionType == area.AdaptiveMotionType.Cutting: z = passEndDepth if z != lz: - op.commandlist.append(Path.Command("G1", { "Z":z,"F": op.vertFeed})) + op.commandlist.append(Path.Command("G1", {"Z": z, "F": op.vertFeed})) - op.commandlist.append(Path.Command("G1", { "X": x, "Y":y, "F": op.horizFeed})) + op.commandlist.append(Path.Command("G1", {"X": x, "Y": y, "F": op.horizFeed})) elif motionType == area.AdaptiveMotionType.LinkClear: z = passEndDepth + stepUp if z != lz: - op.commandlist.append(Path.Command("G0", { "Z":z})) + op.commandlist.append(Path.Command("G0", {"Z": z})) - op.commandlist.append(Path.Command("G0", { "X": x, "Y":y})) + op.commandlist.append(Path.Command("G0", {"X": x, "Y": y})) elif motionType == area.AdaptiveMotionType.LinkNotClear: z = obj.ClearanceHeight.Value if z != lz: - op.commandlist.append(Path.Command("G0", { "Z":z})) + op.commandlist.append(Path.Command("G0", {"Z": z})) - op.commandlist.append(Path.Command("G0", { "X": x, "Y":y})) + op.commandlist.append(Path.Command("G0", {"X": x, "Y": y})) # elif motionType == area.AdaptiveMotionType.LinkClearAtPrevPass: # if lx!=x or ly!=y: # op.commandlist.append(Path.Command("G0", { "X": lx, "Y":ly, "Z":passStartDepth+stepUp})) # op.commandlist.append(Path.Command("G0", { "X": x, "Y":y, "Z":passStartDepth+stepUp})) - lx = x - ly = y + # lx = x + # ly = y lz = z # return to safe height in this Z pass z = obj.ClearanceHeight.Value if z != lz: - op.commandlist.append(Path.Command("G0", { "Z":z})) + op.commandlist.append(Path.Command("G0", {"Z": z})) lz = z @@ -365,17 +370,18 @@ def GenerateGCode(op,obj,adaptiveResults, helixDiameter): # return to safe height in this Z pass z = obj.ClearanceHeight.Value if z != lz: - op.commandlist.append(Path.Command("G0", { "Z":z})) + op.commandlist.append(Path.Command("G0", {"Z": z})) lz = z z = obj.ClearanceHeight.Value if z != lz: - op.commandlist.append(Path.Command("G0", { "Z":z})) + op.commandlist.append(Path.Command("G0", {"Z": z})) lz = z -def Execute(op,obj): + +def Execute(op, obj): # pylint: disable=global-statement global sceneGraph global topZ @@ -384,10 +390,10 @@ def Execute(op,obj): Console.PrintMessage("*** Adaptive toolpath processing started...\n") - #hide old toolpaths during recalculation + # hide old toolpaths during recalculation obj.Path = Path.Path("(Calculating...)") - #store old visibility state + # store old visibility state job = op.getJob(obj) oldObjVisibility = obj.ViewObject.Visibility oldJobVisibility = job.ViewObject.Visibility @@ -415,12 +421,12 @@ def Execute(op,obj): else: stockBB = op.stock.Shape.BoundBox - v=[] - v.append(FreeCAD.Vector(stockBB.XMin,stockBB.YMin,0)) - v.append(FreeCAD.Vector(stockBB.XMax,stockBB.YMin,0)) - v.append(FreeCAD.Vector(stockBB.XMax,stockBB.YMax,0)) - v.append(FreeCAD.Vector(stockBB.XMin,stockBB.YMax,0)) - v.append(FreeCAD.Vector(stockBB.XMin,stockBB.YMin,0)) + v = [] + v.append(FreeCAD.Vector(stockBB.XMin, stockBB.YMin, 0)) + v.append(FreeCAD.Vector(stockBB.XMax, stockBB.YMin, 0)) + v.append(FreeCAD.Vector(stockBB.XMax, stockBB.YMax, 0)) + v.append(FreeCAD.Vector(stockBB.XMin, stockBB.YMax, 0)) + v.append(FreeCAD.Vector(stockBB.XMin, stockBB.YMin, 0)) stockPaths.append([v]) stockPath2d = convertTo2d(stockPaths) @@ -433,14 +439,13 @@ def Execute(op,obj): else: opType = area.AdaptiveOperationType.ClearingInside - else: # profiling + else: # profiling if obj.Side == "Outside": opType = area.AdaptiveOperationType.ProfilingOutside else: opType = area.AdaptiveOperationType.ProfilingInside - keepToolDownRatio = 3.0 if hasattr(obj, 'KeepToolDownRatio'): keepToolDownRatio = float(obj.KeepToolDownRatio) @@ -450,14 +455,14 @@ def Execute(op,obj): inputStateObject = { "tool": float(op.tool.Diameter), "tolerance": float(obj.Tolerance), - "geometry" : path2d, + "geometry": path2d, "stockGeometry": stockPath2d, - "stepover" : float(obj.StepOver), + "stepover": float(obj.StepOver), "effectiveHelixDiameter": float(helixDiameter), "operationType": obj.OperationType, "side": obj.Side, - "forceInsideOut" : obj.ForceInsideOut, - "finishingProfile" : obj.FinishingProfile, + "forceInsideOut": obj.ForceInsideOut, + "finishingProfile": obj.FinishingProfile, "keepToolDownRatio": keepToolDownRatio, "stockToLeave": float(obj.StockToLeave) } @@ -465,7 +470,7 @@ def Execute(op,obj): inputStateChanged = False adaptiveResults = None - if obj.AdaptiveOutputState != None and obj.AdaptiveOutputState != "": + if obj.AdaptiveOutputState is not None and obj.AdaptiveOutputState != "": adaptiveResults = obj.AdaptiveOutputState if json.dumps(obj.AdaptiveInputState) != json.dumps(inputStateObject): @@ -474,33 +479,33 @@ def Execute(op,obj): # progress callback fn, if return true it will stop processing def progressFn(tpaths): - for path in tpaths: #path[0] contains the MotionType, #path[1] contains list of points + for path in tpaths: # path[0] contains the MotionType, #path[1] contains list of points if path[0] == area.AdaptiveMotionType.Cutting: - sceneDrawPath(path[1],(0,0,1)) + sceneDrawPath(path[1], (0, 0, 1)) else: - sceneDrawPath(path[1],(1,0,1)) + sceneDrawPath(path[1], (1, 0, 1)) FreeCADGui.updateGui() - return obj.StopProcessing + return obj.StopProcessing start = time.time() if inputStateChanged or adaptiveResults is None: a2d = area.Adaptive2d() - a2d.stepOverFactor = 0.01*obj.StepOver + a2d.stepOverFactor = 0.01 * obj.StepOver a2d.toolDiameter = float(op.tool.Diameter) - a2d.helixRampDiameter = helixDiameter + a2d.helixRampDiameter = helixDiameter a2d.keepToolDownDistRatio = keepToolDownRatio - a2d.stockToLeave =float(obj.StockToLeave) + a2d.stockToLeave = float(obj.StockToLeave) a2d.tolerance = float(obj.Tolerance) a2d.forceInsideOut = obj.ForceInsideOut a2d.finishingProfile = obj.FinishingProfile a2d.opType = opType # EXECUTE - results = a2d.Execute(stockPath2d,path2d,progressFn) + results = a2d.Execute(stockPath2d, path2d, progressFn) # need to convert results to python object to be JSON serializable adaptiveResults = [] @@ -509,19 +514,18 @@ def Execute(op,obj): "HelixCenterPoint": result.HelixCenterPoint, "StartPoint": result.StartPoint, "AdaptivePaths": result.AdaptivePaths, - "ReturnMotionType": result.ReturnMotionType }) - + "ReturnMotionType": result.ReturnMotionType}) # GENERATE - GenerateGCode(op,obj,adaptiveResults,helixDiameter) + GenerateGCode(op, obj, adaptiveResults, helixDiameter) if not obj.StopProcessing: Console.PrintMessage("*** Done. Elapsed time: %f sec\n\n" %(time.time()-start)) obj.AdaptiveOutputState = adaptiveResults - obj.AdaptiveInputState=inputStateObject + obj.AdaptiveInputState = inputStateObject else: - Console.PrintMessage("*** Processing cancelled (after: %f sec).\n\n" %(time.time()-start)) + Console.PrintMessage("*** Processing cancelled (after: %f sec).\n\n" % (time.time()-start)) finally: obj.ViewObject.Visibility = oldObjVisibility @@ -574,47 +578,43 @@ class PathAdaptive(PathOp.ObjectOp): obj.addProperty("App::PropertyEnumeration", "OperationType", "Adaptive", "Type of adaptive operation") obj.OperationType = ['Clearing', 'Profiling'] # side of profile that cutter is on in relation to direction of profile - obj.addProperty("App::PropertyFloat", "Tolerance", "Adaptive", "Influences accuracy and performance") + obj.addProperty("App::PropertyFloat", "Tolerance", "Adaptive", "Influences accuracy and performance") obj.addProperty("App::PropertyPercent", "StepOver", "Adaptive", "Percent of cutter diameter to step over on each pass") obj.addProperty("App::PropertyDistance", "LiftDistance", "Adaptive", "Lift distance for rapid moves") obj.addProperty("App::PropertyDistance", "KeepToolDownRatio", "Adaptive", "Max length of keep tool down path compared to direct distance between points") obj.addProperty("App::PropertyDistance", "StockToLeave", "Adaptive", "How much stock to leave (i.e. for finishing operation)") # obj.addProperty("App::PropertyBool", "ProcessHoles", "Adaptive","Process holes as well as the face outline") - obj.addProperty("App::PropertyBool", "ForceInsideOut", "Adaptive","Force plunging into material inside and clearing towards the edges") - obj.addProperty("App::PropertyBool", "FinishingProfile", "Adaptive","To take a finishing profile path at the end") + obj.addProperty("App::PropertyBool", "ForceInsideOut", "Adaptive", "Force plunging into material inside and clearing towards the edges") + obj.addProperty("App::PropertyBool", "FinishingProfile", "Adaptive", "To take a finishing profile path at the end") obj.addProperty("App::PropertyBool", "Stopped", "Adaptive", "Stop processing") - obj.setEditorMode('Stopped', 2) #hide this property + obj.setEditorMode('Stopped', 2) # hide this property obj.addProperty("App::PropertyBool", "StopProcessing", "Adaptive", "Stop processing") obj.setEditorMode('StopProcessing', 2) # hide this property - obj.addProperty("App::PropertyBool", "UseHelixArcs", "Adaptive","Use Arcs (G2) for helix ramp") + obj.addProperty("App::PropertyBool", "UseHelixArcs", "Adaptive", "Use Arcs (G2) for helix ramp") obj.addProperty("App::PropertyPythonObject", "AdaptiveInputState", "Adaptive", "Internal input state") obj.addProperty("App::PropertyPythonObject", "AdaptiveOutputState", "Adaptive", "Internal output state") - obj.setEditorMode('AdaptiveInputState', 2) #hide this property - obj.setEditorMode('AdaptiveOutputState', 2) #hide this property - obj.addProperty("App::PropertyAngle", "HelixAngle", "Adaptive", "Helix ramp entry angle (degrees)") - obj.addProperty("App::PropertyAngle", "HelixConeAngle", "Adaptive", "Helix cone angle (degrees)") + obj.setEditorMode('AdaptiveInputState', 2) # hide this property + obj.setEditorMode('AdaptiveOutputState', 2) # hide this property + obj.addProperty("App::PropertyAngle", "HelixAngle", "Adaptive", "Helix ramp entry angle (degrees)") + obj.addProperty("App::PropertyAngle", "HelixConeAngle", "Adaptive", "Helix cone angle (degrees)") obj.addProperty("App::PropertyLength", "HelixDiameterLimit", "Adaptive", "Limit helix entry diameter, if limit larger than tool diameter or 0, tool diameter is used") - if not hasattr(obj, "UseOutline"): - obj.addProperty("App::PropertyBool", - "UseOutline", - "Adaptive", - "Uses the outline of the base geometry.") + obj.addProperty("App::PropertyBool", "UseOutline", "Adaptive", "Uses the outline of the base geometry.") def opSetDefaultValues(self, obj, job): - obj.Side="Inside" + obj.Side = "Inside" obj.OperationType = "Clearing" obj.Tolerance = 0.1 obj.StepOver = 20 - obj.LiftDistance=0 + obj.LiftDistance = 0 # obj.ProcessHoles = True obj.ForceInsideOut = False obj.FinishingProfile = True @@ -623,7 +623,7 @@ class PathAdaptive(PathOp.ObjectOp): obj.HelixAngle = 5 obj.HelixConeAngle = 0 obj.HelixDiameterLimit = 0.0 - obj.AdaptiveInputState ="" + obj.AdaptiveInputState = "" obj.AdaptiveOutputState = "" obj.StockToLeave = 0 obj.KeepToolDownRatio = 3.0 @@ -634,17 +634,22 @@ class PathAdaptive(PathOp.ObjectOp): '''opExecute(obj) ... called whenever the receiver needs to be recalculated. See documentation of execute() for a list of base functionality provided. Should be overwritten by subclasses.''' - Execute(self,obj) - + Execute(self, obj) + def opOnDocumentRestored(self, obj): if not hasattr(obj, 'HelixConeAngle'): obj.addProperty("App::PropertyAngle", "HelixConeAngle", "Adaptive", "Helix cone angle (degrees)") + if not hasattr(obj, "UseOutline"): + obj.addProperty("App::PropertyBool", + "UseOutline", + "Adaptive", + "Uses the outline of the base geometry.") -def Create(name, obj = None): +def Create(name, obj=None): '''Create(name) ... Creates and returns a Adaptive operation.''' if obj is None: obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", name) - obj.Proxy = PathAdaptive(obj,name) + obj.Proxy = PathAdaptive(obj, name) return obj