Added support for feeds and speeds to to cmdsForEdge.

This commit is contained in:
Markus Lampert
2019-01-23 22:08:45 -08:00
committed by Yorik van Havre
parent dedaa80762
commit af4026bcd5
2 changed files with 93 additions and 2 deletions

View File

@@ -208,7 +208,30 @@ def xy(point):
Convenience function to return the projection of the Vector in the XY-plane."""
return Vector(point.x, point.y, 0)
def cmdsForEdge(edge, flip = False, useHelixForBSpline = True, segm = 50):
def speedBetweenPoints(p0, p1, hSpeed, vSpeed):
if isRoughly(hSpeed, vSpeed):
return hSpeed
d = p1 - p0
if isRoughly(0.0, d.z):
return hSpeed
if isRoughly(0.0, d.x) and isRoughly(0.0, d.y):
return vSpeed
# need to interpolate between hSpeed and vSpeed depending on the pitch
pitch = 2 * math.atan2(xy(d).Length, math.fabs(d.z)) / math.pi
while pitch < 0:
pitch = pitch + 1
while pitch > 1:
pitch = pitch - 1
print(" pitch = %g %g (%.2f, %.2f, %.2f) -> %.2f" % (pitch, math.atan2(xy(d).Length, d.z), d.x, d.y, d.z, xy(d).Length))
speed = vSpeed + pitch * (hSpeed - vSpeed)
if speed > hSpeed and speed > vSpeed:
return max(hSpeed, vSpeed)
if speed < hSpeed and speed < vSpeed:
return min(hSpeed, vSpeed)
return speed
def cmdsForEdge(edge, flip = False, useHelixForBSpline = True, segm = 50, hSpeed = 0, vSpeed = 0):
"""(edge, flip=False, useHelixForBSpline=True, segm=50) -> List(Path.Command)
Returns a list of Path.Command representing the given edge.
If flip is True the edge is considered to be backwards.
@@ -220,6 +243,9 @@ def cmdsForEdge(edge, flip = False, useHelixForBSpline = True, segm = 50):
pt = edge.valueAt(edge.LastParameter) if not flip else edge.valueAt(edge.FirstParameter)
params = {'X': pt.x, 'Y': pt.y, 'Z': pt.z}
if type(edge.Curve) == Part.Line or type(edge.Curve) == Part.LineSegment:
if hSpeed > 0 and vSpeed > 0:
pt2 = edge.valueAt(edge.FirstParameter) if not flip else edge.valueAt(edge.LastParameter)
params.update({'F': speedBetweenPoints(pt, pt2, hSpeed, vSpeed)})
commands = [Path.Command('G1', params)]
else:
p1 = edge.valueAt(edge.FirstParameter) if not flip else edge.valueAt(edge.LastParameter)
@@ -251,6 +277,9 @@ def cmdsForEdge(edge, flip = False, useHelixForBSpline = True, segm = 50):
PathLog.debug("**** (%.2f, %.2f, %.2f)" % (offset.x, offset.y, offset.z))
params.update({'I': offset.x, 'J': offset.y, 'K': (p3.z - p1.z)/2})
# G2/G3 commands are always performed at hSpeed
if hSpeed > 0:
params.update({'F': hSpeed})
commands = [ Path.Command(cmd, params) ]
else:
@@ -266,14 +295,19 @@ def cmdsForEdge(edge, flip = False, useHelixForBSpline = True, segm = 50):
segments = int(math.ceil((deviation / eStraight.Length) * segm))
#print("**** pixellation with %d segments" % segments)
dParameter = (edge.LastParameter - edge.FirstParameter) / segments
# starting point
p0 = edge.valueAt(edge.LastParameter) if flip else edge.valueAt(edge.FirstParameter)
for i in range(0, segments):
if flip:
p = edge.valueAt(edge.LastParameter - (i + 1) * dParameter)
else:
p = edge.valueAt(edge.FirstParameter + (i + 1) * dParameter)
if hSpeed > 0 and vSpeed > 0:
params.update({'F': speedBetweenPoints(p0, p, hSpeed, vSpeed)})
cmd = Path.Command('G1', {'X': p.x, 'Y': p.y, 'Z': p.z})
#print("***** %s" % cmd)
commands.append(cmd)
p0 = p
#print commands
return commands

View File

@@ -181,12 +181,68 @@ class TestPathGeom(PathTestBase):
self.assertFalse(PathGeom.isHorizontal(xzCylinder))
self.assertFalse(PathGeom.isHorizontal(yzCylinder))
def test07(self):
"""Verify speed interpolation works for different pitches"""
# horizontal
self.assertRoughly(100, PathGeom.speedBetweenPoints(Vector(), Vector(1,1,0), 100, 50))
self.assertRoughly(100, PathGeom.speedBetweenPoints(Vector(1,1,0), Vector(), 100, 50))
# vertical
self.assertRoughly( 50, PathGeom.speedBetweenPoints(Vector(), Vector(0,0,1), 100, 50))
self.assertRoughly( 50, PathGeom.speedBetweenPoints(Vector(0,0,1), Vector(), 100, 50))
# 45°
self.assertRoughly( 75, PathGeom.speedBetweenPoints(Vector(), Vector(1,0,1), 100, 50))
self.assertRoughly( 75, PathGeom.speedBetweenPoints(Vector(), Vector(0,1,1), 100, 50))
self.assertRoughly( 75, PathGeom.speedBetweenPoints(Vector(), Vector(0.707,0.707,1), 100, 50), 0.01)
self.assertRoughly( 75, PathGeom.speedBetweenPoints(Vector(1,0,1), Vector(), 100, 50))
self.assertRoughly( 75, PathGeom.speedBetweenPoints(Vector(0,1,1), Vector(), 100, 50))
self.assertRoughly( 75, PathGeom.speedBetweenPoints(Vector(0.707,0.707,1), Vector(), 100, 50), 0.01)
# 30°
self.assertRoughly( 66.66, PathGeom.speedBetweenPoints(Vector(), Vector(0.5774,0,1), 100, 50), 0.01)
self.assertRoughly( 66.66, PathGeom.speedBetweenPoints(Vector(), Vector(0,0.5774,1), 100, 50), 0.01)
self.assertRoughly( 66.66, PathGeom.speedBetweenPoints(Vector(0.5774,0,1), Vector(), 100, 50), 0.01)
self.assertRoughly( 66.66, PathGeom.speedBetweenPoints(Vector(0,0.5774,1), Vector(), 100, 50), 0.01)
# 60°
self.assertRoughly( 83.33, PathGeom.speedBetweenPoints(Vector(), Vector(1,0,0.5774), 100, 50), 0.01)
self.assertRoughly( 83.33, PathGeom.speedBetweenPoints(Vector(), Vector(0,1,0.5774), 100, 50), 0.01)
self.assertRoughly( 83.33, PathGeom.speedBetweenPoints(Vector(1,0,0.5774), Vector(), 100, 50), 0.01)
self.assertRoughly( 83.33, PathGeom.speedBetweenPoints(Vector(0,1,0.5774), Vector(), 100, 50), 0.01)
def test08(self):
"""Verify speed interpolation works for different pitches if vSpeed > hSpeed"""
# horizontal
self.assertRoughly( 50, PathGeom.speedBetweenPoints(Vector(), Vector(1,1,0), 50, 100))
self.assertRoughly( 50, PathGeom.speedBetweenPoints(Vector(1,1,0), Vector(), 50, 100))
# vertical
self.assertRoughly(100, PathGeom.speedBetweenPoints(Vector(), Vector(0,0,1), 50, 100))
self.assertRoughly(100, PathGeom.speedBetweenPoints(Vector(0,0,1), Vector(), 50, 100))
# 45°
self.assertRoughly( 75, PathGeom.speedBetweenPoints(Vector(), Vector(1,0,1), 50, 100))
self.assertRoughly( 75, PathGeom.speedBetweenPoints(Vector(), Vector(0,1,1), 50, 100))
self.assertRoughly( 75, PathGeom.speedBetweenPoints(Vector(), Vector(0.707,0.707,1), 50, 100), 0.01)
self.assertRoughly( 75, PathGeom.speedBetweenPoints(Vector(1,0,1), Vector(), 50, 100))
self.assertRoughly( 75, PathGeom.speedBetweenPoints(Vector(0,1,1), Vector(), 50, 100))
self.assertRoughly( 75, PathGeom.speedBetweenPoints(Vector(0.707,0.707,1), Vector(), 50, 100), 0.01)
# 30°
self.assertRoughly( 83.33, PathGeom.speedBetweenPoints(Vector(), Vector(0.5774,0,1), 50, 100), 0.01)
self.assertRoughly( 83.33, PathGeom.speedBetweenPoints(Vector(), Vector(0,0.5774,1), 50, 100), 0.01)
self.assertRoughly( 83.33, PathGeom.speedBetweenPoints(Vector(0.5774,0,1), Vector(), 50, 100), 0.01)
self.assertRoughly( 83.33, PathGeom.speedBetweenPoints(Vector(0,0.5774,1), Vector(), 50, 100), 0.01)
# 60°
self.assertRoughly( 66.66, PathGeom.speedBetweenPoints(Vector(), Vector(1,0,0.5774), 50, 100), 0.01)
self.assertRoughly( 66.66, PathGeom.speedBetweenPoints(Vector(), Vector(0,1,0.5774), 50, 100), 0.01)
self.assertRoughly( 66.66, PathGeom.speedBetweenPoints(Vector(1,0,0.5774), Vector(), 50, 100), 0.01)
self.assertRoughly( 66.66, PathGeom.speedBetweenPoints(Vector(0,1,0.5774), Vector(), 50, 100), 0.01)
def test10(self):
"""Verify proper geometry objects for G1 and G01 commands are created."""
spt = Vector(1,2,3)
self.assertLine(PathGeom.edgeForCmd(Path.Command('G1', {'X': 7, 'Y': 2, 'Z': 3}), spt), spt, Vector(7, 2, 3))
self.assertLine(PathGeom.edgeForCmd(Path.Command('G01', {'X': 1, 'Y': 3, 'Z': 5}), spt), spt, Vector(1, 3, 5))
def test15(self):
"""Verify proper feed rate for G1 commands is assigned."""
pass
def test20(self):
"""Verify proper geometry for arcs in the XY-plane are created."""
p1 = Vector(0, -1, 2)
@@ -262,7 +318,6 @@ class TestPathGeom(PathTestBase):
self.assertCommandEqual(cmds(center, radius), cmd('G3', Vector(15, 10, 0), Vector(-5, 0, 0)))
def test50(self):
"""Verify proper wire(s) aggregation from a Path."""
commands = []
@@ -448,3 +503,5 @@ class TestPathGeom(PathTestBase):
edge = Part.Edge(Part.BSplineCurve([Vector(-8,4,0), Vector(1,-5,0), Vector(5,11,0), Vector(12,-5,0)], weights=[2,3,5,7]))
self.assertEdgeShapesMatch(edge, PathGeom.flipEdge(edge))