| | |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | import FreeCAD |
| | import Part |
| | import Path.Op.Profile as PathProfile |
| | import Path.Main.Job as PathJob |
| | from CAMTests.PathTestUtils import PathTestBase |
| | from CAMTests.TestPathAdaptive import getGcodeMoves |
| |
|
| | if FreeCAD.GuiUp: |
| | import Path.Main.Gui.Job as PathJobGui |
| | import Path.Op.Gui.Profile as PathProfileGui |
| |
|
| |
|
| | class TestPathProfile(PathTestBase): |
| | """Unit tests for the Adaptive operation.""" |
| |
|
| | @classmethod |
| | def setUpClass(cls): |
| | """setUpClass()... |
| | This method is called upon instantiation of this test class. Add code and objects here |
| | that are needed for the duration of the test() methods in this class. In other words, |
| | set up the 'global' test environment here; use the `setUp()` method to set up a 'local' |
| | test environment. |
| | This method does not have access to the class `self` reference, but it |
| | is able to call static methods within this same class. |
| | """ |
| | cls.needsInit = True |
| |
|
| | @classmethod |
| | def initClass(cls): |
| | |
| | cls.needsInit = False |
| | FreeCAD.ConfigSet("SuppressRecomputeRequiredDialog", "True") |
| | cls.doc = FreeCAD.open(FreeCAD.getHomePath() + "Mod/CAM/CAMTests/test_profile.fcstd") |
| | FreeCAD.ConfigSet("SuppressRecomputeRequiredDialog", "") |
| |
|
| | |
| | cls.job = PathJob.Create("Job", [cls.doc.Body], None) |
| | cls.job.GeometryTolerance.Value = 0.001 |
| | if FreeCAD.GuiUp: |
| | cls.job.ViewObject.Proxy = PathJobGui.ViewProvider(cls.job.ViewObject) |
| |
|
| | |
| | cls.prototype = PathProfile.Create("Profile") |
| | cls.prototype.Base = [(cls.doc.Body, ["Face18"])] |
| | cls.prototype.Label = "Prototype" |
| | _addViewProvider(cls.prototype) |
| |
|
| | cls.doc.recompute() |
| |
|
| | @classmethod |
| | def tearDownClass(cls): |
| | """tearDownClass()... |
| | This method is called prior to destruction of this test class. Add code and objects here |
| | that cleanup the test environment after the test() methods in this class have been executed. |
| | This method does not have access to the class `self` reference. This method |
| | is able to call static methods within this same class. |
| | """ |
| | |
| |
|
| | |
| | if not cls.needsInit: |
| | FreeCAD.closeDocument(cls.doc.Name) |
| |
|
| | |
| | def setUp(self): |
| | """setUp()... |
| | This method is called prior to each `test()` method. Add code and objects here |
| | that are needed for multiple `test()` methods. |
| | """ |
| | if self.needsInit: |
| | self.initClass() |
| |
|
| | def tearDown(self): |
| | """tearDown()... |
| | This method is called after each test() method. Add cleanup instructions here. |
| | Such cleanup instructions will likely undo those in the setUp() method. |
| | """ |
| | pass |
| |
|
| | |
| | def test00(self): |
| | """test00() Empty test.""" |
| | return |
| |
|
| | def test01(self): |
| | """test01() Verify path generated on Face18, outside, with tool compensation.""" |
| |
|
| | |
| | profile = PathProfile.Create("Profile1") |
| | profile.Base = [(self.doc.Body, ["Face18"])] |
| | profile.Label = "test01+" |
| | profile.Comment = ( |
| | "test01() Verify path generated on Face18, outside, with tool compensation." |
| | ) |
| |
|
| | |
| | |
| | profile.processCircles = True |
| | profile.processHoles = True |
| | profile.UseComp = True |
| | profile.Direction = "CW" |
| | _addViewProvider(profile) |
| | self.doc.recompute() |
| |
|
| | moves = getGcodeMoves(profile.Path.Commands, includeRapids=False) |
| | operationMoves = "; ".join(moves) |
| | |
| |
|
| | expected_moves = ( |
| | "G1 X16.47 Y16.47 Z10.0; G3 I-2.48 J-2.48 K0.0 X13.93 Y17.5 Z10.0; " |
| | "G1 X-13.93 Y17.5 Z10.0; G3 I-0.06 J-3.51 K0.0 X-17.5 Y13.93 Z10.0; " |
| | "G1 X-17.5 Y-13.93 Z10.0; G3 I3.51 J-0.06 K0.0 X-13.93 Y-17.5 Z10.0; " |
| | "G1 X13.93 Y-17.5 Z10.0; G3 I0.06 J3.51 K0.0 X17.5 Y-13.93 Z10.0; " |
| | "G1 X17.5 Y13.93 Z10.0; G3 I-3.51 J0.06 K0.0 X16.47 Y16.47 Z10.0; " |
| | "G1 X23.54 Y23.54 Z10.0; G2 I-9.55 J-9.55 K0.0 X27.5 Y14.0 Z10.0; " |
| | "G1 X27.5 Y-14.0 Z10.0; G2 I-13.5 J0.0 K0.0 X14.0 Y-27.5 Z10.0; " |
| | "G1 X-14.0 Y-27.5 Z10.0; G2 I0.0 J13.5 K0.0 X-27.5 Y-14.0 Z10.0; " |
| | "G1 X-27.5 Y14.0 Z10.0; G2 I13.5 J-0.0 K0.0 X-14.0 Y27.5 Z10.0; " |
| | "G1 X14.0 Y27.5 Z10.0; G2 I-0.0 J-13.5 K0.0 X23.54 Y23.54 Z10.0" |
| | ) |
| | self.assertTrue( |
| | expected_moves == operationMoves, |
| | "expected_moves: {}\noperationMoves: {}".format(expected_moves, operationMoves), |
| | ) |
| |
|
| | def test02(self): |
| | """test02() Verify path generated on Face18, outside, without compensation.""" |
| |
|
| | |
| | profile = PathProfile.Create("Profile2") |
| | profile.Base = [(self.doc.Body, ["Face18"])] |
| | profile.Label = "test02+" |
| | profile.Comment = "test02() Verify path generated on Face18, outside, without compensation." |
| |
|
| | |
| | |
| | profile.processCircles = True |
| | profile.processHoles = True |
| | profile.UseComp = False |
| | profile.Direction = "CW" |
| | _addViewProvider(profile) |
| | self.doc.recompute() |
| |
|
| | moves = getGcodeMoves(profile.Path.Commands, includeRapids=False) |
| | operationMoves = "; ".join(moves) |
| | |
| |
|
| | expected_moves = ( |
| | "G1 X18.24 Y18.24 Z10.0; G3 I-4.24 J-4.24 K0.0 X14.0 Y20.0 Z10.0; " |
| | "G1 X-14.0 Y20.0 Z10.0; G3 I0.0 J-6.0 K0.0 X-20.0 Y14.0 Z10.0; " |
| | "G1 X-20.0 Y-14.0 Z10.0; G3 I6.0 J0.0 K0.0 X-14.0 Y-20.0 Z10.0; " |
| | "G1 X14.0 Y-20.0 Z10.0; G3 I-0.0 J6.0 K0.0 X20.0 Y-14.0 Z10.0; " |
| | "G1 X20.0 Y14.0 Z10.0; G3 I-6.0 J-0.0 K0.0 X18.24 Y18.24 Z10.0; " |
| | "G1 X21.78 Y21.78 Z10.0; G2 I-7.78 J-7.78 K0.0 X25.0 Y14.0 Z10.0; " |
| | "G1 X25.0 Y-14.0 Z10.0; G2 I-11.0 J0.0 K0.0 X14.0 Y-25.0 Z10.0; " |
| | "G1 X-14.0 Y-25.0 Z10.0; G2 I0.0 J11.0 K0.0 X-25.0 Y-14.0 Z10.0; " |
| | "G1 X-25.0 Y14.0 Z10.0; G2 I11.0 J-0.0 K0.0 X-14.0 Y25.0 Z10.0; " |
| | "G1 X14.0 Y25.0 Z10.0; G2 I-0.0 J-11.0 K0.0 X21.78 Y21.78 Z10.0" |
| | ) |
| |
|
| | self.assertTrue( |
| | expected_moves == operationMoves, |
| | "expected_moves: {}\noperationMoves: {}".format(expected_moves, operationMoves), |
| | ) |
| |
|
| | def test03(self): |
| | """test03() Verify path generated on Face18, outside, |
| | with compensation and extra offset -radius.""" |
| |
|
| | |
| | profile = PathProfile.Create("Profile3") |
| | profile.Base = [(self.doc.Body, ["Face18"])] |
| | profile.Label = "test03+" |
| | profile.Comment = ( |
| | "test03() Verify path generated on Face4, " "with compensation and extra offset -radius" |
| | ) |
| |
|
| | |
| | |
| | profile.processCircles = True |
| | profile.processHoles = True |
| | profile.UseComp = True |
| | profile.Direction = "CW" |
| | profile.OffsetExtra = -profile.OpToolDiameter / 2.0 |
| | _addViewProvider(profile) |
| | self.doc.recompute() |
| |
|
| | moves = getGcodeMoves(profile.Path.Commands, includeRapids=False) |
| | operationMoves = "; ".join(moves) |
| | |
| |
|
| | expected_moves = ( |
| | "G1 X18.24 Y18.24 Z10.0; G3 I-4.24 J-4.24 K0.0 X14.0 Y20.0 Z10.0; " |
| | "G1 X-14.0 Y20.0 Z10.0; G3 I0.0 J-6.0 K0.0 X-20.0 Y14.0 Z10.0; " |
| | "G1 X-20.0 Y-14.0 Z10.0; G3 I6.0 J0.0 K0.0 X-14.0 Y-20.0 Z10.0; " |
| | "G1 X14.0 Y-20.0 Z10.0; G3 I-0.0 J6.0 K0.0 X20.0 Y-14.0 Z10.0; " |
| | "G1 X20.0 Y14.0 Z10.0; G3 I-6.0 J-0.0 K0.0 X18.24 Y18.24 Z10.0; " |
| | "G1 X21.78 Y21.78 Z10.0; G2 I-7.78 J-7.78 K0.0 X25.0 Y14.0 Z10.0; " |
| | "G1 X25.0 Y-14.0 Z10.0; G2 I-11.0 J0.0 K0.0 X14.0 Y-25.0 Z10.0; " |
| | "G1 X-14.0 Y-25.0 Z10.0; G2 I0.0 J11.0 K0.0 X-25.0 Y-14.0 Z10.0; " |
| | "G1 X-25.0 Y14.0 Z10.0; G2 I11.0 J-0.0 K0.0 X-14.0 Y25.0 Z10.0; " |
| | "G1 X14.0 Y25.0 Z10.0; G2 I-0.0 J-11.0 K0.0 X21.78 Y21.78 Z10.0" |
| | ) |
| |
|
| | self.assertTrue( |
| | expected_moves == operationMoves, |
| | "expected_moves: {}\noperationMoves: {}".format(expected_moves, operationMoves), |
| | ) |
| |
|
| |
|
| | def _addViewProvider(profileOp): |
| | if FreeCAD.GuiUp: |
| | PathOpGui = PathProfileGui.PathOpGui |
| | cmdRes = PathProfileGui.Command.res |
| | profileOp.ViewObject.Proxy = PathOpGui.ViewProvider(profileOp.ViewObject, cmdRes) |
| |
|