Path: added use of return_last to contour.

Path: bug fixes
This commit is contained in:
sliptonic
2017-05-17 16:12:32 -05:00
committed by wmayer
parent aad865375b
commit 0405a67c24
3 changed files with 71 additions and 40 deletions

View File

@@ -31,11 +31,12 @@ from PySide import QtCore
import ArchPanel
import Part
from PathScripts.PathUtils import waiting_effects
from PathScripts.PathUtils import makeWorkplane
LOG_MODULE = 'PathContour'
PathLog.setLevel(PathLog.Level.INFO, LOG_MODULE)
#PathLog.trackModule('PathContour')
FreeCAD.setLogLevel('Path.Area',0)
FreeCAD.setLogLevel('Path.Area', 0)
if FreeCAD.GuiUp:
import FreeCADGui
@@ -79,7 +80,6 @@ class ObjectContour:
# 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"))
# Contour Properties
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"))
@@ -92,6 +92,7 @@ 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"))
obj.Proxy = self
self.endVector = None
def __getstate__(self):
return None
@@ -101,6 +102,8 @@ class ObjectContour:
def onChanged(self, obj, prop):
pass
# if prop in ['ClearanceHeight', 'StartPoint']:
# obj.StartPoint.z = obj.ClearanceHeight.Value
def setDepths(proxy, obj):
PathLog.track()
@@ -127,7 +130,7 @@ class ObjectContour:
def _buildPathArea(self, obj, baseobject, start=None):
PathLog.track()
profile = Path.Area()
profile.setPlane(Part.makeCircle(10))
profile.setPlane(makeWorkplane(baseobject))
profile.add(baseobject)
profileparams = {'Fill': 0,
@@ -138,10 +141,6 @@ class ObjectContour:
else:
profileparams['Offset'] = self.radius+obj.OffsetExtra.Value
profile.setParams(**profileparams)
# PathLog.debug("About to profile with params: {}".format(profileparams))
PathLog.debug("About to profile with params: {}".format(profile.getParams()))
depthparams = depth_params(
clearance_height=obj.ClearanceHeight.Value,
rapid_safety_space=obj.SafeHeight.Value,
@@ -151,6 +150,10 @@ class ObjectContour:
final_depth=obj.FinalDepth.Value,
user_depths=None)
PathLog.debug('depths: {}'.format(depthparams.get_depths()))
profile.setParams(**profileparams)
PathLog.debug("Contour with params: {}".format(profile.getParams()))
sections = profile.makeSections(mode=0, project=True, heights=depthparams.get_depths())
shapelist = [sec.getShape() for sec in sections]
@@ -159,25 +162,29 @@ class ObjectContour:
'feedrate_v': self.vertFeed,
'verbose': True,
'resume_height': obj.StepDown.Value,
'retraction': obj.ClearanceHeight.Value}
'retraction': obj.ClearanceHeight.Value,
'return_end': True}
if obj.Direction == 'CCW':
params['orientation'] = 1
else:
params['orientation'] = 0
if obj.UseStartPoint is True and obj.StartPoint is not None:
params['start'] = obj.StartPoint
if self.endVector is not None:
params['start'] = self.endVector
elif start is not None:
params['start'] = start
pp = Path.fromShapes(**params)
(pp, end_vector) = Path.fromShapes(**params)
PathLog.debug("Generating Path with params: {}".format(params))
PathLog.debug(pp)
PathLog.debug('pp: {}, end vector: {}'.format(pp, end_vector))
self.endVector = end_vector
return pp
def execute(self, obj):
PathLog.track()
import Part
self.endVector = None
commandlist = []
toolLoad = obj.ToolController
@@ -211,25 +218,27 @@ class ObjectContour:
if baseobject is None:
return
# Let's always start by rapid to clearance...just for safety
commandlist.append(Path.Command("G0", {"Z": obj.ClearanceHeight.Value}))
if hasattr(baseobject, "Proxy"):
if isinstance(baseobject.Proxy, ArchPanel.PanelSheet): # process the sheet
baseobject.Proxy.execute(baseobject)
for subobj in baseobject.Group: # process the group of panels
if isinstance(subobj.Proxy, ArchPanel.PanelCut):
shapes = baseobject.Proxy.getOutlines(baseobject, transform=True)
for shape in shapes:
f = Part.makeFace([shape], 'Part::FaceMakerSimple')
thickness = baseobject.Group[0].Source.Thickness
contourshape = f.extrude(FreeCAD.Vector(0, 0, thickness))
try:
commandlist.extend(self._buildPathArea(obj, contourshape).Commands)
except Exception as e:
print(e)
FreeCAD.Console.PrintError("Something unexpected happened. Unable to generate a contour path. Check project and tool config.")
shapes = baseobject.Proxy.getOutlines(baseobject, transform=True)
for shape in shapes:
f = Part.makeFace([shape], 'Part::FaceMakerSimple')
thickness = baseobject.Group[0].Source.Thickness
contourshape = f.extrude(FreeCAD.Vector(0, 0, thickness))
try:
commandlist.extend(self._buildPathArea(obj, contourshape, 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.")
else:
env = PathUtils.getEnvelope(baseobject.Shape, obj.StartDepth)
bb = baseobject.Shape.BoundBox
env = PathUtils.getEnvelope(baseobject.Shape, bb.ZLength + (obj.StartDepth.Value-bb.ZMax))
try:
commandlist.extend(self._buildPathArea(obj, env).Commands)
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.")
@@ -285,6 +294,7 @@ class _CommandSetStartPoint:
obj = FreeCADGui.Selection.getSelection()[0]
obj.StartPoint.x = point.x
obj.StartPoint.y = point.y
obj.StartPoint.z = obj.ClearanceHeight.Value
def Activated(self):
FreeCADGui.Snapper.getPoint(callback=self.setpoint)
@@ -371,8 +381,8 @@ class TaskPanel:
self.obj.OffsetExtra = FreeCAD.Units.Quantity(self.form.extraOffset.text()).Value
if hasattr(self.obj, "UseComp"):
self.obj.UseComp = self.form.useCompensation.isChecked()
if hasattr(self.obj, "UseStartPoint"):
self.obj.UseStartPoint = self.form.useStartPoint.isChecked()
# if hasattr(self.obj, "UseStartPoint"):
# self.obj.UseStartPoint = self.form.useStartPoint.isChecked()
if hasattr(self.obj, "Direction"):
self.obj.Direction = str(self.form.direction.currentText())
if hasattr(self.obj, "ToolController"):
@@ -389,7 +399,7 @@ class TaskPanel:
self.form.stepDown.setText(FreeCAD.Units.Quantity(self.obj.StepDown.Value, FreeCAD.Units.Length).UserString)
self.form.extraOffset.setText(FreeCAD.Units.Quantity(self.obj.OffsetExtra.Value, FreeCAD.Units.Length).UserString)
self.form.useCompensation.setChecked(self.obj.UseComp)
self.form.useStartPoint.setChecked(self.obj.UseStartPoint)
# self.form.useStartPoint.setChecked(self.obj.UseStartPoint)
index = self.form.direction.findText(
self.obj.Direction, QtCore.Qt.MatchFixedString)

View File

@@ -31,11 +31,12 @@ import Part
from FreeCAD import Vector
import PathScripts.PathLog as PathLog
from PathScripts.PathUtils import waiting_effects
from PathScripts.PathUtils import makeWorkplane
LOG_MODULE = 'PathMillFace'
PathLog.setLevel(PathLog.Level.INFO, LOG_MODULE)
PathLog.trackModule()
FreeCAD.setLogLevel('Path.Area',0)
FreeCAD.setLogLevel('Path.Area', 0)
FreeCADGui = None
if FreeCAD.GuiUp:
@@ -167,7 +168,7 @@ class ObjectFace:
PathLog.track()
boundary = Path.Area()
boundary.setPlane(Part.makeCircle(10))
boundary.setPlane(makeWorkplane(baseobject))
boundary.add(baseobject)
stepover = (self.radius * 2) * (float(obj.StepOver)/100)
@@ -204,7 +205,6 @@ class ObjectFace:
'resume_height': obj.StepDown,
'retraction': obj.ClearanceHeight.Value}
# if obj.Direction == 'CCW':
# params['orientation'] = 1
# else:
@@ -269,12 +269,12 @@ class ObjectFace:
# if user wants the boundbox, calculate that
PathLog.info("Boundary Shape: {}".format(obj.BoundaryShape))
bb = planeshape.BoundBox
if obj.BoundaryShape == 'Boundbox':
bb = planeshape.BoundBox
bbperim = Part.makeBox(bb.XLength, bb.YLength, 1, Vector(bb.XMin, bb.YMin, bb.ZMin), Vector(0, 0, 1))
env = PathUtils.getEnvelope(bbperim, obj.StartDepth)
env = PathUtils.getEnvelope(bbperim, bb.ZLength + (obj.StartDepth.Value-bb.ZMax))
else:
env = PathUtils.getEnvelope(planeshape, obj.StartDepth)
env = PathUtils.getEnvelope(planeshape, bb.ZLength + (obj.StartDepth.Value-bb.ZMax))
try:
commandlist.extend(self._buildPathArea(obj, env).Commands)

View File

@@ -39,7 +39,8 @@ from PySide import QtGui
LOG_MODULE = 'PathUtils'
PathLog.setLevel(PathLog.Level.INFO, LOG_MODULE)
# PathLog.trackModule('PathUtils')
FreeCAD.setLogLevel('Path.Area',0)
FreeCAD.setLogLevel('Path.Area', 0)
def waiting_effects(function):
def new_function(*args, **kwargs):
@@ -61,6 +62,7 @@ def waiting_effects(function):
def cleanedges(splines, precision):
'''cleanedges([splines],precision). Convert BSpline curves, Beziers, to arcs that can be used for cnc paths.
Returns Lines as is. Filters Circle and Arcs for over 180 degrees. Discretizes Ellipses. Ignores other geometry. '''
PathLog.track()
edges = []
for spline in splines:
if geomType(spline) == "BSplineCurve":
@@ -97,6 +99,7 @@ def cleanedges(splines, precision):
def curvetowire(obj, steps):
'''adapted from DraftGeomUtils, because the discretize function changed a bit '''
PathLog.track()
points = obj.copy().discretize(Distance=eval('steps'))
p0 = points[0]
edgelist = []
@@ -186,6 +189,7 @@ def loopdetect(obj, edge1, edge2):
def filterArcs(arcEdge):
'''filterArcs(Edge) -used to split arcs that over 180 degrees. Returns list '''
PathLog.track()
s = arcEdge
if isinstance(s.Curve, Part.Circle):
splitlist = []
@@ -221,6 +225,18 @@ def filterArcs(arcEdge):
return splitlist
def makeWorkplane(shape):
"""
Creates a workplane circle at the ZMin level.
"""
PathLog.track()
loc = FreeCAD.Vector(shape.BoundBox.Center.x,
shape.BoundBox.Center.y,
shape.BoundBox.ZMin)
c = Part.makeCircle(10, loc)
return c
def getEnvelope(partshape, stockheight=None):
'''
getEnvelop(partshape, stockheight=None)
@@ -230,13 +246,17 @@ def getEnvelope(partshape, stockheight=None):
partshape = solid object
stockheight = float
'''
PathLog.track(partshape, stockheight)
area = Path.Area(Fill=1, Coplanar=0).add(partshape)
area.setPlane(Part.makeCircle(10))
sec = area.makeSections(heights=[1.0], project=True)[0].getShape(rebuild=True)
# 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()
if stockheight is not None:
return sec.extrude(FreeCAD.Vector(0, 0, stockheight))
else:
return sec.extrude(FreeCAD.Vector(0, 0, partshape.BoundBox.ZMax))
return sec.extrude(FreeCAD.Vector(0, 0, partshape.BoundBox.ZLength))
def reverseEdge(e):
@@ -618,6 +638,7 @@ def sort_jobs(locations, keys, attractors=[]):
return out
class depth_params:
'''calculates the intermediate depth values for various operations given the starting, ending, and stepdown parameters
(self, clearance_height, rapid_safety_space, start_depth, step_down, z_finish_depth, final_depth, [user_depths=None])