25
import Path.Base.Generator.dogboneII as dogboneII
26
import Path.Base.Language as PathLanguage
27
import Tests.PathTestUtils as PathTestUtils
32
Path.Log.setLevel(Path.Log.Level.NOTICE)
35
DebugMode = Path.Log.getLevel(Path.Log.thisModule()) == Path.Log.Level.DEBUG
38
def createKinks(maneuver):
40
moves = maneuver.getMoves()
45
k.append(dogboneII.Kink(prev, m))
47
if Path.Geom.pointsCoincide(move0.positionBegin(), prev.positionEnd()):
48
k.append(dogboneII.Kink(prev, move0))
52
def findDogboneKinks(maneuver, threshold):
54
return [k for k in createKinks(maneuver) if k.deflection() > threshold]
56
return [k for k in createKinks(maneuver) if k.deflection() < threshold]
57
return createKinks(maneuver)
60
def MNVR(gcode, begin=None):
63
return PathLanguage.Maneuver.FromGCode(gcode.replace("/", "\n"), begin)
66
def INSTR(gcode, begin=None):
67
return MNVR(gcode, begin).instr[0]
70
def KINK(gcode, begin=None):
71
maneuver = MNVR(gcode, begin)
72
if len(maneuver.instr) != 2:
74
return dogboneII.Kink(maneuver.instr[0], maneuver.instr[1])
77
def GEN(generator, length):
78
return generator(lambda k, a, n, c: n, length, 1)
81
class TestGeneratorDogboneII(PathTestUtils.PathTestBase):
82
"""Unit tests for the dogboneII generator."""
84
def assertKinks(self, maneuver, s):
85
kinks = [f"{k.deflection():4.2f}" for k in createKinks(maneuver)]
86
self.assertEqual(f"[{', '.join(kinks)}]", s)
88
def assertBones(self, maneuver, threshold, s):
89
bones = [f"({int(b.x())},{int(b.y())})" for b in findDogboneKinks(maneuver, threshold)]
90
self.assertEqual(f"[{', '.join(bones)}]", s)
92
def assertBone(self, bone, s, digits=0):
93
if DebugMode and FreeCAD.GuiUp:
94
Path.show(dogboneII.kink_to_path(bone.kink))
95
FreeCAD.ActiveDocument.Objects[-1].Visibility = False
96
Path.show(dogboneII.bone_to_path(bone))
97
FreeCAD.ActiveDocument.Objects[-1].Visibility = False
98
Path.Log.debug(f"{bone.kink} : {bone.angle / PI:.2f}")
100
b = [i.str(digits) for i in bone.instr]
101
self.assertEqual(f"[{', '.join(b)}]", s)
104
"""Verify kinks of maneuvers"""
105
self.assertKinks(MNVR("G1X1/G1Y1"), "[1.57]")
106
self.assertKinks(MNVR("G1X1/G1Y-1"), "[-1.57]")
107
self.assertKinks(MNVR("G1X1/G1Y1/G1X0"), "[1.57, 1.57]")
108
self.assertKinks(MNVR("G1X1/G1Y1/G1X0/G1Y0"), "[1.57, 1.57, 1.57, 1.57]")
110
self.assertKinks(MNVR("G1Y1/G1X1"), "[-1.57]")
111
self.assertKinks(MNVR("G1Y1/G1X1/G1Y0"), "[-1.57, -1.57]")
112
self.assertKinks(MNVR("G1Y1/G1X1/G1Y0/G1X0"), "[-1.57, -1.57, -1.57, -1.57]")
115
self.assertKinks(MNVR("G1X1/G3Y2J1"), "[0.00]")
116
self.assertKinks(MNVR("G1X1/G3Y2J1G1X0"), "[0.00, 0.00]")
119
self.assertKinks(MNVR("G1X1/G2Y2J1"), "[-3.14]")
120
self.assertKinks(MNVR("G1X1/G2Y2J1G1X0"), "[-3.14, 3.14]")
123
"""Verify dogbone detection"""
124
self.assertBones(MNVR("G1X1/G1Y1/G1X0/G1Y0"), PI / 4, "[(1,0), (1,1), (0,1), (0,0)]")
125
self.assertBones(MNVR("G1X1/G1Y1/G1X0/G1Y0"), -PI / 4, "[]")
128
self.assertBones(MNVR("G1X1/G1X3Y1/G1X0/G1Y0"), PI / 4, "[(3,1), (0,1), (0,0)]")
129
self.assertBones(MNVR("G1X1/G1X3Y1/G1X0/G1Y0"), -PI / 4, "[]")
132
self.assertBones(MNVR("G1X1/G3Y2J1/G1X0/G1Y0"), PI / 4, "[(0,2), (0,0)]")
133
self.assertBones(MNVR("G1X1/G3Y2J1/G1X0/G1Y0"), -PI / 4, "[]")
136
self.assertBones(MNVR("G1X1/G3X3I1/G1Y1/G1X0/G1Y0"), PI / 4, "[(3,1), (0,1), (0,0)]")
137
self.assertBones(MNVR("G1X1/G3X3I1/G1Y1/G1X0/G1Y0"), -PI / 4, "[(1,0)]")
140
"""Verify horizontal t-bone creation"""
143
horizontal = GEN(dogboneII.GeneratorTBoneHorizontal, 1)
146
maneuver = MNVR("G1X1/G1Y1")
147
kinks = findDogboneKinks(maneuver, PI / 4)
148
self.assertEqual(len(kinks), 1)
151
self.assertEqual(f"({int(p.x)}, {int(p.y)})", "(1, 0)")
152
bone = horizontal.generate(k)
153
self.assertBone(bone, "[G1{X: 2}, G1{X: 1}]")
156
kinks = findDogboneKinks(MNVR("G1X1/G1Y1/G1X0/G1Y0"), PI / 4)
157
bones = [horizontal.generate(k) for k in kinks]
158
self.assertEqual(len(bones), 4)
159
self.assertBone(bones[0], "[G1{X: 2}, G1{X: 1}]")
160
self.assertBone(bones[1], "[G1{X: 2}, G1{X: 1}]")
161
self.assertBone(bones[2], "[G1{X: -1}, G1{X: 0}]")
162
self.assertBone(bones[3], "[G1{X: -1}, G1{X: 0}]")
165
maneuver = MNVR("G1X1/G1Y-1")
166
kinks = findDogboneKinks(maneuver, -PI / 4)
167
self.assertEqual(len(kinks), 1)
170
self.assertEqual(f"({int(p.x)}, {int(p.y)})", "(1, 0)")
171
bone = horizontal.generate(k)
172
self.assertBone(bone, "[G1{X: 2}, G1{X: 1}]")
175
kinks = findDogboneKinks(MNVR("G1X1/G1Y-1/G1X0/G1Y0"), -PI / 4)
176
bones = [horizontal.generate(k) for k in kinks]
177
self.assertEqual(len(bones), 4)
178
self.assertBone(bones[0], "[G1{X: 2}, G1{X: 1}]")
179
self.assertBone(bones[1], "[G1{X: 2}, G1{X: 1}]")
180
self.assertBone(bones[2], "[G1{X: -1}, G1{X: 0}]")
181
self.assertBone(bones[3], "[G1{X: -1}, G1{X: 0}]")
184
kinks = findDogboneKinks(MNVR("G1X1/G3X3I1/G1Y1/G1X0/G1Y0"), PI / 4)
185
bones = [horizontal.generate(k) for k in kinks]
186
self.assertEqual(len(bones), 3)
187
self.assertBone(bones[0], "[G1{X: 4}, G1{X: 3}]")
188
self.assertBone(bones[1], "[G1{X: -1}, G1{X: 0}]")
189
self.assertBone(bones[2], "[G1{X: -1}, G1{X: 0}]")
192
kinks = findDogboneKinks(MNVR("G1X1/G3X3I1/G1Y1/G1X0/G1Y0"), -PI / 4)
193
bones = [horizontal.generate(k) for k in kinks]
194
self.assertEqual(len(bones), 1)
195
self.assertBone(bones[0], "[G1{X: 2}, G1{X: 1}]")
198
"""Verify vertical t-bone creation"""
201
vertical = GEN(dogboneII.GeneratorTBoneVertical, 1)
204
maneuver = MNVR("G1X1/G1Y1")
205
kinks = findDogboneKinks(maneuver, PI / 4)
206
self.assertEqual(len(kinks), 1)
209
self.assertEqual(f"({int(p.x)}, {int(p.y)})", "(1, 0)")
210
bone = vertical.generate(k)
211
self.assertBone(bone, "[G1{Y: -1}, G1{Y: 0}]")
214
kinks = findDogboneKinks(MNVR("G1X1/G1Y1/G1X0/G1Y0"), PI / 4)
215
bones = [vertical.generate(k) for k in kinks]
216
self.assertEqual(len(bones), 4)
217
self.assertBone(bones[0], "[G1{Y: -1}, G1{Y: 0}]")
218
self.assertBone(bones[1], "[G1{Y: 2}, G1{Y: 1}]")
219
self.assertBone(bones[2], "[G1{Y: 2}, G1{Y: 1}]")
220
self.assertBone(bones[3], "[G1{Y: -1}, G1{Y: 0}]")
223
maneuver = MNVR("G1X1/G1Y-1")
224
kinks = findDogboneKinks(maneuver, -PI / 4)
225
self.assertEqual(len(kinks), 1)
228
self.assertEqual(f"({int(p.x)}, {int(p.y)})", "(1, 0)")
229
bone = vertical.generate(k)
230
self.assertBone(bone, "[G1{Y: 1}, G1{Y: 0}]")
233
kinks = findDogboneKinks(MNVR("G1X1/G1Y-1/G1X0/G1Y0"), -PI / 4)
234
bones = [vertical.generate(k) for k in kinks]
235
self.assertEqual(len(bones), 4)
236
self.assertBone(bones[0], "[G1{Y: 1}, G1{Y: 0}]")
237
self.assertBone(bones[1], "[G1{Y: -2}, G1{Y: -1}]")
238
self.assertBone(bones[2], "[G1{Y: -2}, G1{Y: -1}]")
239
self.assertBone(bones[3], "[G1{Y: 1}, G1{Y: 0}]")
242
kinks = findDogboneKinks(MNVR("G1X1/G3X3I1/G1Y1/G1X0/G1Y0"), PI / 4)
243
bones = [vertical.generate(k) for k in kinks]
244
self.assertEqual(len(bones), 3)
245
self.assertBone(bones[0], "[G1{Y: 2}, G1{Y: 1}]")
246
self.assertBone(bones[1], "[G1{Y: 2}, G1{Y: 1}]")
247
self.assertBone(bones[2], "[G1{Y: -1}, G1{Y: 0}]")
250
kinks = findDogboneKinks(MNVR("G1X1/G3X3I1/G1Y1/G1X0/G1Y0"), -PI / 4)
251
bones = [vertical.generate(k) for k in kinks]
252
self.assertEqual(len(bones), 1)
253
self.assertBone(bones[0], "[G1{Y: 1}, G1{Y: 0}]")
256
"""Verify t-bones on edges"""
258
on_short_1 = GEN(dogboneII.GeneratorTBoneOnShort, 1)
259
on_short_5 = GEN(dogboneII.GeneratorTBoneOnShort, 5)
262
bone = on_short_1.generate(KINK("G1X1/G1Y2"))
263
self.assertBone(bone, "[G1{Y: -1}, G1{Y: 0}]")
265
bone = on_short_1.generate(KINK("G1X-1/G1Y2"))
266
self.assertBone(bone, "[G1{Y: -1}, G1{Y: 0}]")
269
bone = on_short_1.generate(KINK("G1Y1/G1X2"))
270
self.assertBone(bone, "[G1{X: -1}, G1{X: 0}]")
272
bone = on_short_1.generate(KINK("G1Y1/G1X-2"))
273
self.assertBone(bone, "[G1{X: 1}, G1{X: 0}]")
276
bone = on_short_5.generate(KINK("G1X1Y1/G1Y-1"))
277
self.assertBone(bone, "[G1{X: -2.5, Y: 4.5}, G1{X: 1.0, Y: 1.0}]", 2)
279
bone = on_short_5.generate(KINK("G1X-1Y-1/G1Y1"))
280
self.assertBone(bone, "[G1{X: 2.5, Y: -4.5}, G1{X: -1.0, Y: -1.0}]", 2)
283
bone = on_short_5.generate(KINK("G1X2Y1/G1Y-3"))
284
self.assertBone(bone, "[G1{X: -0.24, Y: 5.5}, G1{X: 2.0, Y: 1.0}]", 2)
286
bone = on_short_5.generate(KINK("G1X-2Y-1/G1Y3"))
287
self.assertBone(bone, "[G1{X: 0.24, Y: -5.5}, G1{X: -2.0, Y: -1.0}]", 2)
290
bone = on_short_1.generate(KINK("G1Y2/G1X1"))
291
self.assertBone(bone, "[G1{Y: 3}, G1{Y: 2}]")
292
bone = on_short_1.generate(KINK("G1Y2/G1X-1"))
293
self.assertBone(bone, "[G1{Y: 3}, G1{Y: 2}]")
295
bone = on_short_5.generate(KINK("G1Y-3/G1X2Y-2"))
296
self.assertBone(bone, "[G1{X: 2.2, Y: -7.5}, G1{X: 0.0, Y: -3.0}]", 2)
298
bone = on_short_5.generate(KINK("G1Y3/G1X-2Y2"))
299
self.assertBone(bone, "[G1{X: -2.2, Y: 7.5}, G1{X: 0.0, Y: 3.0}]", 2)
302
on_long_1 = GEN(dogboneII.GeneratorTBoneOnLong, 1)
303
on_long_5 = GEN(dogboneII.GeneratorTBoneOnLong, 5)
305
bone = on_long_1.generate(
308
self.assertBone(bone, "[G1{Y: -1}, G1{Y: 0}]")
309
bone = on_long_1.generate(KINK("G1X-2/G1Y1"))
310
self.assertBone(bone, "[G1{Y: -1}, G1{Y: 0}]")
312
bone = on_long_5.generate(KINK("G1Y-1/G1X2Y0"))
313
self.assertBone(bone, "[G1{X: 2.2, Y: -5.5}, G1{X: 0.0, Y: -1.0}]", 2)
315
bone = on_long_5.generate(KINK("G1Y1/G1X-2Y0"))
316
self.assertBone(bone, "[G1{X: -2.2, Y: 5.5}, G1{X: 0.0, Y: 1.0}]", 2)
319
"""Verify dogbone angles"""
320
self.assertRoughly(180 * KINK("G1X1/G1Y+1").normAngle() / PI, -45)
321
self.assertRoughly(180 * KINK("G1X1/G1Y-1").normAngle() / PI, 45)
323
self.assertRoughly(180 * KINK("G1X1/G1X2Y1").normAngle() / PI, -67.5)
324
self.assertRoughly(180 * KINK("G1X1/G1X2Y-1").normAngle() / PI, 67.5)
326
self.assertRoughly(180 * KINK("G1Y1/G1X+1").normAngle() / PI, 135)
327
self.assertRoughly(180 * KINK("G1Y1/G1X-1").normAngle() / PI, 45)
329
self.assertRoughly(180 * KINK("G1X-1/G1Y+1").normAngle() / PI, -135)
330
self.assertRoughly(180 * KINK("G1X-1/G1Y-1").normAngle() / PI, 135)
332
self.assertRoughly(180 * KINK("G1Y-1/G1X-1").normAngle() / PI, -45)
333
self.assertRoughly(180 * KINK("G1Y-1/G1X+1").normAngle() / PI, -135)
336
"""Verify dogbones"""
338
dogbone = GEN(dogboneII.GeneratorDogbone, 1)
340
bone = dogbone.generate(KINK("G1X1/G1Y1"))
341
self.assertBone(bone, "[G1{X: 1.7, Y: -0.71}, G1{X: 1.0, Y: 0.0}]", 2)
343
bone = dogbone.generate(KINK("G1X1/G1X3Y-1"))
344
self.assertBone(bone, "[G1{X: 1.2, Y: 0.97}, G1{X: 1.0, Y: 0.0}]", 2)
346
bone = dogbone.generate(KINK("G1X1Y1/G1X2"))
347
self.assertBone(bone, "[G1{X: 0.62, Y: 1.9}, G1{X: 1.0, Y: 1.0}]", 2)