FreeCAD

Форк
0
/
TestPathDressupDogboneII.py 
642 строки · 25.6 Кб
1
# -*- coding: utf-8 -*-
2
# ***************************************************************************
3
# *   Copyright (c) 2022 sliptonic <shopinthewoods@gmail.com>               *
4
# *                                                                         *
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.                                 *
10
# *                                                                         *
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.                  *
15
# *                                                                         *
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  *
19
# *   USA                                                                   *
20
# *                                                                         *
21
# ***************************************************************************
22

23
import FreeCAD
24
import Path
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
29
import math
30

31
PI = math.pi
32

33

34
class MockTB(object):
35
    def __init__(self, dia):
36
        self.Name = "ToolBit"
37
        self.Label = "ToolBit"
38
        self.Diameter = FreeCAD.Units.Quantity(dia, FreeCAD.Units.Length)
39

40

41
class MockTC(object):
42
    def __init__(self, dia=2):
43
        self.Name = "TC"
44
        self.Label = "TC"
45
        self.Tool = MockTB(dia)
46

47

48
class MockOp(object):
49
    def __init__(self, path, dia=2):
50
        self.Name = "OP"
51
        self.Label = "OP"
52
        self.Path = Path.Path(path)
53
        self.ToolController = MockTC(dia)
54

55

56
class MockFeaturePython(object):
57
    def __init__(self, name):
58
        self.prop = {}
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())
63

64
    def addProperty(self, typ, name, grp=None, desc=None, val=None):
65
        self.prop[name] = (typ, val)
66

67
    def setEditorMode(self, name, mode):
68
        pass
69

70
    def __setattr__(self, name, val):
71
        if name == "prop":
72
            return super().__setattr__(name, val)
73
        self.prop[name] = (self.prop[name][0], val)
74

75
    def __getattr__(self, name):
76
        if name == "prop":
77
            return super().__getattr__(name)
78
        typ, val = self.prop.get(name, (None, None))
79
        if typ is None and val is None:
80
            raise AttributeError
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)
85
        return val
86

87

88
def CreateDressup(path):
89
    op = MockOp(path)
90
    obj = MockFeaturePython("DressupDogbone")
91
    db = Path.Dressup.DogboneII.Proxy(obj, op)
92
    obj.Proxy = db
93
    return obj
94

95

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)
100

101

102
def INSTR(gcode, begin=None):
103
    return MNVR(gcode, begin).instr[0]
104

105

106
def KINK(gcode, begin=None):
107
    maneuver = MNVR(gcode, begin)
108
    if len(maneuver.instr) != 2:
109
        return None
110
    return dogboneII.Kink(maneuver.instr[0], maneuver.instr[1])
111

112

113
class TestDressupDogboneII(PathTestUtils.PathTestBase):
114
    """Unit tests for the DogboneII dressup."""
115

116
    def assertEqualPath(self, path, s):
117
        def cmd2str(cmd):
118
            param = [
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()
121
            ]
122
            return f"{cmd.Name}{''.join(param)}"
123

124
        p = "/".join([cmd2str(cmd) for cmd in path.Commands])
125
        self.assertEqual(p, s)
126

127
    def test00(self):
128
        """Verify adaptive length"""
129

130
        def adaptive(k, a, n):
131
            return Path.Dressup.DogboneII.calc_length_adaptive(k, a, n, n)
132

133
        if True:
134
            # horizontal bones
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)
144

145
        if True:
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)
157

158
        if True:
159
            # dogbones
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)
174

175
    def test01(self):
176
        """Verify nominal length"""
177

178
        def nominal(k, a, n):
179
            return Path.Dressup.DogboneII.calc_length_nominal(k, a, n, 0)
180

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)
190

191
    def test02(self):
192
        """Verify custom length"""
193

194
        def custom(k, a, c):
195
            return Path.Dressup.DogboneII.calc_length_custom(k, a, 0, c)
196

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)
206

207
    def test10(self):
208
        """Verify basic op dressup"""
209

210
        obj = CreateDressup("G1X10/G1Y20")
211
        obj.Incision = Path.Dressup.DogboneII.Incision.Fixed
212
        obj.Style = Path.Dressup.DogboneII.Style.Tbone_H
213

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")
218

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")
223

224
    def test11(self):
225
        """Verify retaining non-move instructions"""
226

227
        obj = CreateDressup("G1X10/(some comment)/G1Y20")
228
        obj.Incision = Path.Dressup.DogboneII.Incision.Fixed
229
        obj.Style = Path.Dressup.DogboneII.Style.Tbone_H
230

231
        # bone on right side
232
        obj.Side = Path.Dressup.DogboneII.Side.Right
233
        obj.Proxy.execute(obj)
234
        self.assertEqualPath(obj.Path, "G1X10/(some comment)/G1X11/G1X10/G1Y20")
235

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")
240

241
    def test20(self):
242
        """Verify bone on plunge moves"""
243

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
248

249
        obj.Proxy.execute(obj)
250
        self.assertEqualPath(
251
            obj.Path,
252
            "G0Z10/G1Z0/G1X10/G1X11/G1X10/G1Y10/G1X11/G1X10/G1X0/G1X-1/G1X0/G1Y0/G1X-1/G1X0/G0Z10",
253
        )
254

255
    def test21(self):
256
        """Verify ignoring plunge moves that don't connect"""
257

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
262

263
        obj.Proxy.execute(obj)
264
        self.assertEqualPath(
265
            obj.Path,
266
            "G0Z10/G1Z0/G1X10/G1X11/G1X10/G1Y10/G1X11/G1X10/G1X0/G1X-1/G1X0/G1Y5/G0Z10",
267
        )
268

269
    def test30(self):
270
        """Verify TBone_V style"""
271

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
275
            if right:
276
                obj.Side = Path.Dressup.DogboneII.Side.Right
277
            else:
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}")
282

283
        # test data with a horizontal lead in
284
        test_data_h = [
285
            # top right quadrant
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),
295
            # top left quadrant
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),
305
        ]
306

307
        for i, (path, out, right) in enumerate(test_data_h):
308
            check_tbone("h", i, path, out, right)
309

310
        # test data with a vertical lead in
311
        test_data_v = [
312
            # top right quadrant
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),
322
            # top left quadrant
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),
332
        ]
333

334
        for i, (path, out, right) in enumerate(test_data_v):
335
            check_tbone("v", i, path, out, right)
336

337
    def test40(self):
338
        """Verify TBone_S style"""
339

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
343
            if right:
344
                obj.Side = Path.Dressup.DogboneII.Side.Right
345
            else:
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}")
350

351
        # short edge m0
352
        test_data_0 = [
353
            # CCW
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),
357
            (
358
                "G1X-10Y10/G1X-30Y-10",
359
                "G1X-10Y10/G1X-9.29Y10.71/G1X-10Y10/G1X-30Y-10",
360
                True,
361
            ),
362
            ("G1X-10/G1Y-20", "G1X-10/G1Y1/G1Y0/G1Y-20", True),
363
            (
364
                "G1X-10Y-10/G1X10Y-30",
365
                "G1X-10Y-10/G1X-10.71Y-9.29/G1X-10Y-10/G1X10Y-30",
366
                True,
367
            ),
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),
370
            # CW
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),
374
            (
375
                "G1X-10Y10/G1X10Y30",
376
                "G1X-10Y10/G1X-10.71Y9.29/G1X-10Y10/G1X10Y30",
377
                False,
378
            ),
379
            ("G1X-10/G1Y20", "G1X-10/G1Y-1/G1Y0/G1Y20", False),
380
            (
381
                "G1X-10Y-10/G1X-30Y10",
382
                "G1X-10Y-10/G1X-9.29Y-10.71/G1X-10Y-10/G1X-30Y10",
383
                False,
384
            ),
385
            ("G1Y-10/G1X-20", "G1Y-10/G1X1/G1X0/G1X-20", False),
386
            (
387
                "G1X10Y-10/G1X-10Y-30",
388
                "G1X10Y-10/G1X10.71Y-9.29/G1X10Y-10/G1X-10Y-30",
389
                False,
390
            ),
391
        ]
392

393
        for i, (path, out, right) in enumerate(test_data_0):
394
            check_tbone_s("0", i, path, out, right)
395

396
        # short edge m1
397
        test_data_1 = [
398
            # CCW
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),
402
            (
403
                "G1X-20Y20/G1X-30Y10",
404
                "G1X-20Y20/G1X-20.71Y20.71/G1X-20Y20/G1X-30Y10",
405
                True,
406
            ),
407
            ("G1X-20/G1Y-10", "G1X-20/G1X-21/G1X-20/G1Y-10", True),
408
            (
409
                "G1X-20Y-20/G1X-10Y-30",
410
                "G1X-20Y-20/G1X-20.71Y-20.71/G1X-20Y-20/G1X-10Y-30",
411
                True,
412
            ),
413
            ("G1Y-20/G1X10", "G1Y-20/G1Y-21/G1Y-20/G1X10", True),
414
            (
415
                "G1X20Y-20/G1X30Y-10",
416
                "G1X20Y-20/G1X20.71Y-20.71/G1X20Y-20/G1X30Y-10",
417
                True,
418
            ),
419
            # CW
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),
423
            (
424
                "G1X-20Y20/G1X-10Y30",
425
                "G1X-20Y20/G1X-20.71Y20.71/G1X-20Y20/G1X-10Y30",
426
                False,
427
            ),
428
            ("G1X-20/G1Y10", "G1X-20/G1X-21/G1X-20/G1Y10", False),
429
            (
430
                "G1X-20Y-20/G1X-30Y-10",
431
                "G1X-20Y-20/G1X-20.71Y-20.71/G1X-20Y-20/G1X-30Y-10",
432
                False,
433
            ),
434
            ("G1Y-20/G1X-10", "G1Y-20/G1Y-21/G1Y-20/G1X-10", False),
435
            (
436
                "G1X20Y-20/G1X10Y-30",
437
                "G1X20Y-20/G1X20.71Y-20.71/G1X20Y-20/G1X10Y-30",
438
                False,
439
            ),
440
        ]
441

442
        for i, (path, out, right) in enumerate(test_data_1):
443
            check_tbone_s("1", i, path, out, right)
444

445
    def test50(self):
446
        """Verify TBone_L style"""
447

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
451
            if right:
452
                obj.Side = Path.Dressup.DogboneII.Side.Right
453
            else:
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}")
458

459
        # long edge m1
460
        test_data_1 = [
461
            # CCW
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),
465
            (
466
                "G1X-10Y10/G1X-30Y-10",
467
                "G1X-10Y10/G1X-10.71Y10.71/G1X-10Y10/G1X-30Y-10",
468
                True,
469
            ),
470
            ("G1X-10/G1Y-20", "G1X-10/G1X-11/G1X-10/G1Y-20", True),
471
            (
472
                "G1X-10Y-10/G1X10Y-30",
473
                "G1X-10Y-10/G1X-10.71Y-10.71/G1X-10Y-10/G1X10Y-30",
474
                True,
475
            ),
476
            ("G1Y-10/G1X20", "G1Y-10/G1Y-11/G1Y-10/G1X20", True),
477
            (
478
                "G1X10Y-10/G1X30Y10",
479
                "G1X10Y-10/G1X10.71Y-10.71/G1X10Y-10/G1X30Y10",
480
                True,
481
            ),
482
            # CW
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),
486
            (
487
                "G1X-10Y10/G1X10Y30",
488
                "G1X-10Y10/G1X-10.71Y10.71/G1X-10Y10/G1X10Y30",
489
                False,
490
            ),
491
            ("G1X-10/G1Y20", "G1X-10/G1X-11/G1X-10/G1Y20", False),
492
            (
493
                "G1X-10Y-10/G1X-30Y10",
494
                "G1X-10Y-10/G1X-10.71Y-10.71/G1X-10Y-10/G1X-30Y10",
495
                False,
496
            ),
497
            ("G1Y-10/G1X-20", "G1Y-10/G1Y-11/G1Y-10/G1X-20", False),
498
            (
499
                "G1X10Y-10/G1X-10Y-30",
500
                "G1X10Y-10/G1X10.71Y-10.71/G1X10Y-10/G1X-10Y-30",
501
                False,
502
            ),
503
        ]
504

505
        for i, (path, out, right) in enumerate(test_data_1):
506
            check_tbone_l("1", i, path, out, right)
507

508
        # long edge m0
509
        test_data_0 = [
510
            # CCW
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),
514
            (
515
                "G1X-20Y20/G1X-30Y10",
516
                "G1X-20Y20/G1X-19.29Y20.71/G1X-20Y20/G1X-30Y10",
517
                True,
518
            ),
519
            ("G1X-20/G1Y-10", "G1X-20/G1Y1/G1Y0/G1Y-10", True),
520
            (
521
                "G1X-20Y-20/G1X-10Y-30",
522
                "G1X-20Y-20/G1X-20.71Y-19.29/G1X-20Y-20/G1X-10Y-30",
523
                True,
524
            ),
525
            ("G1Y-20/G1X10", "G1Y-20/G1X-1/G1X0/G1X10", True),
526
            (
527
                "G1X20Y-20/G1X30Y-10",
528
                "G1X20Y-20/G1X19.29Y-20.71/G1X20Y-20/G1X30Y-10",
529
                True,
530
            ),
531
            # CW
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),
535
            (
536
                "G1X-20Y20/G1X-10Y30",
537
                "G1X-20Y20/G1X-20.71Y19.29/G1X-20Y20/G1X-10Y30",
538
                False,
539
            ),
540
            ("G1X-20/G1Y10", "G1X-20/G1Y-1/G1Y0/G1Y10", False),
541
            (
542
                "G1X-20Y-20/G1X-30Y-10",
543
                "G1X-20Y-20/G1X-19.29Y-20.71/G1X-20Y-20/G1X-30Y-10",
544
                False,
545
            ),
546
            ("G1Y-20/G1X-10", "G1Y-20/G1X1/G1X0/G1X-10", False),
547
            (
548
                "G1X20Y-20/G1X10Y-30",
549
                "G1X20Y-20/G1X20.71Y-19.29/G1X20Y-20/G1X10Y-30",
550
                False,
551
            ),
552
        ]
553

554
        for i, (path, out, right) in enumerate(test_data_0):
555
            check_tbone_l("0", i, path, out, right)
556

557
    def test60(self):
558
        """Verify Dogbone style"""
559

560
        obj = CreateDressup("G1X10/G1Y20")
561
        obj.Incision = Path.Dressup.DogboneII.Incision.Fixed
562
        obj.Side = Path.Dressup.DogboneII.Side.Right
563

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")
567

568
    def test70(self):
569
        """Verify custom length."""
570

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
574

575
        obj.Incision = Path.Dressup.DogboneII.Incision.Custom
576
        obj.Custom = 3
577
        obj.Proxy.execute(obj)
578
        self.assertEqualPath(
579
            obj.Path,
580
            "G0Z10/G1Z0/G1X10/G1X13/G1X10/G1Y10/G1X13/G1X10/G1X0/G1X-3/G1X0/G1Y0/G1X-3/G1X0/G0Z10",
581
        )
582

583
        obj.Custom = 2
584
        obj.Proxy.execute(obj)
585
        self.assertEqualPath(
586
            obj.Path,
587
            "G0Z10/G1Z0/G1X10/G1X12/G1X10/G1Y10/G1X12/G1X10/G1X0/G1X-2/G1X0/G1Y0/G1X-2/G1X0/G0Z10",
588
        )
589

590
    def test80(self):
591
        """Verify adaptive length."""
592

593
        obj = CreateDressup("G1X10/G1Y20")
594
        obj.Incision = Path.Dressup.DogboneII.Incision.Adaptive
595
        obj.Side = Path.Dressup.DogboneII.Side.Right
596

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")
600

601
    def test81(self):
602
        """Verify adaptive length II."""
603

604
        obj = CreateDressup("G1X10/G1X20Y20")
605
        obj.Incision = Path.Dressup.DogboneII.Incision.Adaptive
606
        obj.Side = Path.Dressup.DogboneII.Side.Right
607

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")
611

612
    def test90(self):
613
        """Verify dogbone blacklist"""
614

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"
623
        )
624
        return obj
625

626
    def test91(self):
627
        """Verify dogbone on dogbone"""
628

629
        obj = self.test90()
630

631
        obj2 = MockFeaturePython("DressupDogbone001")
632
        db2 = Path.Dressup.DogboneII.Proxy(obj2, obj)
633
        obj2.Proxy = db2
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(
640
            obj2.Path,
641
            "G0Z10/G1Z0/G1X10/G1X11/G1X10/G1Y10/G1X11/G1X10/G1X0/G1X-1/G1X0/G1Y0/G1X-1/G1X0/G0Z10",
642
        )
643

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.