From 95ccfd45056d373d69695d392e446299653b204f Mon Sep 17 00:00:00 2001 From: Markus Lampert Date: Thu, 11 Feb 2021 21:29:52 -0800 Subject: [PATCH] Fixed segmentation for unknown shapes, leaving that to the experts. --- src/Mod/Path/PathScripts/PathGeom.py | 36 +++++++++------------- src/Mod/Path/PathTests/TestPathGeom.py | 42 +++++++++++++++----------- 2 files changed, 39 insertions(+), 39 deletions(-) diff --git a/src/Mod/Path/PathScripts/PathGeom.py b/src/Mod/Path/PathScripts/PathGeom.py index 5c70b63701..fc838ada15 100644 --- a/src/Mod/Path/PathScripts/PathGeom.py +++ b/src/Mod/Path/PathScripts/PathGeom.py @@ -284,29 +284,21 @@ def cmdsForEdge(edge, flip = False, useHelixForBSpline = True, segm = 50, hSpeed else: # We're dealing with a helix or a more complex shape and it has to get approximated # by a number of straight segments - eStraight = Part.Edge(Part.LineSegment(p1, p3)) - esP2 = eStraight.valueAt((eStraight.FirstParameter + eStraight.LastParameter)/2) - deviation = (p2 - esP2).Length - if isRoughly(deviation, 0): - return [ Path.Command('G1', {'X': p3.x, 'Y': p3.y, 'Z': p3.z}) ] - # at this point pixellation is all we can do + points = edge.discretize(Deflection=0.01) + if flip: + points = points[::-1] + commands = [] - 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 + if points: + p0 = points[0] + for p in points[1:]: + params = {'X': p.x, 'Y': p.y, 'Z': p.z} + if hSpeed > 0 and vSpeed > 0: + params['F'] = speedBetweenPoints(p0, p, hSpeed, vSpeed) + cmd = Path.Command('G1', params) + # print("***** {}".format(cmd)) + commands.append(cmd) + p0 = p #print commands return commands diff --git a/src/Mod/Path/PathTests/TestPathGeom.py b/src/Mod/Path/PathTests/TestPathGeom.py index d96d1ba202..0f25764dda 100644 --- a/src/Mod/Path/PathTests/TestPathGeom.py +++ b/src/Mod/Path/PathTests/TestPathGeom.py @@ -29,10 +29,10 @@ from FreeCAD import Vector from PathTests.PathTestUtils import PathTestBase class TestPathGeom(PathTestBase): - """Test Path <-> Wire conversion.""" + '''Test Path <-> Wire conversion.''' def test00(self): - """Verify getAngle functionality.""" + '''Verify getAngle functionality.''' self.assertRoughly(PathGeom.getAngle(Vector(1, 0, 0)), 0) self.assertRoughly(PathGeom.getAngle(Vector(1, 1, 0)), math.pi/4) self.assertRoughly(PathGeom.getAngle(Vector(0, 1, 0)), math.pi/2) @@ -43,7 +43,7 @@ class TestPathGeom(PathTestBase): self.assertRoughly(PathGeom.getAngle(Vector(1, -1, 0)), -math.pi/4) def test01(self): - """Verify diffAngle functionality.""" + '''Verify diffAngle functionality.''' self.assertRoughly(PathGeom.diffAngle(0, +0*math.pi/4, 'CW') / math.pi, 0/4.) self.assertRoughly(PathGeom.diffAngle(0, +3*math.pi/4, 'CW') / math.pi, 5/4.) self.assertRoughly(PathGeom.diffAngle(0, -3*math.pi/4, 'CW') / math.pi, 3/4.) @@ -68,7 +68,7 @@ class TestPathGeom(PathTestBase): self.assertRoughly(PathGeom.diffAngle(-math.pi/4, -1*math.pi/4, 'CCW') / math.pi, 0/4.) def test02(self): - """Verify isVertical/isHorizontal for Vector""" + '''Verify isVertical/isHorizontal for Vector''' self.assertTrue(PathGeom.isVertical(Vector(0, 0, 1))) self.assertTrue(PathGeom.isVertical(Vector(0, 0, -1))) self.assertFalse(PathGeom.isVertical(Vector(1, 0, 1))) @@ -89,7 +89,7 @@ class TestPathGeom(PathTestBase): self.assertFalse(PathGeom.isHorizontal(Vector(0, -1, -1))) def test03(self): - """Verify isVertical/isHorizontal for Edges""" + '''Verify isVertical/isHorizontal for Edges''' # lines self.assertTrue(PathGeom.isVertical(Part.Edge(Part.LineSegment(Vector(-1, -1, -1), Vector(-1, -1, 8))))) @@ -136,7 +136,7 @@ class TestPathGeom(PathTestBase): def test04(self): - """Verify isVertical/isHorizontal for faces""" + '''Verify isVertical/isHorizontal for faces''' # planes xPlane = Part.makePlane(100, 100, Vector(), Vector(1, 0, 0)) @@ -176,7 +176,7 @@ class TestPathGeom(PathTestBase): self.assertFalse(PathGeom.isHorizontal(yzCylinder)) def test07(self): - """Verify speed interpolation works for different pitches""" + '''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)) @@ -202,7 +202,7 @@ class TestPathGeom(PathTestBase): 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""" + '''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)) @@ -228,13 +228,13 @@ class TestPathGeom(PathTestBase): 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.""" + '''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 test20(self): - """Verify proper geometry for arcs in the XY-plane are created.""" + '''Verify proper geometry for arcs in the XY-plane are created.''' p1 = Vector(0, -1, 2) p2 = Vector(-1, 0, 2) self.assertArc( @@ -247,7 +247,7 @@ class TestPathGeom(PathTestBase): p2, p1, 'CCW') def test30(self): - """Verify proper geometry for arcs with rising and fall ing Z-axis are created.""" + '''Verify proper geometry for arcs with rising and fall ing Z-axis are created.''' #print("------ rising helix -------") p1 = Vector(0, 1, 0) p2 = Vector(1, 0, 2) @@ -277,7 +277,7 @@ class TestPathGeom(PathTestBase): p1, Vector(-1/math.sqrt(2), -1/math.sqrt(2), 1), p2) def test40(self): - """Verify arc results in proper G2/3 command.""" + '''Verify arc results in proper G2/3 command.''' p1 = Vector( 0, -10, 0) p2 = Vector(-10, 0, 0) p3 = Vector( 0, +10, 0) @@ -295,7 +295,7 @@ class TestPathGeom(PathTestBase): self.assertCommandEqual(cmds(p1, p4, p3, True), cmd('G2', p1, Vector(0, -10, 0))) def test41(self): - """Verify circle results in proper G2/G3 commands.""" + '''Verify circle results in proper G2/G3 commands.''' def cmds(center, radius, up = True): norm = Vector(0, 0, 1) if up else Vector(0, 0, -1) @@ -308,8 +308,16 @@ class TestPathGeom(PathTestBase): self.assertCommandEqual(cmds(center, radius), cmd('G3', Vector(15, 10, 0), Vector(-5, 0, 0))) + def test42(self): + '''Verify ellipsis results in a proper segmentation of G1 commands.''' + ellipse = Part.Edge(Part.Ellipse()) + cmds = PathGeom.cmdsForEdge(ellipse) + # let's make sure all commands are G1 and there are more than 20 of those + self.assertGreater(len(cmds), 20) + self.assertTrue(all([cmd.Name == 'G1' for cmd in cmds])) + def test50(self): - """Verify proper wire(s) aggregation from a Path.""" + '''Verify proper wire(s) aggregation from a Path.''' commands = [] commands.append(Path.Command('G1', {'X': 1})) commands.append(Path.Command('G1', {'Y': 1})) @@ -335,7 +343,7 @@ class TestPathGeom(PathTestBase): def test60(self): - """Verify arcToHelix returns proper helix.""" + '''Verify arcToHelix returns proper helix.''' p1 = Vector(10,-10,0) p2 = Vector(0,0,0) p3 = Vector(10,10,0) @@ -368,7 +376,7 @@ class TestPathGeom(PathTestBase): def test62(self): - """Verify splitArcAt returns proper subarcs.""" + '''Verify splitArcAt returns proper subarcs.''' p1 = Vector(10,-10,0) p2 = Vector(0,0,0) p3 = Vector(10,10,0) @@ -392,7 +400,7 @@ class TestPathGeom(PathTestBase): def test65(self): - """Verify splitEdgeAt.""" + '''Verify splitEdgeAt.''' # split a line segment e = PathGeom.splitEdgeAt(Part.Edge(Part.LineSegment(Vector(), Vector(2, 4, 6))), Vector(1, 2, 3))