freecad-cam/Mod/CAM/CAMTests/TestPathDressupDogboneII.py
2026-02-01 01:59:24 +01:00

643 lines
26 KiB
Python

# -*- coding: utf-8 -*-
# ***************************************************************************
# * Copyright (c) 2022 sliptonic <shopinthewoods@gmail.com> *
# * *
# * 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 Path
import Path.Base.Generator.dogboneII as dogboneII
import Path.Base.Language as PathLanguage
import Path.Dressup.DogboneII
import CAMTests.PathTestUtils as PathTestUtils
import math
PI = math.pi
class MockTB(object):
def __init__(self, dia):
self.Name = "ToolBit"
self.Label = "ToolBit"
self.Diameter = FreeCAD.Units.Quantity(dia, FreeCAD.Units.Length)
class MockTC(object):
def __init__(self, dia=2):
self.Name = "TC"
self.Label = "TC"
self.Tool = MockTB(dia)
class MockOp(object):
def __init__(self, path, dia=2):
self.Name = "OP"
self.Label = "OP"
self.Path = Path.Path(path)
self.ToolController = MockTC(dia)
class MockFeaturePython(object):
def __init__(self, name):
self.prop = {}
self.addProperty("App::PropertyString", "Name", val=name)
self.addProperty("App::PropertyString", "Label", val=name)
self.addProperty("App::PropertyLink", "Proxy")
self.addProperty("Path::Path", "Path", val=Path.Path())
def addProperty(self, typ, name, grp=None, desc=None, val=None):
self.prop[name] = (typ, val)
def setEditorMode(self, name, mode):
pass
def __setattr__(self, name, val):
if name == "prop":
return super().__setattr__(name, val)
self.prop[name] = (self.prop[name][0], val)
def __getattr__(self, name):
if name == "prop":
return super().__getattr__(name)
typ, val = self.prop.get(name, (None, None))
if typ is None and val is None:
raise AttributeError
if typ == "App::PropertyLength":
if type(val) == float or type(val) == int:
return FreeCAD.Units.Quantity(val, FreeCAD.Units.Length)
return FreeCAD.Units.Quantity(val)
return val
def CreateDressup(path):
op = MockOp(path)
obj = MockFeaturePython("DressupDogbone")
db = Path.Dressup.DogboneII.Proxy(obj, op)
obj.Proxy = db
return obj
def MNVR(gcode, begin=None):
# 'turns out the replace() isn't really necessary
# leave it here anyway for clarity
return PathLanguage.Maneuver.FromGCode(gcode.replace("/", "\n"), begin)
def INSTR(gcode, begin=None):
return MNVR(gcode, begin).instr[0]
def KINK(gcode, begin=None):
maneuver = MNVR(gcode, begin)
if len(maneuver.instr) != 2:
return None
return dogboneII.Kink(maneuver.instr[0], maneuver.instr[1])
class TestDressupDogboneII(PathTestUtils.PathTestBase):
"""Unit tests for the DogboneII dressup."""
def assertEqualPath(self, path, s):
def cmd2str(cmd):
param = [
f"{k}{v:g}" if Path.Geom.isRoughly(0, v - int(v)) else f"{k}{v:.2f}"
for k, v in cmd.Parameters.items()
]
return f"{cmd.Name}{''.join(param)}"
p = "/".join([cmd2str(cmd) for cmd in path.Commands])
self.assertEqual(p, s)
def test00(self):
"""Verify adaptive length"""
def adaptive(k, a, n):
return Path.Dressup.DogboneII.calc_length_adaptive(k, a, n, n)
if True:
# horizontal bones
self.assertRoughly(adaptive(KINK("G1X1/G1X2"), 0, 1), 0)
self.assertRoughly(adaptive(KINK("G1X1/G1Y1"), 0, 1), 1)
self.assertRoughly(adaptive(KINK("G1X1/G1X2Y1"), 0, 1), 0.414214)
self.assertRoughly(adaptive(KINK("G1X1/G1X0Y1"), 0, 1), 2.414211)
self.assertRoughly(adaptive(KINK("G1X1/G1X0"), 0, 1), 1)
self.assertRoughly(adaptive(KINK("G1X1/G1X0Y-1"), 0, 1), 2.414211)
self.assertRoughly(adaptive(KINK("G1X1/G1X1Y-1"), 0, 1), 1)
self.assertRoughly(adaptive(KINK("G1X1/G1X2Y-1"), 0, 1), 0.414214)
self.assertRoughly(adaptive(KINK("G1X1Y1/G1X0Y2"), 0, 1), 0.414214)
if True:
# more horizontal and some vertical bones
self.assertRoughly(adaptive(KINK("G1Y1/G1Y2"), 0, 1), 0)
self.assertRoughly(adaptive(KINK("G1Y1/G1Y1X1"), PI, 1), 1)
self.assertRoughly(adaptive(KINK("G1Y1/G1Y2X1"), PI, 1), 0.089820)
self.assertRoughly(adaptive(KINK("G1Y1/G1Y2X1"), PI / 2, 1), 0.414214)
self.assertRoughly(adaptive(KINK("G1Y1/G1Y0X1"), PI / 2, 1), 2.414211)
self.assertRoughly(adaptive(KINK("G1Y1/G1Y0"), 0, 1), 1)
self.assertRoughly(adaptive(KINK("G1Y1/G1Y0X-1"), PI / 2, 1), 2.414211)
self.assertRoughly(adaptive(KINK("G1Y1/G1Y1X-1"), 0, 1), 1)
self.assertRoughly(adaptive(KINK("G1Y1/G1Y2X-1"), 0, 1), 0.089820)
self.assertRoughly(adaptive(KINK("G1Y1/G1Y2X-1"), PI / 2, 1), 0.414214)
if True:
# dogbones
self.assertRoughly(adaptive(KINK("G1X1/G1Y1"), -PI / 4, 1), 0.414214)
self.assertRoughly(adaptive(KINK("G1X1/G1X0Y1"), -PI / 8, 1), 1.613126)
self.assertRoughly(adaptive(KINK("G1X1/G1Y-1"), PI / 4, 1), 0.414214)
self.assertRoughly(adaptive(KINK("G1X1/G1X0Y-1"), PI / 8, 1), 1.613126)
self.assertRoughly(adaptive(KINK("G1Y1/G1X-1"), PI / 4, 1), 0.414214)
self.assertRoughly(adaptive(KINK("G1Y1/G1X1"), 3 * PI / 4, 1), 0.414214)
self.assertRoughly(adaptive(KINK("G1Y-1/G1X1"), -3 * PI / 4, 1), 0.414214)
self.assertRoughly(adaptive(KINK("G1Y-1/G1X-1"), -PI / 4, 1), 0.414214)
self.assertRoughly(adaptive(KINK("G1X1Y1/G1X0Y2"), 0, 1), 0.414214)
self.assertRoughly(adaptive(KINK("G1X-1Y1/G1X0Y2"), PI, 1), 0.414214)
self.assertRoughly(adaptive(KINK("G1X1Y1/G1X2Y0"), PI / 2, 2), 0.828428)
self.assertRoughly(adaptive(KINK("G1X-1Y-1/G1X-2Y0"), -PI / 2, 2), 0.828428)
self.assertRoughly(adaptive(KINK("G1X-1Y1/G1X-2Y0"), PI / 2, 2), 0.828428)
self.assertRoughly(adaptive(KINK("G1X1Y-1/G1X2Y0"), -PI / 2, 2), 0.828428)
def test01(self):
"""Verify nominal length"""
def nominal(k, a, n):
return Path.Dressup.DogboneII.calc_length_nominal(k, a, n, 0)
# neither angle nor kink matter
self.assertRoughly(nominal(KINK("G1X1/G1X2"), 0, 13), 13)
self.assertRoughly(nominal(KINK("G1X1/G1X2"), PI / 2, 13), 13)
self.assertRoughly(nominal(KINK("G1X1/G1X2"), PI, 13), 13)
self.assertRoughly(nominal(KINK("G1X1/G1X2"), -PI / 2, 13), 13)
self.assertRoughly(nominal(KINK("G1X8/G1X12"), 0, 13), 13)
self.assertRoughly(nominal(KINK("G1X9/G1X0"), 0, 13), 13)
self.assertRoughly(nominal(KINK("G1X7/G1X9"), 0, 13), 13)
self.assertRoughly(nominal(KINK("G1X5/G1X1"), 0, 13), 13)
def test02(self):
"""Verify custom length"""
def custom(k, a, c):
return Path.Dressup.DogboneII.calc_length_custom(k, a, 0, c)
# neither angle nor kink matter
self.assertRoughly(custom(KINK("G1X1/G1X2"), 0, 7), 7)
self.assertRoughly(custom(KINK("G1X1/G1X2"), PI / 2, 7), 7)
self.assertRoughly(custom(KINK("G1X1/G1X2"), PI, 7), 7)
self.assertRoughly(custom(KINK("G1X1/G1X2"), -PI / 2, 7), 7)
self.assertRoughly(custom(KINK("G1X8/G1X12"), 0, 7), 7)
self.assertRoughly(custom(KINK("G1X9/G1X0"), 0, 7), 7)
self.assertRoughly(custom(KINK("G1X7/G1X9"), 0, 7), 7)
self.assertRoughly(custom(KINK("G1X5/G1X1"), 0, 7), 7)
def test10(self):
"""Verify basic op dressup"""
obj = CreateDressup("G1X10/G1Y20")
obj.Incision = Path.Dressup.DogboneII.Incision.Fixed
obj.Style = Path.Dressup.DogboneII.Style.Tbone_H
# bones on right side
obj.Side = Path.Dressup.DogboneII.Side.Right
obj.Proxy.execute(obj)
self.assertEqualPath(obj.Path, "G1X10/G1X11/G1X10/G1Y20")
# no bones on left side
obj.Side = Path.Dressup.DogboneII.Side.Left
obj.Proxy.execute(obj)
self.assertEqualPath(obj.Path, "G1X10/G1Y20")
def test11(self):
"""Verify retaining non-move instructions"""
obj = CreateDressup("G1X10/(some comment)/G1Y20")
obj.Incision = Path.Dressup.DogboneII.Incision.Fixed
obj.Style = Path.Dressup.DogboneII.Style.Tbone_H
# bone on right side
obj.Side = Path.Dressup.DogboneII.Side.Right
obj.Proxy.execute(obj)
self.assertEqualPath(obj.Path, "G1X10/(some comment)/G1X11/G1X10/G1Y20")
# no bone on left side
obj.Side = Path.Dressup.DogboneII.Side.Left
obj.Proxy.execute(obj)
self.assertEqualPath(obj.Path, "G1X10/(some comment)/G1Y20")
def test20(self):
"""Verify bone on plunge moves"""
obj = CreateDressup("G0Z10/G1Z0/G1X10/G1Y10/G1X0/G1Y0/G0Z10")
obj.Incision = Path.Dressup.DogboneII.Incision.Fixed
obj.Style = Path.Dressup.DogboneII.Style.Tbone_H
obj.Side = Path.Dressup.DogboneII.Side.Right
obj.Proxy.execute(obj)
self.assertEqualPath(
obj.Path,
"G0Z10/G1Z0/G1X10/G1X11/G1X10/G1Y10/G1X11/G1X10/G1X0/G1X-1/G1X0/G1Y0/G1X-1/G1X0/G0Z10",
)
def test21(self):
"""Verify ignoring plunge moves that don't connect"""
obj = CreateDressup("G0Z10/G1Z0/G1X10/G1Y10/G1X0/G1Y5/G0Z10")
obj.Incision = Path.Dressup.DogboneII.Incision.Fixed
obj.Style = Path.Dressup.DogboneII.Style.Tbone_H
obj.Side = Path.Dressup.DogboneII.Side.Right
obj.Proxy.execute(obj)
self.assertEqualPath(
obj.Path,
"G0Z10/G1Z0/G1X10/G1X11/G1X10/G1Y10/G1X11/G1X10/G1X0/G1X-1/G1X0/G1Y5/G0Z10",
)
def test30(self):
"""Verify TBone_V style"""
def check_tbone(d, i, path, out, right):
obj = CreateDressup(f"({d}.{i:02})/{path}")
obj.Incision = Path.Dressup.DogboneII.Incision.Fixed
if right:
obj.Side = Path.Dressup.DogboneII.Side.Right
else:
obj.Side = Path.Dressup.DogboneII.Side.Left
obj.Style = Path.Dressup.DogboneII.Style.Tbone_V
obj.Proxy.execute(obj)
self.assertEqualPath(obj.Path, f"({d}.{i:02})/{out}")
# test data with a horizontal lead in
test_data_h = [
# top right quadrant
("G1X10Y0/G1X10Y10", "G1X10Y0/G1Y-1/G1Y0/G1X10Y10", True),
("G1X10Y0/G1X20Y10", "G1X10Y0/G1Y-1/G1Y0/G1X20Y10", True),
("G1X10Y0/G1X90Y10", "G1X10Y0/G1Y-1/G1Y0/G1X90Y10", True),
("G1X10Y0/G1X0Y10", "G1X10Y0/G1Y-1/G1Y0/G1X0Y10", True),
# bottom right quadrant
("G1X10Y0/G1X90Y-10", "G1X10Y0/G1Y1/G1Y0/G1X90Y-10", False),
("G1X10Y0/G1X20Y-10", "G1X10Y0/G1Y1/G1Y0/G1X20Y-10", False),
("G1X10Y0/G1X10Y-10", "G1X10Y0/G1Y1/G1Y0/G1X10Y-10", False),
("G1X10Y0/G1X0Y-10", "G1X10Y0/G1Y1/G1Y0/G1X0Y-10", False),
# top left quadrant
("G1X-10Y0/G1X-10Y10", "G1X-10Y0/G1Y-1/G1Y0/G1X-10Y10", False),
("G1X-10Y0/G1X-20Y10", "G1X-10Y0/G1Y-1/G1Y0/G1X-20Y10", False),
("G1X-10Y0/G1X-90Y10", "G1X-10Y0/G1Y-1/G1Y0/G1X-90Y10", False),
("G1X-10Y0/G1X-0Y10", "G1X-10Y0/G1Y-1/G1Y0/G1X-0Y10", False),
# bottom left quadrant
("G1X-10Y0/G1X-90Y-10", "G1X-10Y0/G1Y1/G1Y0/G1X-90Y-10", True),
("G1X-10Y0/G1X-20Y-10", "G1X-10Y0/G1Y1/G1Y0/G1X-20Y-10", True),
("G1X-10Y0/G1X-10Y-10", "G1X-10Y0/G1Y1/G1Y0/G1X-10Y-10", True),
("G1X-10Y0/G1X-0Y-10", "G1X-10Y0/G1Y1/G1Y0/G1X-0Y-10", True),
]
for i, (path, out, right) in enumerate(test_data_h):
check_tbone("h", i, path, out, right)
# test data with a vertical lead in
test_data_v = [
# top right quadrant
("G1X0Y10/G1X10Y10", "G1X0Y10/G1Y11/G1Y10/G1X10Y10", False),
("G1X0Y10/G1X10Y20", "G1X0Y10/G1Y11/G1Y10/G1X10Y20", False),
("G1X0Y10/G1X10Y90", "G1X0Y10/G1Y11/G1Y10/G1X10Y90", False),
("G1X0Y10/G1X10Y0", "G1X0Y10/G1Y11/G1Y10/G1X10Y0", False),
# bottom right quadrant
("G1X0Y-10/G1X10Y-90", "G1X0Y-10/G1Y-11/G1Y-10/G1X10Y-90", True),
("G1X0Y-10/G1X10Y-20", "G1X0Y-10/G1Y-11/G1Y-10/G1X10Y-20", True),
("G1X0Y-10/G1X10Y-10", "G1X0Y-10/G1Y-11/G1Y-10/G1X10Y-10", True),
("G1X0Y-10/G1X10Y-0", "G1X0Y-10/G1Y-11/G1Y-10/G1X10Y-0", True),
# top left quadrant
("G1X0Y10/G1X-10Y10", "G1X0Y10/G1Y11/G1Y10/G1X-10Y10", True),
("G1X0Y10/G1X-10Y20", "G1X0Y10/G1Y11/G1Y10/G1X-10Y20", True),
("G1X0Y10/G1X-10Y90", "G1X0Y10/G1Y11/G1Y10/G1X-10Y90", True),
("G1X0Y10/G1X-10Y0", "G1X0Y10/G1Y11/G1Y10/G1X-10Y0", True),
# bottom left quadrant
("G1X0Y-10/G1X-10Y-90", "G1X0Y-10/G1Y-11/G1Y-10/G1X-10Y-90", False),
("G1X0Y-10/G1X-10Y-20", "G1X0Y-10/G1Y-11/G1Y-10/G1X-10Y-20", False),
("G1X0Y-10/G1X-10Y-10", "G1X0Y-10/G1Y-11/G1Y-10/G1X-10Y-10", False),
("G1X0Y-10/G1X-10Y-0", "G1X0Y-10/G1Y-11/G1Y-10/G1X-10Y-0", False),
]
for i, (path, out, right) in enumerate(test_data_v):
check_tbone("v", i, path, out, right)
def test40(self):
"""Verify TBone_S style"""
def check_tbone_s(d, i, path, out, right):
obj = CreateDressup(f"(m{d}.{i:02})/{path}")
obj.Incision = Path.Dressup.DogboneII.Incision.Fixed
if right:
obj.Side = Path.Dressup.DogboneII.Side.Right
else:
obj.Side = Path.Dressup.DogboneII.Side.Left
obj.Style = Path.Dressup.DogboneII.Style.Tbone_S
obj.Proxy.execute(obj)
self.assertEqualPath(obj.Path, f"(m{d}.{i:02})/{out}")
# short edge m0
test_data_0 = [
# CCW
("G1X10/G1Y20", "G1X10/G1Y-1/G1Y0/G1Y20", True),
("G1X10Y10/G1X-10Y30", "G1X10Y10/G1X10.71Y9.29/G1X10Y10/G1X-10Y30", True),
("G1Y10/G1X-20", "G1Y10/G1X1/G1X0/G1X-20", True),
(
"G1X-10Y10/G1X-30Y-10",
"G1X-10Y10/G1X-9.29Y10.71/G1X-10Y10/G1X-30Y-10",
True,
),
("G1X-10/G1Y-20", "G1X-10/G1Y1/G1Y0/G1Y-20", True),
(
"G1X-10Y-10/G1X10Y-30",
"G1X-10Y-10/G1X-10.71Y-9.29/G1X-10Y-10/G1X10Y-30",
True,
),
("G1Y-10/G1X20", "G1Y-10/G1X-1/G1X0/G1X20", True),
("G1X10Y-10/G1X30Y10", "G1X10Y-10/G1X9.29Y-10.71/G1X10Y-10/G1X30Y10", True),
# CW
("G1X10/G1Y-20", "G1X10/G1Y1/G1Y0/G1Y-20", False),
("G1X10Y10/G1X30Y-10", "G1X10Y10/G1X9.29Y10.71/G1X10Y10/G1X30Y-10", False),
("G1Y10/G1X20", "G1Y10/G1X-1/G1X0/G1X20", False),
(
"G1X-10Y10/G1X10Y30",
"G1X-10Y10/G1X-10.71Y9.29/G1X-10Y10/G1X10Y30",
False,
),
("G1X-10/G1Y20", "G1X-10/G1Y-1/G1Y0/G1Y20", False),
(
"G1X-10Y-10/G1X-30Y10",
"G1X-10Y-10/G1X-9.29Y-10.71/G1X-10Y-10/G1X-30Y10",
False,
),
("G1Y-10/G1X-20", "G1Y-10/G1X1/G1X0/G1X-20", False),
(
"G1X10Y-10/G1X-10Y-30",
"G1X10Y-10/G1X10.71Y-9.29/G1X10Y-10/G1X-10Y-30",
False,
),
]
for i, (path, out, right) in enumerate(test_data_0):
check_tbone_s("0", i, path, out, right)
# short edge m1
test_data_1 = [
# CCW
("G1X20/G1Y10", "G1X20/G1X21/G1X20/G1Y10", True),
("G1X20Y20/G1X10Y30", "G1X20Y20/G1X20.71Y20.71/G1X20Y20/G1X10Y30", True),
("G1Y20/G1X-10", "G1Y20/G1Y21/G1Y20/G1X-10", True),
(
"G1X-20Y20/G1X-30Y10",
"G1X-20Y20/G1X-20.71Y20.71/G1X-20Y20/G1X-30Y10",
True,
),
("G1X-20/G1Y-10", "G1X-20/G1X-21/G1X-20/G1Y-10", True),
(
"G1X-20Y-20/G1X-10Y-30",
"G1X-20Y-20/G1X-20.71Y-20.71/G1X-20Y-20/G1X-10Y-30",
True,
),
("G1Y-20/G1X10", "G1Y-20/G1Y-21/G1Y-20/G1X10", True),
(
"G1X20Y-20/G1X30Y-10",
"G1X20Y-20/G1X20.71Y-20.71/G1X20Y-20/G1X30Y-10",
True,
),
# CW
("G1X20/G1Y-10", "G1X20/G1X21/G1X20/G1Y-10", False),
("G1X20Y20/G1X30Y10", "G1X20Y20/G1X20.71Y20.71/G1X20Y20/G1X30Y10", False),
("G1Y20/G1X10", "G1Y20/G1Y21/G1Y20/G1X10", False),
(
"G1X-20Y20/G1X-10Y30",
"G1X-20Y20/G1X-20.71Y20.71/G1X-20Y20/G1X-10Y30",
False,
),
("G1X-20/G1Y10", "G1X-20/G1X-21/G1X-20/G1Y10", False),
(
"G1X-20Y-20/G1X-30Y-10",
"G1X-20Y-20/G1X-20.71Y-20.71/G1X-20Y-20/G1X-30Y-10",
False,
),
("G1Y-20/G1X-10", "G1Y-20/G1Y-21/G1Y-20/G1X-10", False),
(
"G1X20Y-20/G1X10Y-30",
"G1X20Y-20/G1X20.71Y-20.71/G1X20Y-20/G1X10Y-30",
False,
),
]
for i, (path, out, right) in enumerate(test_data_1):
check_tbone_s("1", i, path, out, right)
def test50(self):
"""Verify TBone_L style"""
def check_tbone_l(d, i, path, out, right):
obj = CreateDressup(f"(m{d}.{i:02})/{path}")
obj.Incision = Path.Dressup.DogboneII.Incision.Fixed
if right:
obj.Side = Path.Dressup.DogboneII.Side.Right
else:
obj.Side = Path.Dressup.DogboneII.Side.Left
obj.Style = Path.Dressup.DogboneII.Style.Tbone_L
obj.Proxy.execute(obj)
self.assertEqualPath(obj.Path, f"(m{d}.{i:02})/{out}")
# long edge m1
test_data_1 = [
# CCW
("G1X10/G1Y20", "G1X10/G1X11/G1X10/G1Y20", True),
("G1X10Y10/G1X-10Y30", "G1X10Y10/G1X10.71Y10.71/G1X10Y10/G1X-10Y30", True),
("G1Y10/G1X-20", "G1Y10/G1Y11/G1Y10/G1X-20", True),
(
"G1X-10Y10/G1X-30Y-10",
"G1X-10Y10/G1X-10.71Y10.71/G1X-10Y10/G1X-30Y-10",
True,
),
("G1X-10/G1Y-20", "G1X-10/G1X-11/G1X-10/G1Y-20", True),
(
"G1X-10Y-10/G1X10Y-30",
"G1X-10Y-10/G1X-10.71Y-10.71/G1X-10Y-10/G1X10Y-30",
True,
),
("G1Y-10/G1X20", "G1Y-10/G1Y-11/G1Y-10/G1X20", True),
(
"G1X10Y-10/G1X30Y10",
"G1X10Y-10/G1X10.71Y-10.71/G1X10Y-10/G1X30Y10",
True,
),
# CW
("G1X10/G1Y-20", "G1X10/G1X11/G1X10/G1Y-20", False),
("G1X10Y10/G1X30Y-10", "G1X10Y10/G1X10.71Y10.71/G1X10Y10/G1X30Y-10", False),
("G1Y10/G1X20", "G1Y10/G1Y11/G1Y10/G1X20", False),
(
"G1X-10Y10/G1X10Y30",
"G1X-10Y10/G1X-10.71Y10.71/G1X-10Y10/G1X10Y30",
False,
),
("G1X-10/G1Y20", "G1X-10/G1X-11/G1X-10/G1Y20", False),
(
"G1X-10Y-10/G1X-30Y10",
"G1X-10Y-10/G1X-10.71Y-10.71/G1X-10Y-10/G1X-30Y10",
False,
),
("G1Y-10/G1X-20", "G1Y-10/G1Y-11/G1Y-10/G1X-20", False),
(
"G1X10Y-10/G1X-10Y-30",
"G1X10Y-10/G1X10.71Y-10.71/G1X10Y-10/G1X-10Y-30",
False,
),
]
for i, (path, out, right) in enumerate(test_data_1):
check_tbone_l("1", i, path, out, right)
# long edge m0
test_data_0 = [
# CCW
("G1X20/G1Y10", "G1X20/G1Y-1/G1Y0/G1Y10", True),
("G1X20Y20/G1X10Y30", "G1X20Y20/G1X20.71Y19.29/G1X20Y20/G1X10Y30", True),
("G1Y20/G1X-10", "G1Y20/G1X1/G1X0/G1X-10", True),
(
"G1X-20Y20/G1X-30Y10",
"G1X-20Y20/G1X-19.29Y20.71/G1X-20Y20/G1X-30Y10",
True,
),
("G1X-20/G1Y-10", "G1X-20/G1Y1/G1Y0/G1Y-10", True),
(
"G1X-20Y-20/G1X-10Y-30",
"G1X-20Y-20/G1X-20.71Y-19.29/G1X-20Y-20/G1X-10Y-30",
True,
),
("G1Y-20/G1X10", "G1Y-20/G1X-1/G1X0/G1X10", True),
(
"G1X20Y-20/G1X30Y-10",
"G1X20Y-20/G1X19.29Y-20.71/G1X20Y-20/G1X30Y-10",
True,
),
# CW
("G1X20/G1Y-10", "G1X20/G1Y1/G1Y0/G1Y-10", False),
("G1X20Y20/G1X30Y10", "G1X20Y20/G1X19.29Y20.71/G1X20Y20/G1X30Y10", False),
("G1Y20/G1X10", "G1Y20/G1X-1/G1X0/G1X10", False),
(
"G1X-20Y20/G1X-10Y30",
"G1X-20Y20/G1X-20.71Y19.29/G1X-20Y20/G1X-10Y30",
False,
),
("G1X-20/G1Y10", "G1X-20/G1Y-1/G1Y0/G1Y10", False),
(
"G1X-20Y-20/G1X-30Y-10",
"G1X-20Y-20/G1X-19.29Y-20.71/G1X-20Y-20/G1X-30Y-10",
False,
),
("G1Y-20/G1X-10", "G1Y-20/G1X1/G1X0/G1X-10", False),
(
"G1X20Y-20/G1X10Y-30",
"G1X20Y-20/G1X20.71Y-19.29/G1X20Y-20/G1X10Y-30",
False,
),
]
for i, (path, out, right) in enumerate(test_data_0):
check_tbone_l("0", i, path, out, right)
def test60(self):
"""Verify Dogbone style"""
obj = CreateDressup("G1X10/G1Y20")
obj.Incision = Path.Dressup.DogboneII.Incision.Fixed
obj.Side = Path.Dressup.DogboneII.Side.Right
obj.Style = Path.Dressup.DogboneII.Style.Dogbone
obj.Proxy.execute(obj)
self.assertEqualPath(obj.Path, "G1X10/G1X10.71Y-0.71/G1X10Y0/G1Y20")
def test70(self):
"""Verify custom length."""
obj = CreateDressup("G0Z10/G1Z0/G1X10/G1Y10/G1X0/G1Y0/G0Z10")
obj.Style = Path.Dressup.DogboneII.Style.Tbone_H
obj.Side = Path.Dressup.DogboneII.Side.Right
obj.Incision = Path.Dressup.DogboneII.Incision.Custom
obj.Custom = 3
obj.Proxy.execute(obj)
self.assertEqualPath(
obj.Path,
"G0Z10/G1Z0/G1X10/G1X13/G1X10/G1Y10/G1X13/G1X10/G1X0/G1X-3/G1X0/G1Y0/G1X-3/G1X0/G0Z10",
)
obj.Custom = 2
obj.Proxy.execute(obj)
self.assertEqualPath(
obj.Path,
"G0Z10/G1Z0/G1X10/G1X12/G1X10/G1Y10/G1X12/G1X10/G1X0/G1X-2/G1X0/G1Y0/G1X-2/G1X0/G0Z10",
)
def test80(self):
"""Verify adaptive length."""
obj = CreateDressup("G1X10/G1Y20")
obj.Incision = Path.Dressup.DogboneII.Incision.Adaptive
obj.Side = Path.Dressup.DogboneII.Side.Right
obj.Style = Path.Dressup.DogboneII.Style.Dogbone
obj.Proxy.execute(obj)
self.assertEqualPath(obj.Path, "G1X10/G1X10.29Y-0.29/G1X10Y0/G1Y20")
def test81(self):
"""Verify adaptive length II."""
obj = CreateDressup("G1X10/G1X20Y20")
obj.Incision = Path.Dressup.DogboneII.Incision.Adaptive
obj.Side = Path.Dressup.DogboneII.Side.Right
obj.Style = Path.Dressup.DogboneII.Style.Dogbone
obj.Proxy.execute(obj)
self.assertEqualPath(obj.Path, "G1X10/G1X10.09Y-0.15/G1X10Y0/G1X20Y20")
def test90(self):
"""Verify dogbone blacklist"""
obj = CreateDressup("G0Z10/G1Z0/G1X10/G1Y10/G1X0/G1Y0/G0Z10")
obj.Incision = Path.Dressup.DogboneII.Incision.Fixed
obj.Style = Path.Dressup.DogboneII.Style.Tbone_H
obj.Side = Path.Dressup.DogboneII.Side.Right
obj.BoneBlacklist = [0, 2]
obj.Proxy.execute(obj)
self.assertEqualPath(
obj.Path, "G0Z10/G1Z0/G1X10/G1Y10/G1X11/G1X10/G1X0/G1Y0/G1X-1/G1X0/G0Z10"
)
return obj
def test91(self):
"""Verify dogbone on dogbone"""
obj = self.test90()
obj2 = MockFeaturePython("DressupDogbone001")
db2 = Path.Dressup.DogboneII.Proxy(obj2, obj)
obj2.Proxy = db2
obj2.Incision = Path.Dressup.DogboneII.Incision.Fixed
obj2.Style = Path.Dressup.DogboneII.Style.Tbone_H
obj2.Side = Path.Dressup.DogboneII.Side.Right
obj2.BoneBlacklist = [1]
obj2.Proxy.execute(obj2)
self.assertEqualPath(
obj2.Path,
"G0Z10/G1Z0/G1X10/G1X11/G1X10/G1Y10/G1X11/G1X10/G1X0/G1X-1/G1X0/G1Y0/G1X-1/G1X0/G0Z10",
)