From c955bf4a4e0fd49cd4d4ad7ff52757eeffd8a545 Mon Sep 17 00:00:00 2001 From: Markus Lampert Date: Sat, 12 Dec 2020 20:16:44 -0800 Subject: [PATCH] Fixed v-carve depth calculation in the presence of a bottom diameter, added unit tests and cleaned up the v-bit parameter naming. --- src/Mod/Path/CMakeLists.txt | 1 + src/Mod/Path/PathScripts/PathVcarve.py | 82 +++++++++------- src/Mod/Path/PathTests/TestPathVcarve.py | 114 ++++++++++++++++++++++ src/Mod/Path/TestPathApp.py | 2 + src/Mod/Path/Tools/Bit/60degree_Vbit.fctb | 6 +- src/Mod/Path/Tools/Shape/v-bit.fcstd | Bin 12937 -> 12742 bytes 6 files changed, 167 insertions(+), 38 deletions(-) create mode 100644 src/Mod/Path/PathTests/TestPathVcarve.py diff --git a/src/Mod/Path/CMakeLists.txt b/src/Mod/Path/CMakeLists.txt index b25189233a..db02b58762 100644 --- a/src/Mod/Path/CMakeLists.txt +++ b/src/Mod/Path/CMakeLists.txt @@ -204,6 +204,7 @@ SET(PathTests_SRCS PathTests/TestPathToolController.py PathTests/TestPathTooltable.py PathTests/TestPathUtil.py + PathTests/TestPathVcarve.py PathTests/TestPathVoronoi.py PathTests/boxtest.fcstd PathTests/test_centroid_00.ngc diff --git a/src/Mod/Path/PathScripts/PathVcarve.py b/src/Mod/Path/PathScripts/PathVcarve.py index 00e812392f..472c61fc4f 100644 --- a/src/Mod/Path/PathScripts/PathVcarve.py +++ b/src/Mod/Path/PathScripts/PathVcarve.py @@ -157,6 +157,45 @@ def _sortVoronoiWires(wires, start=FreeCAD.Vector(0, 0, 0)): return result +class _Geometry(object): + '''POD class so the limits only have to be calculated once.''' + + def __init__(self, zStart, zStop, zScale): + self.start = zStart + self.stop = zStop + self.scale = zScale + + @classmethod + def FromTool(cls, tool, zStart, zFinal): + rMax = float(tool.Diameter) / 2.0 + rMin = float(tool.TipDiameter) / 2.0 + toolangle = math.tan(math.radians(tool.CuttingEdgeAngle.Value / 2.0)) + zScale = 1.0 / toolangle + zStop = zStart - rMax * zScale + zOff = rMin * zScale + + return _Geometry(zStart + zOff, max(zStop + zOff, zFinal), zScale) + + @classmethod + def FromObj(cls, obj, model): + zStart = model.Shape.BoundBox.ZMax + finalDepth = obj.FinalDepth.Value + + return cls.FromTool(obj.ToolController.Tool, zStart, finalDepth) + +def _calculate_depth(MIC, geom): + # given a maximum inscribed circle (MIC) and tool angle, + # return depth of cut relative to zStart. + depth = geom.start - round(MIC / geom.scale, 4) + PathLog.debug('zStart value: {} depth: {}'.format(geom.start, depth)) + + return max(depth, geom.stop) + +def _getPartEdge(edge, depths): + dist = edge.getDistances() + zBegin = _calculate_depth(dist[0], depths) + zEnd = _calculate_depth(dist[1], depths) + return edge.toShape(zBegin, zEnd) class ObjectVcarve(PathEngraveBase.ObjectOp): '''Proxy class for Vcarve operation.''' @@ -197,42 +236,10 @@ class ObjectVcarve(PathEngraveBase.ObjectOp): # upgrade ... self.setupAdditionalProperties(obj) - def _calculate_depth(self, MIC, zStart, zStop, zScale, finaldepth): - # given a maximum inscribed circle (MIC) and tool angle, - # return depth of cut relative to zStart. - depth = zStart - round(MIC / zScale, 4) - PathLog.debug('zStart value: {} depth: {}'.format(zStart, depth)) - - # Never go below the operation final depth. - zStop = zStop if zStop > finaldepth else finaldepth - - return depth if depth > zStop else zStop - - def _getPartEdge(self, edge, zStart, zStop, zScale, finaldepth): - dist = edge.getDistances() - return edge.toShape(self._calculate_depth(dist[0], - zStart, - zStop, - zScale, - finaldepth), - self._calculate_depth(dist[1], - zStart, - zStop, - zScale, - finaldepth)) - - def _getPartEdges(self, obj, vWire): - # pre-calculate the depth limits - pre-mature optimisation ;) - r = float(obj.ToolController.Tool.Diameter) / 2 - toolangle = obj.ToolController.Tool.CuttingEdgeAngle - zStart = self.model[0].Shape.BoundBox.ZMin - zStop = zStart - r / math.tan(math.radians(toolangle/2)) - zScale = 1.0 / math.tan(math.radians(toolangle / 2)) - finaldepth = obj.FinalDepth.Value - + def _getPartEdges(self, obj, vWire, geom): edges = [] for e in vWire: - edges.append(self._getPartEdge(e, zStart, zStop, zScale, finaldepth)) + edges.append(_getPartEdge(e, geom)) return edges def buildPathMedial(self, obj, Faces): @@ -290,10 +297,12 @@ class ObjectVcarve(PathEngraveBase.ObjectOp): if _sorting == 'global': voronoiWires = _sortVoronoiWires(voronoiWires) + geom = _Geometry.FromObj(obj, self.model[0]) + pathlist = [] pathlist.append(Path.Command("(starting)")) for w in voronoiWires: - pWire = self._getPartEdges(obj, w) + pWire = self._getPartEdges(obj, w, geom) if pWire: wires.append(pWire) pathlist.extend(cutWire(pWire)) @@ -355,6 +364,9 @@ operation will produce no output.')) else: obj.OpFinalDepth = -0.1 + def isToolSupported(self, obj, tool): + '''isToolSupported(obj, tool) ... returns True if v-carve op can work with tool.''' + return hasattr(tool, 'Diameter') and hasattr(tool, 'CuttingEdgeAngle') and hasattr(tool, 'TipDiameter') def SetupProperties(): return ["Discretize"] diff --git a/src/Mod/Path/PathTests/TestPathVcarve.py b/src/Mod/Path/PathTests/TestPathVcarve.py new file mode 100644 index 0000000000..686cc4ddff --- /dev/null +++ b/src/Mod/Path/PathTests/TestPathVcarve.py @@ -0,0 +1,114 @@ +# -*- coding: utf-8 -*- + +# *************************************************************************** +# * * +# * Copyright (c) 2020 sliptonic * +# * * +# * This program is free software; you can redistribute it and/or modify * +# * it under the terms of the GNU Lesser General Public License (LGPL) * +# * as published by the Free Software Foundation; either version 2 of * +# * the License, or (at your option) any later version. * +# * for detail see the LICENCE text file. * +# * * +# * This program is distributed in the hope that it will be useful, * +# * but WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +# * GNU Library General Public License for more details. * +# * * +# * You should have received a copy of the GNU Library General Public * +# * License along with this program; if not, write to the Free Software * +# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +# * USA * +# * * +# *************************************************************************** + +import FreeCAD +import PathScripts.PathGeom as PathGeom +import PathScripts.PathToolBit as PathToolBit +import PathScripts.PathVcarve as PathVcarve +import math + +from PathTests.PathTestUtils import PathTestBase + +class VbitTool(object): + '''Faked out vcarve tool''' + + def __init__(self, dia, angle, tipDia): + self.Diameter = FreeCAD.Units.Quantity(dia, FreeCAD.Units.Length) + self.CuttingEdgeAngle = FreeCAD.Units.Quantity(angle, FreeCAD.Units.Angle) + self.TipDiameter = FreeCAD.Units.Quantity(tipDia, FreeCAD.Units.Length) + +Scale45 = 2.414214 +Scale60 = math.sqrt(3) + +class TestPathVcarve(PathTestBase): + '''Test Vcarve milling basics.''' + + def test00(self): + '''Verify 90 deg depth calculation''' + tool = VbitTool(10, 90, 0) + geom = PathVcarve._Geometry.FromTool(tool, 0, -10) + self.assertRoughly(geom.start, 0) + self.assertRoughly(geom.stop, -5) + self.assertRoughly(geom.scale, 1) + + def test01(self): + '''Verify 90 deg depth limit''' + tool = VbitTool(10, 90, 0) + geom = PathVcarve._Geometry.FromTool(tool, 0, -3) + self.assertRoughly(geom.start, 0) + self.assertRoughly(geom.stop, -3) + self.assertRoughly(geom.scale, 1) + + def test02(self): + '''Verify 60 deg depth calculation''' + tool = VbitTool(10, 60, 0) + geom = PathVcarve._Geometry.FromTool(tool, 0, -10) + self.assertRoughly(geom.start, 0) + self.assertRoughly(geom.stop, -5 * Scale60) + self.assertRoughly(geom.scale, Scale60) + + def test03(self): + '''Verify 60 deg depth limit''' + tool = VbitTool(10, 60, 0) + geom = PathVcarve._Geometry.FromTool(tool, 0, -3) + self.assertRoughly(geom.start, 0) + self.assertRoughly(geom.stop, -3) + self.assertRoughly(geom.scale, Scale60) + + def test10(self): + '''Verify 90 deg with tip dia depth calculation''' + tool = VbitTool(10, 90, 2) + geom = PathVcarve._Geometry.FromTool(tool, 0, -10) + # in order for the width to be correct the height needs to be shifted + self.assertRoughly(geom.start, 1) + self.assertRoughly(geom.stop, -4) + self.assertRoughly(geom.scale, 1) + + def test11(self): + '''Verify 90 deg with tip dia depth limit calculation''' + tool = VbitTool(10, 90, 2) + geom = PathVcarve._Geometry.FromTool(tool, 0, -3) + # in order for the width to be correct the height needs to be shifted + self.assertRoughly(geom.start, 1) + self.assertRoughly(geom.stop, -3) + self.assertRoughly(geom.scale, 1) + + def test12(self): + '''Verify 45 deg with tip dia depth calculation''' + tool = VbitTool(10, 45, 2) + geom = PathVcarve._Geometry.FromTool(tool, 0, -10) + # in order for the width to be correct the height needs to be shifted + self.assertRoughly(geom.start, Scale45) + self.assertRoughly(geom.stop, -4 * Scale45) + self.assertRoughly(geom.scale, Scale45) + + def test13(self): + '''Verify 45 deg with tip dia depth limit calculation''' + tool = VbitTool(10, 45, 2) + geom = PathVcarve._Geometry.FromTool(tool, 0, -3) + # in order for the width to be correct the height needs to be shifted + self.assertRoughly(geom.start, Scale45) + self.assertRoughly(geom.stop, -3) + self.assertRoughly(geom.scale, Scale45) + diff --git a/src/Mod/Path/TestPathApp.py b/src/Mod/Path/TestPathApp.py index 623bf180ee..0adebedfc6 100644 --- a/src/Mod/Path/TestPathApp.py +++ b/src/Mod/Path/TestPathApp.py @@ -42,6 +42,7 @@ from PathTests.TestPathDeburr import TestPathDeburr from PathTests.TestPathHelix import TestPathHelix from PathTests.TestPathVoronoi import TestPathVoronoi from PathTests.TestPathThreadMilling import TestPathThreadMilling +from PathTests.TestPathVcarve import TestPathVcarve # dummy usage to get flake8 and lgtm quiet False if TestApp.__name__ else True @@ -64,4 +65,5 @@ False if TestPathPreferences.__name__ else True False if TestPathToolBit.__name__ else True False if TestPathVoronoi.__name__ else True False if TestPathThreadMilling.__name__ else True +False if TestPathVcarve.__name__ else True diff --git a/src/Mod/Path/Tools/Bit/60degree_Vbit.fctb b/src/Mod/Path/Tools/Bit/60degree_Vbit.fctb index 715361ec34..69d181d4a3 100644 --- a/src/Mod/Path/Tools/Bit/60degree_Vbit.fctb +++ b/src/Mod/Path/Tools/Bit/60degree_Vbit.fctb @@ -5,10 +5,10 @@ "parameter": { "CuttingEdgeAngle": "60.0000 \u00b0", "Diameter": "10.0000 mm", - "FlatHeight": "1.0000 mm", - "FlatRadius": "0.5000 mm", + "CuttingEdgeHeight": "1.0000 mm", + "TipDiameter": "1.0000 mm", "Length": "20.0000 mm", "ShankDiameter": "5.0000 mm" }, "attribute": {} -} \ No newline at end of file +} diff --git a/src/Mod/Path/Tools/Shape/v-bit.fcstd b/src/Mod/Path/Tools/Shape/v-bit.fcstd index 5d35188c81f7991a0ab7e982bf553938d9d5cf42..d2711ad0af2fcc34d6d883427c111b560e5bee74 100644 GIT binary patch delta 11198 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 YHgcS~KR(bwk}l@vVj|+C|1Qb>e-Hp_VgLXD delta 11403 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