2
# ***************************************************************************
3
# * Copyright (c) 2022 sliptonic <shopinthewoods@gmail.com> *
5
# * This program is free software; you can redistribute it and/or modify *
6
# * it under the terms of the GNU Lesser General Public License (LGPL) *
7
# * as published by the Free Software Foundation; either version 2 of *
8
# * the License, or (at your option) any later version. *
9
# * for detail see the LICENCE text file. *
11
# * This program is distributed in the hope that it will be useful, *
12
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14
# * GNU Library General Public License for more details. *
16
# * You should have received a copy of the GNU Library General Public *
17
# * License along with this program; if not, write to the Free Software *
18
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
21
# ***************************************************************************
25
import Path.Base.Generator.dogboneII as dogboneII
26
import Path.Base.Language as PathLanguage
27
import Path.Dressup.DogboneII
28
import Tests.PathTestUtils as PathTestUtils
35
def __init__(self, dia):
37
self.Label = "ToolBit"
38
self.Diameter = FreeCAD.Units.Quantity(dia, FreeCAD.Units.Length)
42
def __init__(self, dia=2):
45
self.Tool = MockTB(dia)
49
def __init__(self, path, dia=2):
52
self.Path = Path.Path(path)
53
self.ToolController = MockTC(dia)
56
class MockFeaturePython(object):
57
def __init__(self, name):
59
self.addProperty("App::PropertyString", "Name", val=name)
60
self.addProperty("App::PropertyString", "Label", val=name)
61
self.addProperty("App::PropertyLink", "Proxy")
62
self.addProperty("Path::Path", "Path", val=Path.Path())
64
def addProperty(self, typ, name, grp=None, desc=None, val=None):
65
self.prop[name] = (typ, val)
67
def setEditorMode(self, name, mode):
70
def __setattr__(self, name, val):
72
return super().__setattr__(name, val)
73
self.prop[name] = (self.prop[name][0], val)
75
def __getattr__(self, name):
77
return super().__getattr__(name)
78
typ, val = self.prop.get(name, (None, None))
79
if typ is None and val is None:
81
if typ == "App::PropertyLength":
82
if type(val) == float or type(val) == int:
83
return FreeCAD.Units.Quantity(val, FreeCAD.Units.Length)
84
return FreeCAD.Units.Quantity(val)
88
def CreateDressup(path):
90
obj = MockFeaturePython("DressupDogbone")
91
db = Path.Dressup.DogboneII.Proxy(obj, op)
96
def MNVR(gcode, begin=None):
97
# 'turns out the replace() isn't really necessary
98
# leave it here anyway for clarity
99
return PathLanguage.Maneuver.FromGCode(gcode.replace("/", "\n"), begin)
102
def INSTR(gcode, begin=None):
103
return MNVR(gcode, begin).instr[0]
106
def KINK(gcode, begin=None):
107
maneuver = MNVR(gcode, begin)
108
if len(maneuver.instr) != 2:
110
return dogboneII.Kink(maneuver.instr[0], maneuver.instr[1])
113
class TestDressupDogboneII(PathTestUtils.PathTestBase):
114
"""Unit tests for the DogboneII dressup."""
116
def assertEqualPath(self, path, s):
119
f"{k}{v:g}" if Path.Geom.isRoughly(0, v - int(v)) else f"{k}{v:.2f}"
120
for k, v in cmd.Parameters.items()
122
return f"{cmd.Name}{''.join(param)}"
124
p = "/".join([cmd2str(cmd) for cmd in path.Commands])
125
self.assertEqual(p, s)
128
"""Verify adaptive length"""
130
def adaptive(k, a, n):
131
return Path.Dressup.DogboneII.calc_length_adaptive(k, a, n, n)
135
self.assertRoughly(adaptive(KINK("G1X1/G1X2"), 0, 1), 0)
136
self.assertRoughly(adaptive(KINK("G1X1/G1Y1"), 0, 1), 1)
137
self.assertRoughly(adaptive(KINK("G1X1/G1X2Y1"), 0, 1), 0.414214)
138
self.assertRoughly(adaptive(KINK("G1X1/G1X0Y1"), 0, 1), 2.414211)
139
self.assertRoughly(adaptive(KINK("G1X1/G1X0"), 0, 1), 1)
140
self.assertRoughly(adaptive(KINK("G1X1/G1X0Y-1"), 0, 1), 2.414211)
141
self.assertRoughly(adaptive(KINK("G1X1/G1X1Y-1"), 0, 1), 1)
142
self.assertRoughly(adaptive(KINK("G1X1/G1X2Y-1"), 0, 1), 0.414214)
143
self.assertRoughly(adaptive(KINK("G1X1Y1/G1X0Y2"), 0, 1), 0.414214)
146
# more horizontal and some vertical bones
147
self.assertRoughly(adaptive(KINK("G1Y1/G1Y2"), 0, 1), 0)
148
self.assertRoughly(adaptive(KINK("G1Y1/G1Y1X1"), PI, 1), 1)
149
self.assertRoughly(adaptive(KINK("G1Y1/G1Y2X1"), PI, 1), 0.089820)
150
self.assertRoughly(adaptive(KINK("G1Y1/G1Y2X1"), PI / 2, 1), 0.414214)
151
self.assertRoughly(adaptive(KINK("G1Y1/G1Y0X1"), PI / 2, 1), 2.414211)
152
self.assertRoughly(adaptive(KINK("G1Y1/G1Y0"), 0, 1), 1)
153
self.assertRoughly(adaptive(KINK("G1Y1/G1Y0X-1"), PI / 2, 1), 2.414211)
154
self.assertRoughly(adaptive(KINK("G1Y1/G1Y1X-1"), 0, 1), 1)
155
self.assertRoughly(adaptive(KINK("G1Y1/G1Y2X-1"), 0, 1), 0.089820)
156
self.assertRoughly(adaptive(KINK("G1Y1/G1Y2X-1"), PI / 2, 1), 0.414214)
160
self.assertRoughly(adaptive(KINK("G1X1/G1Y1"), -PI / 4, 1), 0.414214)
161
self.assertRoughly(adaptive(KINK("G1X1/G1X0Y1"), -PI / 8, 1), 1.613126)
162
self.assertRoughly(adaptive(KINK("G1X1/G1Y-1"), PI / 4, 1), 0.414214)
163
self.assertRoughly(adaptive(KINK("G1X1/G1X0Y-1"), PI / 8, 1), 1.613126)
164
self.assertRoughly(adaptive(KINK("G1Y1/G1X-1"), PI / 4, 1), 0.414214)
165
self.assertRoughly(adaptive(KINK("G1Y1/G1X1"), 3 * PI / 4, 1), 0.414214)
166
self.assertRoughly(adaptive(KINK("G1Y-1/G1X1"), -3 * PI / 4, 1), 0.414214)
167
self.assertRoughly(adaptive(KINK("G1Y-1/G1X-1"), -PI / 4, 1), 0.414214)
168
self.assertRoughly(adaptive(KINK("G1X1Y1/G1X0Y2"), 0, 1), 0.414214)
169
self.assertRoughly(adaptive(KINK("G1X-1Y1/G1X0Y2"), PI, 1), 0.414214)
170
self.assertRoughly(adaptive(KINK("G1X1Y1/G1X2Y0"), PI / 2, 2), 0.828428)
171
self.assertRoughly(adaptive(KINK("G1X-1Y-1/G1X-2Y0"), -PI / 2, 2), 0.828428)
172
self.assertRoughly(adaptive(KINK("G1X-1Y1/G1X-2Y0"), PI / 2, 2), 0.828428)
173
self.assertRoughly(adaptive(KINK("G1X1Y-1/G1X2Y0"), -PI / 2, 2), 0.828428)
176
"""Verify nominal length"""
178
def nominal(k, a, n):
179
return Path.Dressup.DogboneII.calc_length_nominal(k, a, n, 0)
181
# neither angle nor kink matter
182
self.assertRoughly(nominal(KINK("G1X1/G1X2"), 0, 13), 13)
183
self.assertRoughly(nominal(KINK("G1X1/G1X2"), PI / 2, 13), 13)
184
self.assertRoughly(nominal(KINK("G1X1/G1X2"), PI, 13), 13)
185
self.assertRoughly(nominal(KINK("G1X1/G1X2"), -PI / 2, 13), 13)
186
self.assertRoughly(nominal(KINK("G1X8/G1X12"), 0, 13), 13)
187
self.assertRoughly(nominal(KINK("G1X9/G1X0"), 0, 13), 13)
188
self.assertRoughly(nominal(KINK("G1X7/G1X9"), 0, 13), 13)
189
self.assertRoughly(nominal(KINK("G1X5/G1X1"), 0, 13), 13)
192
"""Verify custom length"""
195
return Path.Dressup.DogboneII.calc_length_custom(k, a, 0, c)
197
# neither angle nor kink matter
198
self.assertRoughly(custom(KINK("G1X1/G1X2"), 0, 7), 7)
199
self.assertRoughly(custom(KINK("G1X1/G1X2"), PI / 2, 7), 7)
200
self.assertRoughly(custom(KINK("G1X1/G1X2"), PI, 7), 7)
201
self.assertRoughly(custom(KINK("G1X1/G1X2"), -PI / 2, 7), 7)
202
self.assertRoughly(custom(KINK("G1X8/G1X12"), 0, 7), 7)
203
self.assertRoughly(custom(KINK("G1X9/G1X0"), 0, 7), 7)
204
self.assertRoughly(custom(KINK("G1X7/G1X9"), 0, 7), 7)
205
self.assertRoughly(custom(KINK("G1X5/G1X1"), 0, 7), 7)
208
"""Verify basic op dressup"""
210
obj = CreateDressup("G1X10/G1Y20")
211
obj.Incision = Path.Dressup.DogboneII.Incision.Fixed
212
obj.Style = Path.Dressup.DogboneII.Style.Tbone_H
214
# bones on right side
215
obj.Side = Path.Dressup.DogboneII.Side.Right
216
obj.Proxy.execute(obj)
217
self.assertEqualPath(obj.Path, "G1X10/G1X11/G1X10/G1Y20")
219
# no bones on left side
220
obj.Side = Path.Dressup.DogboneII.Side.Left
221
obj.Proxy.execute(obj)
222
self.assertEqualPath(obj.Path, "G1X10/G1Y20")
225
"""Verify retaining non-move instructions"""
227
obj = CreateDressup("G1X10/(some comment)/G1Y20")
228
obj.Incision = Path.Dressup.DogboneII.Incision.Fixed
229
obj.Style = Path.Dressup.DogboneII.Style.Tbone_H
232
obj.Side = Path.Dressup.DogboneII.Side.Right
233
obj.Proxy.execute(obj)
234
self.assertEqualPath(obj.Path, "G1X10/(some comment)/G1X11/G1X10/G1Y20")
236
# no bone on left side
237
obj.Side = Path.Dressup.DogboneII.Side.Left
238
obj.Proxy.execute(obj)
239
self.assertEqualPath(obj.Path, "G1X10/(some comment)/G1Y20")
242
"""Verify bone on plunge moves"""
244
obj = CreateDressup("G0Z10/G1Z0/G1X10/G1Y10/G1X0/G1Y0/G0Z10")
245
obj.Incision = Path.Dressup.DogboneII.Incision.Fixed
246
obj.Style = Path.Dressup.DogboneII.Style.Tbone_H
247
obj.Side = Path.Dressup.DogboneII.Side.Right
249
obj.Proxy.execute(obj)
250
self.assertEqualPath(
252
"G0Z10/G1Z0/G1X10/G1X11/G1X10/G1Y10/G1X11/G1X10/G1X0/G1X-1/G1X0/G1Y0/G1X-1/G1X0/G0Z10",
256
"""Verify ignoring plunge moves that don't connect"""
258
obj = CreateDressup("G0Z10/G1Z0/G1X10/G1Y10/G1X0/G1Y5/G0Z10")
259
obj.Incision = Path.Dressup.DogboneII.Incision.Fixed
260
obj.Style = Path.Dressup.DogboneII.Style.Tbone_H
261
obj.Side = Path.Dressup.DogboneII.Side.Right
263
obj.Proxy.execute(obj)
264
self.assertEqualPath(
266
"G0Z10/G1Z0/G1X10/G1X11/G1X10/G1Y10/G1X11/G1X10/G1X0/G1X-1/G1X0/G1Y5/G0Z10",
270
"""Verify TBone_V style"""
272
def check_tbone(d, i, path, out, right):
273
obj = CreateDressup(f"({d}.{i:02})/{path}")
274
obj.Incision = Path.Dressup.DogboneII.Incision.Fixed
276
obj.Side = Path.Dressup.DogboneII.Side.Right
278
obj.Side = Path.Dressup.DogboneII.Side.Left
279
obj.Style = Path.Dressup.DogboneII.Style.Tbone_V
280
obj.Proxy.execute(obj)
281
self.assertEqualPath(obj.Path, f"({d}.{i:02})/{out}")
283
# test data with a horizontal lead in
286
("G1X10Y0/G1X10Y10", "G1X10Y0/G1Y-1/G1Y0/G1X10Y10", True),
287
("G1X10Y0/G1X20Y10", "G1X10Y0/G1Y-1/G1Y0/G1X20Y10", True),
288
("G1X10Y0/G1X90Y10", "G1X10Y0/G1Y-1/G1Y0/G1X90Y10", True),
289
("G1X10Y0/G1X0Y10", "G1X10Y0/G1Y-1/G1Y0/G1X0Y10", True),
290
# bottom right quadrant
291
("G1X10Y0/G1X90Y-10", "G1X10Y0/G1Y1/G1Y0/G1X90Y-10", False),
292
("G1X10Y0/G1X20Y-10", "G1X10Y0/G1Y1/G1Y0/G1X20Y-10", False),
293
("G1X10Y0/G1X10Y-10", "G1X10Y0/G1Y1/G1Y0/G1X10Y-10", False),
294
("G1X10Y0/G1X0Y-10", "G1X10Y0/G1Y1/G1Y0/G1X0Y-10", False),
296
("G1X-10Y0/G1X-10Y10", "G1X-10Y0/G1Y-1/G1Y0/G1X-10Y10", False),
297
("G1X-10Y0/G1X-20Y10", "G1X-10Y0/G1Y-1/G1Y0/G1X-20Y10", False),
298
("G1X-10Y0/G1X-90Y10", "G1X-10Y0/G1Y-1/G1Y0/G1X-90Y10", False),
299
("G1X-10Y0/G1X-0Y10", "G1X-10Y0/G1Y-1/G1Y0/G1X-0Y10", False),
300
# bottom left quadrant
301
("G1X-10Y0/G1X-90Y-10", "G1X-10Y0/G1Y1/G1Y0/G1X-90Y-10", True),
302
("G1X-10Y0/G1X-20Y-10", "G1X-10Y0/G1Y1/G1Y0/G1X-20Y-10", True),
303
("G1X-10Y0/G1X-10Y-10", "G1X-10Y0/G1Y1/G1Y0/G1X-10Y-10", True),
304
("G1X-10Y0/G1X-0Y-10", "G1X-10Y0/G1Y1/G1Y0/G1X-0Y-10", True),
307
for i, (path, out, right) in enumerate(test_data_h):
308
check_tbone("h", i, path, out, right)
310
# test data with a vertical lead in
313
("G1X0Y10/G1X10Y10", "G1X0Y10/G1Y11/G1Y10/G1X10Y10", False),
314
("G1X0Y10/G1X10Y20", "G1X0Y10/G1Y11/G1Y10/G1X10Y20", False),
315
("G1X0Y10/G1X10Y90", "G1X0Y10/G1Y11/G1Y10/G1X10Y90", False),
316
("G1X0Y10/G1X10Y0", "G1X0Y10/G1Y11/G1Y10/G1X10Y0", False),
317
# bottom right quadrant
318
("G1X0Y-10/G1X10Y-90", "G1X0Y-10/G1Y-11/G1Y-10/G1X10Y-90", True),
319
("G1X0Y-10/G1X10Y-20", "G1X0Y-10/G1Y-11/G1Y-10/G1X10Y-20", True),
320
("G1X0Y-10/G1X10Y-10", "G1X0Y-10/G1Y-11/G1Y-10/G1X10Y-10", True),
321
("G1X0Y-10/G1X10Y-0", "G1X0Y-10/G1Y-11/G1Y-10/G1X10Y-0", True),
323
("G1X0Y10/G1X-10Y10", "G1X0Y10/G1Y11/G1Y10/G1X-10Y10", True),
324
("G1X0Y10/G1X-10Y20", "G1X0Y10/G1Y11/G1Y10/G1X-10Y20", True),
325
("G1X0Y10/G1X-10Y90", "G1X0Y10/G1Y11/G1Y10/G1X-10Y90", True),
326
("G1X0Y10/G1X-10Y0", "G1X0Y10/G1Y11/G1Y10/G1X-10Y0", True),
327
# bottom left quadrant
328
("G1X0Y-10/G1X-10Y-90", "G1X0Y-10/G1Y-11/G1Y-10/G1X-10Y-90", False),
329
("G1X0Y-10/G1X-10Y-20", "G1X0Y-10/G1Y-11/G1Y-10/G1X-10Y-20", False),
330
("G1X0Y-10/G1X-10Y-10", "G1X0Y-10/G1Y-11/G1Y-10/G1X-10Y-10", False),
331
("G1X0Y-10/G1X-10Y-0", "G1X0Y-10/G1Y-11/G1Y-10/G1X-10Y-0", False),
334
for i, (path, out, right) in enumerate(test_data_v):
335
check_tbone("v", i, path, out, right)
338
"""Verify TBone_S style"""
340
def check_tbone_s(d, i, path, out, right):
341
obj = CreateDressup(f"(m{d}.{i:02})/{path}")
342
obj.Incision = Path.Dressup.DogboneII.Incision.Fixed
344
obj.Side = Path.Dressup.DogboneII.Side.Right
346
obj.Side = Path.Dressup.DogboneII.Side.Left
347
obj.Style = Path.Dressup.DogboneII.Style.Tbone_S
348
obj.Proxy.execute(obj)
349
self.assertEqualPath(obj.Path, f"(m{d}.{i:02})/{out}")
354
("G1X10/G1Y20", "G1X10/G1Y-1/G1Y0/G1Y20", True),
355
("G1X10Y10/G1X-10Y30", "G1X10Y10/G1X10.71Y9.29/G1X10Y10/G1X-10Y30", True),
356
("G1Y10/G1X-20", "G1Y10/G1X1/G1X0/G1X-20", True),
358
"G1X-10Y10/G1X-30Y-10",
359
"G1X-10Y10/G1X-9.29Y10.71/G1X-10Y10/G1X-30Y-10",
362
("G1X-10/G1Y-20", "G1X-10/G1Y1/G1Y0/G1Y-20", True),
364
"G1X-10Y-10/G1X10Y-30",
365
"G1X-10Y-10/G1X-10.71Y-9.29/G1X-10Y-10/G1X10Y-30",
368
("G1Y-10/G1X20", "G1Y-10/G1X-1/G1X0/G1X20", True),
369
("G1X10Y-10/G1X30Y10", "G1X10Y-10/G1X9.29Y-10.71/G1X10Y-10/G1X30Y10", True),
371
("G1X10/G1Y-20", "G1X10/G1Y1/G1Y0/G1Y-20", False),
372
("G1X10Y10/G1X30Y-10", "G1X10Y10/G1X9.29Y10.71/G1X10Y10/G1X30Y-10", False),
373
("G1Y10/G1X20", "G1Y10/G1X-1/G1X0/G1X20", False),
375
"G1X-10Y10/G1X10Y30",
376
"G1X-10Y10/G1X-10.71Y9.29/G1X-10Y10/G1X10Y30",
379
("G1X-10/G1Y20", "G1X-10/G1Y-1/G1Y0/G1Y20", False),
381
"G1X-10Y-10/G1X-30Y10",
382
"G1X-10Y-10/G1X-9.29Y-10.71/G1X-10Y-10/G1X-30Y10",
385
("G1Y-10/G1X-20", "G1Y-10/G1X1/G1X0/G1X-20", False),
387
"G1X10Y-10/G1X-10Y-30",
388
"G1X10Y-10/G1X10.71Y-9.29/G1X10Y-10/G1X-10Y-30",
393
for i, (path, out, right) in enumerate(test_data_0):
394
check_tbone_s("0", i, path, out, right)
399
("G1X20/G1Y10", "G1X20/G1X21/G1X20/G1Y10", True),
400
("G1X20Y20/G1X10Y30", "G1X20Y20/G1X20.71Y20.71/G1X20Y20/G1X10Y30", True),
401
("G1Y20/G1X-10", "G1Y20/G1Y21/G1Y20/G1X-10", True),
403
"G1X-20Y20/G1X-30Y10",
404
"G1X-20Y20/G1X-20.71Y20.71/G1X-20Y20/G1X-30Y10",
407
("G1X-20/G1Y-10", "G1X-20/G1X-21/G1X-20/G1Y-10", True),
409
"G1X-20Y-20/G1X-10Y-30",
410
"G1X-20Y-20/G1X-20.71Y-20.71/G1X-20Y-20/G1X-10Y-30",
413
("G1Y-20/G1X10", "G1Y-20/G1Y-21/G1Y-20/G1X10", True),
415
"G1X20Y-20/G1X30Y-10",
416
"G1X20Y-20/G1X20.71Y-20.71/G1X20Y-20/G1X30Y-10",
420
("G1X20/G1Y-10", "G1X20/G1X21/G1X20/G1Y-10", False),
421
("G1X20Y20/G1X30Y10", "G1X20Y20/G1X20.71Y20.71/G1X20Y20/G1X30Y10", False),
422
("G1Y20/G1X10", "G1Y20/G1Y21/G1Y20/G1X10", False),
424
"G1X-20Y20/G1X-10Y30",
425
"G1X-20Y20/G1X-20.71Y20.71/G1X-20Y20/G1X-10Y30",
428
("G1X-20/G1Y10", "G1X-20/G1X-21/G1X-20/G1Y10", False),
430
"G1X-20Y-20/G1X-30Y-10",
431
"G1X-20Y-20/G1X-20.71Y-20.71/G1X-20Y-20/G1X-30Y-10",
434
("G1Y-20/G1X-10", "G1Y-20/G1Y-21/G1Y-20/G1X-10", False),
436
"G1X20Y-20/G1X10Y-30",
437
"G1X20Y-20/G1X20.71Y-20.71/G1X20Y-20/G1X10Y-30",
442
for i, (path, out, right) in enumerate(test_data_1):
443
check_tbone_s("1", i, path, out, right)
446
"""Verify TBone_L style"""
448
def check_tbone_l(d, i, path, out, right):
449
obj = CreateDressup(f"(m{d}.{i:02})/{path}")
450
obj.Incision = Path.Dressup.DogboneII.Incision.Fixed
452
obj.Side = Path.Dressup.DogboneII.Side.Right
454
obj.Side = Path.Dressup.DogboneII.Side.Left
455
obj.Style = Path.Dressup.DogboneII.Style.Tbone_L
456
obj.Proxy.execute(obj)
457
self.assertEqualPath(obj.Path, f"(m{d}.{i:02})/{out}")
462
("G1X10/G1Y20", "G1X10/G1X11/G1X10/G1Y20", True),
463
("G1X10Y10/G1X-10Y30", "G1X10Y10/G1X10.71Y10.71/G1X10Y10/G1X-10Y30", True),
464
("G1Y10/G1X-20", "G1Y10/G1Y11/G1Y10/G1X-20", True),
466
"G1X-10Y10/G1X-30Y-10",
467
"G1X-10Y10/G1X-10.71Y10.71/G1X-10Y10/G1X-30Y-10",
470
("G1X-10/G1Y-20", "G1X-10/G1X-11/G1X-10/G1Y-20", True),
472
"G1X-10Y-10/G1X10Y-30",
473
"G1X-10Y-10/G1X-10.71Y-10.71/G1X-10Y-10/G1X10Y-30",
476
("G1Y-10/G1X20", "G1Y-10/G1Y-11/G1Y-10/G1X20", True),
478
"G1X10Y-10/G1X30Y10",
479
"G1X10Y-10/G1X10.71Y-10.71/G1X10Y-10/G1X30Y10",
483
("G1X10/G1Y-20", "G1X10/G1X11/G1X10/G1Y-20", False),
484
("G1X10Y10/G1X30Y-10", "G1X10Y10/G1X10.71Y10.71/G1X10Y10/G1X30Y-10", False),
485
("G1Y10/G1X20", "G1Y10/G1Y11/G1Y10/G1X20", False),
487
"G1X-10Y10/G1X10Y30",
488
"G1X-10Y10/G1X-10.71Y10.71/G1X-10Y10/G1X10Y30",
491
("G1X-10/G1Y20", "G1X-10/G1X-11/G1X-10/G1Y20", False),
493
"G1X-10Y-10/G1X-30Y10",
494
"G1X-10Y-10/G1X-10.71Y-10.71/G1X-10Y-10/G1X-30Y10",
497
("G1Y-10/G1X-20", "G1Y-10/G1Y-11/G1Y-10/G1X-20", False),
499
"G1X10Y-10/G1X-10Y-30",
500
"G1X10Y-10/G1X10.71Y-10.71/G1X10Y-10/G1X-10Y-30",
505
for i, (path, out, right) in enumerate(test_data_1):
506
check_tbone_l("1", i, path, out, right)
511
("G1X20/G1Y10", "G1X20/G1Y-1/G1Y0/G1Y10", True),
512
("G1X20Y20/G1X10Y30", "G1X20Y20/G1X20.71Y19.29/G1X20Y20/G1X10Y30", True),
513
("G1Y20/G1X-10", "G1Y20/G1X1/G1X0/G1X-10", True),
515
"G1X-20Y20/G1X-30Y10",
516
"G1X-20Y20/G1X-19.29Y20.71/G1X-20Y20/G1X-30Y10",
519
("G1X-20/G1Y-10", "G1X-20/G1Y1/G1Y0/G1Y-10", True),
521
"G1X-20Y-20/G1X-10Y-30",
522
"G1X-20Y-20/G1X-20.71Y-19.29/G1X-20Y-20/G1X-10Y-30",
525
("G1Y-20/G1X10", "G1Y-20/G1X-1/G1X0/G1X10", True),
527
"G1X20Y-20/G1X30Y-10",
528
"G1X20Y-20/G1X19.29Y-20.71/G1X20Y-20/G1X30Y-10",
532
("G1X20/G1Y-10", "G1X20/G1Y1/G1Y0/G1Y-10", False),
533
("G1X20Y20/G1X30Y10", "G1X20Y20/G1X19.29Y20.71/G1X20Y20/G1X30Y10", False),
534
("G1Y20/G1X10", "G1Y20/G1X-1/G1X0/G1X10", False),
536
"G1X-20Y20/G1X-10Y30",
537
"G1X-20Y20/G1X-20.71Y19.29/G1X-20Y20/G1X-10Y30",
540
("G1X-20/G1Y10", "G1X-20/G1Y-1/G1Y0/G1Y10", False),
542
"G1X-20Y-20/G1X-30Y-10",
543
"G1X-20Y-20/G1X-19.29Y-20.71/G1X-20Y-20/G1X-30Y-10",
546
("G1Y-20/G1X-10", "G1Y-20/G1X1/G1X0/G1X-10", False),
548
"G1X20Y-20/G1X10Y-30",
549
"G1X20Y-20/G1X20.71Y-19.29/G1X20Y-20/G1X10Y-30",
554
for i, (path, out, right) in enumerate(test_data_0):
555
check_tbone_l("0", i, path, out, right)
558
"""Verify Dogbone style"""
560
obj = CreateDressup("G1X10/G1Y20")
561
obj.Incision = Path.Dressup.DogboneII.Incision.Fixed
562
obj.Side = Path.Dressup.DogboneII.Side.Right
564
obj.Style = Path.Dressup.DogboneII.Style.Dogbone
565
obj.Proxy.execute(obj)
566
self.assertEqualPath(obj.Path, "G1X10/G1X10.71Y-0.71/G1X10Y0/G1Y20")
569
"""Verify custom length."""
571
obj = CreateDressup("G0Z10/G1Z0/G1X10/G1Y10/G1X0/G1Y0/G0Z10")
572
obj.Style = Path.Dressup.DogboneII.Style.Tbone_H
573
obj.Side = Path.Dressup.DogboneII.Side.Right
575
obj.Incision = Path.Dressup.DogboneII.Incision.Custom
577
obj.Proxy.execute(obj)
578
self.assertEqualPath(
580
"G0Z10/G1Z0/G1X10/G1X13/G1X10/G1Y10/G1X13/G1X10/G1X0/G1X-3/G1X0/G1Y0/G1X-3/G1X0/G0Z10",
584
obj.Proxy.execute(obj)
585
self.assertEqualPath(
587
"G0Z10/G1Z0/G1X10/G1X12/G1X10/G1Y10/G1X12/G1X10/G1X0/G1X-2/G1X0/G1Y0/G1X-2/G1X0/G0Z10",
591
"""Verify adaptive length."""
593
obj = CreateDressup("G1X10/G1Y20")
594
obj.Incision = Path.Dressup.DogboneII.Incision.Adaptive
595
obj.Side = Path.Dressup.DogboneII.Side.Right
597
obj.Style = Path.Dressup.DogboneII.Style.Dogbone
598
obj.Proxy.execute(obj)
599
self.assertEqualPath(obj.Path, "G1X10/G1X10.29Y-0.29/G1X10Y0/G1Y20")
602
"""Verify adaptive length II."""
604
obj = CreateDressup("G1X10/G1X20Y20")
605
obj.Incision = Path.Dressup.DogboneII.Incision.Adaptive
606
obj.Side = Path.Dressup.DogboneII.Side.Right
608
obj.Style = Path.Dressup.DogboneII.Style.Dogbone
609
obj.Proxy.execute(obj)
610
self.assertEqualPath(obj.Path, "G1X10/G1X10.09Y-0.15/G1X10Y0/G1X20Y20")
613
"""Verify dogbone blacklist"""
615
obj = CreateDressup("G0Z10/G1Z0/G1X10/G1Y10/G1X0/G1Y0/G0Z10")
616
obj.Incision = Path.Dressup.DogboneII.Incision.Fixed
617
obj.Style = Path.Dressup.DogboneII.Style.Tbone_H
618
obj.Side = Path.Dressup.DogboneII.Side.Right
619
obj.BoneBlacklist = [0, 2]
620
obj.Proxy.execute(obj)
621
self.assertEqualPath(
622
obj.Path, "G0Z10/G1Z0/G1X10/G1Y10/G1X11/G1X10/G1X0/G1Y0/G1X-1/G1X0/G0Z10"
627
"""Verify dogbone on dogbone"""
631
obj2 = MockFeaturePython("DressupDogbone001")
632
db2 = Path.Dressup.DogboneII.Proxy(obj2, obj)
634
obj2.Incision = Path.Dressup.DogboneII.Incision.Fixed
635
obj2.Style = Path.Dressup.DogboneII.Style.Tbone_H
636
obj2.Side = Path.Dressup.DogboneII.Side.Right
637
obj2.BoneBlacklist = [1]
638
obj2.Proxy.execute(obj2)
639
self.assertEqualPath(
641
"G0Z10/G1Z0/G1X10/G1X11/G1X10/G1Y10/G1X11/G1X10/G1X0/G1X-1/G1X0/G1Y0/G1X-1/G1X0/G0Z10",