path: more collision support

Made depthparams an iterable.
This commit is contained in:
sliptonic
2017-06-21 15:23:38 -05:00
committed by wmayer
parent 0326b5ba49
commit 8b804d71ae
7 changed files with 158 additions and 88 deletions

View File

@@ -178,21 +178,11 @@ class ObjectContour:
simobj = None
if getsim:
#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()
sec = profile.makeSections(mode=0, project=False, heights=depthparams.get_depths())[-1].getShape()
simobj = sec.extrude(FreeCAD.Vector(0,0,baseobject.BoundBox.ZMax))
#c = CollisionTester()
#simobj = c.getCollisionSim(base.Shape, cutPath)
return pp, simobj

View File

@@ -168,15 +168,18 @@ class ObjectPocket:
return None
@waiting_effects
def _buildPathArea(self, obj, envelopeshape):
def _buildPathArea(self, obj, envelopeshape, getsim=False):
PathLog.track()
pocket = Path.Area()
pocket.setPlane(Part.makeCircle(10))
pocket.add(envelopeshape)
removalshape = FreeCAD.ActiveDocument.addObject("Part::Feature", "Envelope")
removalshape.Shape = envelopeshape
stepover = (self.radius * 2) * (float(obj.StepOver)/100)
pocketparams = {'Fill': 2,
pocketparams = {'Fill': 0,
'Coplanar': 0,
'PocketMode': 1,
'SectionCount': -1,
@@ -214,11 +217,23 @@ class ObjectPocket:
pp = Path.fromShapes(**params)
PathLog.debug("Generating Path with params: {}".format(params))
PathLog.debug(pp)
return pp
def execute(self, obj):
simobj = None
if getsim:
pocketparams['Thicken'] = True
pocketparams['ToolRadius']= self.radius - self.radius *.005
pocket.setParams(**pocketparams)
#pocket.makeSections(mode=0, project=False, heights=depthparams.get_depths())
simobj = pocket.getShape().extrude(FreeCAD.Vector(0,0,obj.StepDown.Value))
removalshape = FreeCAD.ActiveDocument.addObject("Part::Feature", "simshape")
removalshape.Shape = simobj
return pp, simobj
def execute(self, obj, getsim=False):
PathLog.track()
commandlist = []
simlist = []
commandlist.append(Path.Command("(" + obj.Label + ")"))
if not obj.Active:
path = Path.Path("(inactive operation)")
@@ -266,7 +281,10 @@ class ObjectPocket:
removalshape.Shape = env.cut(baseobject.Shape)
try:
commandlist.extend(self._buildPathArea(obj, env.cut(baseobject.Shape)).Commands)
(pp, sim) = self._buildPathArea(obj, env.cut(baseobject.Shape), getsim=getsim)
if sim is not None:
simlist.append(sim)
commandlist.extend(pp.Commands)
except Exception as e:
FreeCAD.Console.PrintError(e)
FreeCAD.Console.PrintError("Something unexpected happened. Unable to generate a pocket path. Check project and tool config.")
@@ -275,7 +293,12 @@ class ObjectPocket:
env = PathUtils.getEnvelope(baseobject.Shape, subshape=None, stockheight=obj.StartDepth)
try:
commandlist.extend(self._buildPathArea(obj, env.cut(baseobject.Shape)).Commands)
(pp, sim) = self._buildPathArea(obj, env.cut(baseobject.Shape), getsim=getsim)
commandlist.extend(pp.Commands)
if sim is not None:
simlist.append(sim)
#commandlist.extend(self._buildPathArea(obj, env.cut(baseobject.Shape)).Commands)
except Exception as e:
FreeCAD.Console.PrintError(e)
FreeCAD.Console.PrintError("Something unexpected happened. Unable to generate a pocket path. Check project and tool config.")
@@ -286,6 +309,12 @@ class ObjectPocket:
path = Path.Path(commandlist)
obj.Path = path
obj.ViewObject.Visibility = True
if len(simlist) == 0:
return None
if len(simlist) > 1:
return simlist[0].fuse(simlist[1:])
else:
return simlist[0]
class _CommandSetPocketStartPoint:

View File

@@ -146,7 +146,7 @@ class ObjectProfile:
obj.Base = baselist
self.execute(obj)
def _buildPathArea(self, obj, baseobject, isHole=False, start=None):
def _buildPathArea(self, obj, baseobject, isHole=False, start=None, getsim=False):
PathLog.track()
profile = Path.Area()
profile.setPlane(Part.makeCircle(10))
@@ -213,9 +213,17 @@ class ObjectProfile:
PathLog.debug("Generating Path with params: {}".format(params))
PathLog.debug(pp)
return pp
simobj = None
if getsim:
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(mode=0, project=False, heights=depthparams.get_depths())[-1].getShape()
simobj = sec.extrude(FreeCAD.Vector(0,0,baseobject.BoundBox.ZMax))
def execute(self, obj):
return pp, simobj
def execute(self, obj, getsim=False):
import Part
if not obj.Active:
@@ -275,7 +283,8 @@ class ObjectProfile:
if (drillable and obj.processCircles) or (not drillable and obj.processHoles):
env = PathUtils.getEnvelope(baseobject.Shape, subshape=f, stockheight=obj.StartDepth)
try:
commandlist.extend(self._buildPathArea(obj, baseobject=env, isHole=True, start=None).Commands)
(pp, sim) = self._buildPathArea(obj, baseobject=env, isHole=True, start=None, getsim=getsim)
commandlist.extend(pp.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.")
@@ -286,7 +295,8 @@ class ObjectProfile:
if obj.processPerimeter:
env = PathUtils.getEnvelope(baseobject.Shape, subshape=profileshape, stockheight=obj.StartDepth)
try:
commandlist.extend(self._buildPathArea(obj, baseobject=env, start=None).Commands)
(pp, sim) = self._buildPathArea(obj, baseobject=env, start=None, getsim=getsim)
commandlist.extend(pp.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.")
@@ -301,7 +311,8 @@ class ObjectProfile:
f = Part.makeFace(wire, 'Part::FaceMakerSimple')
env = PathUtils.getEnvelope(baseobject.Shape, subshape=f, stockheight=obj.StartDepth)
try:
commandlist.extend(self._buildPathArea(obj, baseobject=env, isHole=False, start=None).Commands)
(pp, sim) = self._buildPathArea(obj, baseobject=env, isHole=False, start=None, getsim=getsim)
commandlist.extend(pp.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.")
@@ -314,7 +325,8 @@ class ObjectProfile:
f = Part.makeFace(wire, 'Part::FaceMakerSimple')
env = PathUtils.getEnvelope(baseobject.Shape, subshape=f, stockheight=obj.StartDepth)
try:
commandlist.extend(self._buildPathArea(obj, baseobject=env, isHole=True, start=None).Commands)
(pp, sim) = self._buildPathArea(obj, baseobject=env, isHole=True, start=None, getsim=getsim)
commandlist.extend(pp.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.")

View File

@@ -35,7 +35,7 @@ from PathScripts.PathUtils import waiting_effects
"""Path Profile from Edges Object and Command"""
LOG_MODULE = 'PathProfileEdges'
PathLog.setLevel(PathLog.Level.DEBUG, LOG_MODULE)
PathLog.setLevel(PathLog.Level.INFO, LOG_MODULE)
# PathLog.trackModule('PathProfileEdges')
if FreeCAD.GuiUp:
@@ -142,7 +142,7 @@ class ObjectProfile:
@waiting_effects
def _buildPathArea(self, obj, baseobject, start=None):
def _buildPathArea(self, obj, baseobject, start=None, getsim=False):
PathLog.track()
profile = Path.Area()
profile.setPlane(Part.makeCircle(10))
@@ -185,12 +185,6 @@ class ObjectProfile:
'resume_height': obj.StepDown.Value,
'retraction': obj.ClearanceHeight.Value}
# Reverse the direction for holes
# if isHole:
# direction = "CW" if obj.Direction == "CCW" else "CCW"
# else:
# direction = obj.Direction
if obj.Direction == 'CCW':
params['orientation'] = 0
else:
@@ -203,26 +197,18 @@ class ObjectProfile:
PathLog.debug("Generating Path with params: {}".format(params))
PathLog.debug(pp)
# if True:
# from PathScripts.PathUtils import CollisionTester
# parentJob = PathUtils.findParentJob(obj)
# if parentJob is None:
# pass
# base = parentJob.Base
# if base is None:
# pass
simobj = None
if getsim:
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(mode=0, project=False, heights=depthparams.get_depths())[-1].getShape()
simobj = sec.extrude(FreeCAD.Vector(0,0,baseobject.BoundBox.ZMax))
# 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
return pp, simobj
def execute(self, obj):
def execute(self, obj, getsim=False):
# import Part # math #DraftGeomUtils
commandlist = []
@@ -281,8 +267,8 @@ class ObjectProfile:
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)
(pp, sim) = self._buildPathArea(obj, baseobject=env, start=obj.StartPoint, getsim=getsim)
commandlist.extend(pp.Commands)
except Exception as e:
FreeCAD.Console.PrintError(e)
@@ -294,6 +280,7 @@ class ObjectProfile:
path = Path.Path(commandlist)
obj.Path = path
obj.ViewObject.Visibility = True
return sim
class _ViewProviderProfile:

View File

@@ -26,10 +26,10 @@ Path projects. Ideally, the user could execute these utilities from an icon
to make sure tools are selected and configured and defaults have been revised'''
from __future__ import print_function
from PySide import QtCore, QtGui
from PySide import QtCore
import FreeCAD
import FreeCADGui
import PathScripts.PathUtils as PU
#import PathScripts.PathUtils as PU
import PathScripts
import PathScripts.PathCollision as PC
# Qt tanslation handling
@@ -81,18 +81,32 @@ class CommandPathSanity:
PC.getCollisionObject(self.baseobj, simobj)
#r.original = self.baseobj
if isinstance(item.Proxy, PathScripts.PathProfile.ObjectProfile):
if item.Active:
operationcount +=1
simobj = item.Proxy.execute(item, getsim=True)
if simobj is not None:
print ('collision detected')
PC.getCollisionObject(self.baseobj, simobj)
#r.original = self.baseobj
if isinstance(item.Proxy, PathScripts.PathProfileEdges.ObjectProfile):
if item.Active:
operationcount +=1
simobj = item.Proxy.execute(item, getsim=True)
if simobj is not None:
print ('collision detected')
PC.getCollisionObject(self.baseobj, simobj)
#r.original = self.baseobj
if isinstance(item.Proxy, PathScripts.PathPocket.ObjectPocket):
if item.Active:
operationcount +=1
simobj = item.Proxy.execute(item, getsim=True)
if simobj is not None:
print ('collision detected')
PC.getCollisionObject(self.baseobj, simobj)
#r.original = self.baseobj
if isinstance(item.Proxy, PathScripts.PathDrilling.ObjectDrilling):
if item.Active:

View File

@@ -685,44 +685,87 @@ class depth_params:
user_depths: List of specified depths
'''
def __init__(self, clearance_height, rapid_safety_space, start_depth, step_down, z_finish_step, final_depth, user_depths=None):
def __init__(self, clearance_height, rapid_safety_space, start_depth, step_down, z_finish_step, final_depth, user_depths=None, equalstep=False):
'''self, clearance_height, rapid_safety_space, start_depth, step_down, z_finish_depth, final_depth, [user_depths=None]'''
if z_finish_step > step_down:
raise ValueError('z_finish_step must be less than step_down')
self.clearance_height = clearance_height
self.rapid_safety_space = math.fabs(rapid_safety_space)
self.start_depth = start_depth
self.step_down = math.fabs(step_down)
self.z_finish_step = math.fabs(z_finish_step)
self.final_depth = final_depth
self.user_depths = user_depths
self.__clearance_height = clearance_height
self.__rapid_safety_space = math.fabs(rapid_safety_space)
self.__start_depth = start_depth
self.__step_down = math.fabs(step_down)
self.__z_finish_step = math.fabs(z_finish_step)
self.__final_depth = final_depth
self.__user_depths = user_depths
self.data = self.__get_depths(equalstep=equalstep)
self.index = 0
def get_depths(self, equalstep=False):
def __iter__(self):
return self
def next(self):
if self.index == len(self.data):
raise StopIteration
self.index = self.index + 1
return self.data[self.index - 1]
@property
def clearance_height(self):
"""
Height of all vises, clamps, and other obstructions. Rapid moves at clearance height
are always assumed to be safe from collision.
"""
return self.__clearance_height
@property
def rapid_safety_space(self):
return self.__rapid_safety_space
@property
def start_depth(self):
return self.__start_depth
@property
def step_down(self):
return self.__step_down
@property
def z_finish_depth(self):
return self.__z_finish_depth
@property
def final_depth(self):
return self.__final_depth
@property
def user_depths(self):
return self.__user_depths
def __get_depths(self, equalstep=False):
'''returns a list of depths to be used in order from first to last.
equalstep=True: all steps down before the finish pass will be equalized.'''
if self.user_depths is not None:
return self.user_depths
return self.__user_depths
total_depth = self.start_depth - self.final_depth
total_depth = self.__start_depth - self.__final_depth
if total_depth < 0:
return []
depths = [self.final_depth]
depths = [self.__final_depth]
# apply finish step if necessary
if self.z_finish_step > 0:
if self.z_finish_step < total_depth:
depths.append(self.z_finish_step + self.final_depth)
if self.__z_finish_step > 0:
if self.__z_finish_step < total_depth:
depths.append(self.__z_finish_step + self.__final_depth)
else:
return depths
if equalstep:
depths += self.__equal_steps(self.start_depth, depths[-1], self.step_down)[1:]
depths += self.__equal_steps(self.__start_depth, depths[-1], self.__step_down)[1:]
else:
depths += self.__fixed_steps(self.start_depth, depths[-1], self.step_down)[1:]
depths += self.__fixed_steps(self.__start_depth, depths[-1], self.__step_down)[1:]
depths.reverse()
return depths

View File

@@ -41,7 +41,7 @@ class depthTestCases(unittest.TestCase):
expected =[8,6,4,2,1,0]
d = PU.depth_params(clearance_height, rapid_safety_space, start_depth, step_down, z_finish_step, final_depth, user_depths)
r = d.get_depths()
r = [i for i in d]
self.assertListEqual (r, expected)
def test10(self):
@@ -59,7 +59,7 @@ class depthTestCases(unittest.TestCase):
expected =[-2, -4, -6, -8, -10]
d = PU.depth_params(clearance_height, rapid_safety_space, start_depth, step_down, z_finish_step, final_depth, user_depths)
r = d.get_depths()
r = [i for i in d]
self.assertListEqual (r, expected)
def test20(self):
@@ -76,7 +76,7 @@ class depthTestCases(unittest.TestCase):
expected =[10]
d = PU.depth_params(clearance_height, rapid_safety_space, start_depth, step_down, z_finish_step, final_depth, user_depths)
r = d.get_depths()
r = [i for i in d]
self.assertListEqual (r, expected)
start_depth = 10
@@ -85,12 +85,9 @@ class depthTestCases(unittest.TestCase):
expected =[]
d = PU.depth_params(clearance_height, rapid_safety_space, start_depth, step_down, z_finish_step, final_depth, user_depths)
r = d.get_depths()
r = [i for i in d]
self.assertListEqual (r, expected)
def test30(self):
'''User Parameters passed in'''
clearance_height= 10
@@ -105,7 +102,7 @@ class depthTestCases(unittest.TestCase):
expected =[2, 4, 8, 10, 11, 12]
d = PU.depth_params(clearance_height, rapid_safety_space, start_depth, step_down, z_finish_step, final_depth, user_depths)
r = d.get_depths()
r = [i for i in d]
self.assertListEqual (r, expected)
def test40(self):
@@ -122,7 +119,7 @@ class depthTestCases(unittest.TestCase):
expected =[-2, -4, -6, -8, -9, -10]
d = PU.depth_params(clearance_height, rapid_safety_space, start_depth, step_down, z_finish_step, final_depth, user_depths)
r = d.get_depths()
r = [i for i in d]
self.assertListEqual (r, expected)
@@ -139,8 +136,8 @@ class depthTestCases(unittest.TestCase):
expected =[7.5, 5.0, 2.5, 0]
d = PU.depth_params(clearance_height, rapid_safety_space, start_depth, step_down, z_finish_step, final_depth, user_depths)
r = d.get_depths(equalstep=True)
d = PU.depth_params(clearance_height, rapid_safety_space, start_depth, step_down, z_finish_step, final_depth, user_depths, equalstep=True)
r = [i for i in d]
self.assertListEqual (r, expected)
@@ -157,8 +154,8 @@ class depthTestCases(unittest.TestCase):
expected =[7.0, 4.0, 1.0, 0]
d = PU.depth_params(clearance_height, rapid_safety_space, start_depth, step_down, z_finish_step, final_depth, user_depths)
r = d.get_depths(equalstep=True)
d = PU.depth_params(clearance_height, rapid_safety_space, start_depth, step_down, z_finish_step, final_depth, user_depths, equalstep=True)
r = [i for i in d]
self.assertListEqual (r, expected)
def test70(self):
@@ -175,9 +172,7 @@ class depthTestCases(unittest.TestCase):
expected =[1.0, 0]
d = PU.depth_params(clearance_height, rapid_safety_space, start_depth, step_down, z_finish_step, final_depth, user_depths)
r = d.get_depths(equalstep=True)
r = [i for i in d]
self.assertListEqual (r, expected)
d = PU.depth_params(clearance_height, rapid_safety_space, start_depth, step_down, z_finish_step, final_depth, user_depths)
r = d.get_depths()
self.assertListEqual (r, expected)