From d8394df08e1e1e1f234c5c8cc149c265ee2d418f Mon Sep 17 00:00:00 2001 From: Markus Lampert Date: Tue, 26 Jun 2018 21:36:02 -0700 Subject: [PATCH] Extracted and added tests for chamfer tool depth and offset calculations. --- src/Mod/Path/PathScripts/PathChamfer.py | 37 ++++++++------ src/Mod/Path/PathTests/TestPathChamfer.py | 62 +++++++++++++++++++++++ 2 files changed, 84 insertions(+), 15 deletions(-) diff --git a/src/Mod/Path/PathScripts/PathChamfer.py b/src/Mod/Path/PathScripts/PathChamfer.py index ab84fbb975..61c891b366 100644 --- a/src/Mod/Path/PathScripts/PathChamfer.py +++ b/src/Mod/Path/PathScripts/PathChamfer.py @@ -33,7 +33,7 @@ import math from PySide import QtCore -if True: +if False: PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule()) PathLog.trackModule(PathLog.thisModule()) else: @@ -80,6 +80,7 @@ def orientWire(w, forward=True): return wire def isCircleAt(edge, center): + '''isCircleAt(edge, center) ... helper function returns True if edge is a circle at the given center.''' if Circel == type(edge.Curve) or ArcOfCircle == type(edge.Curve): return PathGeom.pointsCoincide(edge.Curve.Center, center) return False @@ -206,6 +207,21 @@ def offsetWire(wire, base, offset, forward): edges = [PathGeom.flipEdge(edge) for edge in rightSideEdges] return Part.Wire(edges) +def toolDepthAndOffset(width, extraDepth, tool): + '''toolDepthAndOffset(width, extraDepth, tool) ... return tuple for given parameters.''' + angle = tool.CuttingEdgeAngle + if 0 == angle: + angle = 180 + tan = math.tan(math.radians(angle/2)) + + toolDepth = 0 if 0 == tan else width / tan + extraDepth = extraDepth + depth = toolDepth + extraDepth + toolOffset = tool.FlatRadius + extraOffset = tool.Diameter/2 - width if 180 == angle else extraDepth / tan + offset = toolOffset + extraOffset + return (depth, offset) + class ObjectChamfer(PathEngraveBase.ObjectOp): '''Proxy class for Chamfer operation.''' @@ -213,23 +229,14 @@ class ObjectChamfer(PathEngraveBase.ObjectOp): return PathOp.FeatureTool | PathOp.FeatureHeights | PathOp.FeatureBaseEdges | PathOp.FeatureBaseFaces def initOperation(self, obj): - obj.addProperty("App::PropertyDistance", "Width", "Chamfer", QtCore.QT_TRANSLATE_NOOP("PathChamfer", "The desired width of the chamfer")) - obj.addProperty("App::PropertyDistance", "ExtraDepth", "Chamfer", QtCore.QT_TRANSLATE_NOOP("PathChamfer", "The additional depth of the tool path")) - obj.addProperty("App::PropertyEnumeration", "Join", "Chamfer", QtCore.QT_TRANSLATE_NOOP("PathChamfer", "How to join chamfer segments")) + obj.addProperty('App::PropertyDistance', 'Width', 'Chamfer', QtCore.QT_TRANSLATE_NOOP('PathChamfer', 'The desired width of the chamfer')) + obj.addProperty('App::PropertyDistance', 'ExtraDepth', 'Chamfer', QtCore.QT_TRANSLATE_NOOP('PathChamfer', 'The additional depth of the tool path')) + obj.addProperty('App::PropertyEnumeration', 'Join', 'Chamfer', QtCore.QT_TRANSLATE_NOOP('PathChamfer', 'How to join chamfer segments')) obj.Join = ['Round', 'Miter'] + obj.setEditorMode('Join', 2) # hide for now def opExecute(self, obj): - angle = self.tool.CuttingEdgeAngle - if 0 == angle: - angle = 180 - tan = math.tan(math.radians(angle/2)) - - toolDepth = 0 if 0 == tan else obj.Width.Value / tan - extraDepth = obj.ExtraDepth.Value - depth = toolDepth + extraDepth - toolOffset = self.tool.FlatRadius - extraOffset = self.tool.Diameter/2 - obj.Width.Value if 180 == angle else obj.ExtraDepth.Value / tan - offset = toolOffset + extraOffset + (depth, offset) = toolDepthAndOffset(obj.Width.Value, obj.ExtraDepth.Value, self.tool) self.basewires = [] self.adjusted_basewires = [] diff --git a/src/Mod/Path/PathTests/TestPathChamfer.py b/src/Mod/Path/PathTests/TestPathChamfer.py index 12e764c94d..f9721996c3 100644 --- a/src/Mod/Path/PathTests/TestPathChamfer.py +++ b/src/Mod/Path/PathTests/TestPathChamfer.py @@ -466,3 +466,65 @@ class TestPathChamfer(PathTestUtils.PathTestBase): self.assertRoughly(radius, e.Curve.Radius) self.assertCoincide(Vector(0, 0, -1), e.Curve.Axis) + + def test50(self): + '''Verify chamfer depth and offset for an end mill.''' + tool = Path.Tool() + tool.Diameter = 20 + tool.FlatRadius = 0 + tool.CuttingEdgeAngle = 180 + + (depth, offset) = PathChamfer.toolDepthAndOffset(1, 0.01, tool) + self.assertRoughly(0.01, depth) + self.assertRoughly(9, offset) + + # legacy tools - no problem, same result + tool.CuttingEdgeAngle = 0 + + (depth, offset) = PathChamfer.toolDepthAndOffset(1, 0.01, tool) + self.assertRoughly(0.01, depth) + self.assertRoughly(9, offset) + + def test51(self): + '''Verify chamfer depth and offset for a 90° v-bit.''' + tool = Path.Tool() + tool.FlatRadius = 0 + tool.CuttingEdgeAngle = 90 + + (depth, offset) = PathChamfer.toolDepthAndOffset(1, 0, tool) + self.assertRoughly(1, depth) + self.assertRoughly(0, offset) + + (depth, offset) = PathChamfer.toolDepthAndOffset(1, 0.2, tool) + self.assertRoughly(1.2, depth) + self.assertRoughly(0.2, offset) + + def test52(self): + '''Verify chamfer depth and offset for a 90° v-bit with non 0 flat radius.''' + tool = Path.Tool() + tool.FlatRadius = 0.3 + tool.CuttingEdgeAngle = 90 + + (depth, offset) = PathChamfer.toolDepthAndOffset(1, 0, tool) + self.assertRoughly(1, depth) + self.assertRoughly(0.3, offset) + + (depth, offset) = PathChamfer.toolDepthAndOffset(2, 0.2, tool) + self.assertRoughly(2.2, depth) + self.assertRoughly(0.5, offset) + + def test53(self): + '''Verify chamfer depth and offset for a 60° v-bit with non 0 flat radius.''' + tool = Path.Tool() + tool.FlatRadius = 10 + tool.CuttingEdgeAngle = 60 + + td = 1.73205 + + (depth, offset) = PathChamfer.toolDepthAndOffset(1, 0, tool) + self.assertRoughly(td, depth) + self.assertRoughly(10, offset) + + (depth, offset) = PathChamfer.toolDepthAndOffset(3, 1, tool) + self.assertRoughly(td * 3 + 1, depth) + self.assertRoughly(10 + td, offset)