123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391 |
- # Copyright (c) 2020 Ultimaker B.V.
- # Cura is released under the terms of the LGPLv3 or higher.
- from unittest.mock import MagicMock, patch
- import pytest
- from UM.Math.Polygon import Polygon
- from UM.Math.Vector import Vector
- from cura.BuildVolume import BuildVolume, PRIME_CLEARANCE
- import numpy
- @pytest.fixture
- def build_volume() -> BuildVolume:
- mocked_application = MagicMock()
- mocked_platform = MagicMock(name="platform")
- with patch("cura.BuildVolume.Platform", mocked_platform):
- return BuildVolume(mocked_application)
- def test_buildVolumeSetSizes(build_volume):
- build_volume.setWidth(10)
- assert build_volume.getDiagonalSize() == 10
- build_volume.setWidth(0)
- build_volume.setHeight(100)
- assert build_volume.getDiagonalSize() == 100
- build_volume.setHeight(0)
- build_volume.setDepth(200)
- assert build_volume.getDiagonalSize() == 200
- def test_buildMesh(build_volume):
- mesh = build_volume._buildMesh(0, 100, 0, 100, 0, 100, 1)
- result_vertices = numpy.array([[0., 0., 0.], [100., 0., 0.], [0., 0., 0.], [0., 100., 0.], [0., 100., 0.], [100., 100., 0.], [100., 0., 0.], [100., 100., 0.], [0., 0., 100.], [100., 0., 100.], [0., 0., 100.], [0., 100., 100.], [0., 100., 100.], [100., 100., 100.], [100., 0., 100.], [100., 100., 100.], [0., 0., 0.], [0., 0., 100.], [100., 0., 0.], [100., 0., 100.], [0., 100., 0.], [0., 100., 100.], [100., 100., 0.], [100., 100., 100.]], dtype=numpy.float32)
- assert numpy.array_equal(result_vertices, mesh.getVertices())
- def test_buildGridMesh(build_volume):
- mesh = build_volume._buildGridMesh(0, 100, 0, 100, 0, 100, 1)
- result_vertices = numpy.array([[0., -1., 0.], [100., -1., 100.], [100., -1., 0.], [0., -1., 0.], [0., -1., 100.], [100., -1., 100.]])
- assert numpy.array_equal(result_vertices, mesh.getVertices())
- def test_clamp(build_volume):
- assert build_volume._clamp(0, 0, 200) == 0
- assert build_volume._clamp(0, -200, 200) == 0
- assert build_volume._clamp(300, -200, 200) == 200
- class TestCalculateBedAdhesionSize:
- setting_property_dict = {"adhesion_type": { "value": "brim"},
- "skirt_brim_line_width": {"value": 0},
- "initial_layer_line_width_factor": {"value": 0},
- "brim_line_count": {"value": 0},
- "machine_width": {"value": 200},
- "machine_depth": {"value": 200},
- "skirt_line_count": {"value": 0},
- "skirt_gap": {"value": 0},
- "raft_margin": {"value": 0}
- }
- def getPropertySideEffect(*args, **kwargs):
- properties = TestCalculateBedAdhesionSize.setting_property_dict.get(args[1])
- if properties:
- return properties.get(args[2])
- def createAndSetGlobalStack(self, build_volume):
- mocked_stack = MagicMock(name = "mocked_stack")
- mocked_stack.getProperty = MagicMock(side_effect=self.getPropertySideEffect)
- mocked_extruder = MagicMock(name = "mocked_extruder")
- mocked_extruder.getProperty = MagicMock(side_effect=self.getPropertySideEffect)
- mocked_stack.extruderList = [mocked_extruder]
- build_volume._global_container_stack = mocked_stack
- def test_noGlobalStack(self, build_volume: BuildVolume):
- assert build_volume._calculateBedAdhesionSize([]) is None
- @pytest.mark.parametrize("setting_dict, result", [
- ({}, 0),
- ({"adhesion_type": { "value": "skirt"}}, 0),
- ({"adhesion_type": { "value": "raft"}}, 0),
- ({"adhesion_type": { "value": "none"}}, 0),
- ({"adhesion_type": { "value": "skirt"}, "skirt_line_count": {"value": 2}, "initial_layer_line_width_factor": {"value": 1}, "skirt_brim_line_width": {"value": 2}}, 0.02),
- # Even though it's marked as skirt, it should behave as a brim as the prime tower has a brim (skirt line count is still at 0!)
- ({"adhesion_type": { "value": "skirt"}, "prime_tower_brim_enable": {"value": True}, "skirt_brim_line_width": {"value": 2}, "initial_layer_line_width_factor": {"value": 3}}, -0.06),
- ({"brim_line_count": {"value": 1}, "skirt_brim_line_width": {"value": 2}, "initial_layer_line_width_factor": {"value": 3}}, 0),
- ({"brim_line_count": {"value": 2}, "skirt_brim_line_width": {"value": 2}, "initial_layer_line_width_factor": {"value": 3}}, 0.06),
- ({"brim_line_count": {"value": 9000000}, "skirt_brim_line_width": {"value": 90000}, "initial_layer_line_width_factor": {"value": 9000}}, 100), # Clamped at half the max size of buildplate
- ])
- def test_singleExtruder(self, build_volume: BuildVolume, setting_dict, result):
- self.createAndSetGlobalStack(build_volume)
- patched_dictionary = self.setting_property_dict.copy()
- patched_dictionary.update(setting_dict)
- patched_dictionary.update({"adhesion_extruder_nr": {"value": 0}})
- with patch.dict(self.setting_property_dict, patched_dictionary):
- assert build_volume._calculateBedAdhesionSize([]) == result
- def test_unknownBedAdhesion(self, build_volume: BuildVolume):
- self.createAndSetGlobalStack(build_volume)
- patched_dictionary = self.setting_property_dict.copy()
- patched_dictionary.update({"adhesion_type": { "value": "OMGZOMGBBQ"}})
- with patch.dict(self.setting_property_dict, patched_dictionary):
- with pytest.raises(Exception):
- build_volume._calculateBedAdhesionSize([])
- class TestComputeDisallowedAreasStatic:
- setting_property_dict = {"machine_disallowed_areas": {"value": [[[-200, 112.5], [ -82, 112.5], [ -84, 102.5], [-115, 102.5]]]},
- "machine_width": {"value": 200},
- "machine_depth": {"value": 200},
- }
- def getPropertySideEffect(*args, **kwargs):
- properties = TestComputeDisallowedAreasStatic.setting_property_dict.get(args[1])
- if properties:
- return properties.get(args[2])
- def test_computeDisallowedAreasStaticNoExtruder(self, build_volume: BuildVolume):
- mocked_stack = MagicMock()
- mocked_stack.getProperty = MagicMock(side_effect=self.getPropertySideEffect)
- build_volume._global_container_stack = mocked_stack
- assert build_volume._computeDisallowedAreasStatic(0, []) == {}
- def test_computeDisalowedAreasStaticSingleExtruder(self, build_volume: BuildVolume):
- mocked_stack = MagicMock()
- mocked_stack.getProperty = MagicMock(side_effect=self.getPropertySideEffect)
- mocked_extruder = MagicMock()
- mocked_extruder.getProperty = MagicMock(side_effect=self.getPropertySideEffect)
- mocked_extruder.getId = MagicMock(return_value = "zomg")
- build_volume._global_container_stack = mocked_stack
- with patch("cura.Settings.ExtruderManager.ExtruderManager.getInstance"):
- result = build_volume._computeDisallowedAreasStatic(0, [mocked_extruder])
- assert result == {"zomg": [Polygon([[-84.0, 102.5], [-115.0, 102.5], [-200.0, 112.5], [-82.0, 112.5]])]}
- def test_computeDisalowedAreasMutliExtruder(self, build_volume):
- mocked_stack = MagicMock()
- mocked_stack.getProperty = MagicMock(side_effect=self.getPropertySideEffect)
- mocked_extruder = MagicMock()
- mocked_extruder.getProperty = MagicMock(side_effect=self.getPropertySideEffect)
- mocked_extruder.getId = MagicMock(return_value="zomg")
- extruder_manager = MagicMock()
- extruder_manager.getActiveExtruderStacks = MagicMock(return_value = [mocked_stack])
- build_volume._global_container_stack = mocked_stack
- with patch("cura.Settings.ExtruderManager.ExtruderManager.getInstance", MagicMock(return_value = extruder_manager)):
- result = build_volume._computeDisallowedAreasStatic(0, [mocked_extruder])
- assert result == {"zomg": [Polygon([[-84.0, 102.5], [-115.0, 102.5], [-200.0, 112.5], [-82.0, 112.5]])]}
- class TestUpdateRaftThickness:
- setting_property_dict = {"raft_base_thickness": {"value": 1},
- "raft_interface_thickness": {"value": 1},
- "raft_surface_layers": {"value": 1},
- "raft_surface_thickness": {"value": 1},
- "raft_airgap": {"value": 1},
- "layer_0_z_overlap": {"value": 1},
- "adhesion_type": { "value": "raft"}}
- def getPropertySideEffect(*args, **kwargs):
- properties = TestUpdateRaftThickness.setting_property_dict.get(args[1])
- if properties:
- return properties.get(args[2])
- def createMockedStack(self):
- mocked_global_stack = MagicMock(name = "mocked_global_stack")
- mocked_global_stack.getProperty = MagicMock(side_effect = self.getPropertySideEffect)
- extruder_stack = MagicMock()
- return mocked_global_stack
- def test_simple(self, build_volume: BuildVolume):
- build_volume.raftThicknessChanged = MagicMock()
- mocked_global_stack = self.createMockedStack()
- build_volume._global_container_stack = mocked_global_stack
- assert build_volume.getRaftThickness() == 0
- build_volume._updateRaftThickness()
- assert build_volume.getRaftThickness() == 3
- assert build_volume.raftThicknessChanged.emit.call_count == 1
- def test_adhesionIsNotRaft(self, build_volume: BuildVolume):
- patched_dictionary = self.setting_property_dict.copy()
- patched_dictionary["adhesion_type"] = {"value": "not_raft"}
- mocked_global_stack = self.createMockedStack()
- build_volume._global_container_stack = mocked_global_stack
- assert build_volume.getRaftThickness() == 0
- with patch.dict(self.setting_property_dict, patched_dictionary):
- build_volume._updateRaftThickness()
- assert build_volume.getRaftThickness() == 0
- def test_noGlobalStack(self, build_volume: BuildVolume):
- build_volume.raftThicknessChanged = MagicMock()
- assert build_volume.getRaftThickness() == 0
- build_volume._updateRaftThickness()
- assert build_volume.getRaftThickness() == 0
- assert build_volume.raftThicknessChanged.emit.call_count == 0
- class TestComputeDisallowedAreasPrimeBlob:
- setting_property_dict = {"machine_width": {"value": 50},
- "machine_depth": {"value": 100},
- "prime_blob_enable": {"value": True},
- "extruder_prime_pos_x": {"value": 25},
- "extruder_prime_pos_y": {"value": 50},
- "machine_center_is_zero": {"value": True},
- }
- def getPropertySideEffect(*args, **kwargs):
- properties = TestComputeDisallowedAreasPrimeBlob.setting_property_dict.get(args[1])
- if properties:
- return properties.get(args[2])
- def test_noGlobalContainer(self, build_volume: BuildVolume):
- # No global container and no extruders, so we expect no blob areas
- assert build_volume._computeDisallowedAreasPrimeBlob(12, []) == {}
- def test_noExtruders(self, build_volume: BuildVolume):
- mocked_stack = MagicMock()
- mocked_stack.getProperty = MagicMock(side_effect=self.getPropertySideEffect)
- build_volume._global_container_stack = mocked_stack
- # No extruders, so still expect that we get no area
- assert build_volume._computeDisallowedAreasPrimeBlob(12, []) == {}
- def test_singleExtruder(self, build_volume: BuildVolume):
- mocked_global_stack = MagicMock(name = "mocked_global_stack")
- mocked_global_stack.getProperty = MagicMock(side_effect=self.getPropertySideEffect)
- mocked_extruder_stack = MagicMock(name = "mocked_extruder_stack")
- mocked_extruder_stack.getId = MagicMock(return_value = "0")
- mocked_extruder_stack.getProperty = MagicMock(side_effect=self.getPropertySideEffect)
- build_volume._global_container_stack = mocked_global_stack
- # Create a polygon that should be the result
- resulting_polygon = Polygon.approximatedCircle(PRIME_CLEARANCE)
- # Since we want a blob of size 12;
- resulting_polygon = resulting_polygon.getMinkowskiHull(Polygon.approximatedCircle(12))
- # In the The translation result is 25, -50 (due to the settings used)
- resulting_polygon = resulting_polygon.translate(25, -50)
- assert build_volume._computeDisallowedAreasPrimeBlob(12, [mocked_extruder_stack]) == {"0": [resulting_polygon]}
- class TestCalculateExtraZClearance:
- setting_property_dict = {"retraction_hop": {"value": 12},
- "retraction_hop_enabled": {"value": True}}
- def getPropertySideEffect(*args, **kwargs):
- properties = TestCalculateExtraZClearance.setting_property_dict.get(args[1])
- if properties:
- return properties.get(args[2])
- def test_noContainerStack(self, build_volume: BuildVolume):
- assert build_volume._calculateExtraZClearance([]) == 0
- def test_withRetractionHop(self, build_volume: BuildVolume):
- mocked_global_stack = MagicMock(name="mocked_global_stack")
- mocked_extruder = MagicMock()
- mocked_extruder.getProperty = MagicMock(side_effect=self.getPropertySideEffect)
- build_volume._global_container_stack = mocked_global_stack
- # It should be 12 because we have the hop enabled and the hop distance is set to 12
- assert build_volume._calculateExtraZClearance([mocked_extruder]) == 12
- def test_withoutRetractionHop(self, build_volume: BuildVolume):
- mocked_global_stack = MagicMock(name="mocked_global_stack")
- mocked_extruder = MagicMock()
- mocked_extruder.getProperty = MagicMock(side_effect=self.getPropertySideEffect)
- build_volume._global_container_stack = mocked_global_stack
- patched_dictionary = self.setting_property_dict.copy()
- patched_dictionary["retraction_hop_enabled"] = {"value": False}
- with patch.dict(self.setting_property_dict, patched_dictionary):
- # It should be 12 because we have the hop enabled and the hop distance is set to 12
- assert build_volume._calculateExtraZClearance([mocked_extruder]) == 0
- class TestRebuild:
- def test_zeroWidthHeightDepth(self, build_volume: BuildVolume):
- build_volume.rebuild()
- assert build_volume.getMeshData() is None
- def test_engineIsNotRead(self, build_volume: BuildVolume):
- build_volume.setWidth(10)
- build_volume.setHeight(10)
- build_volume.setDepth(10)
- build_volume.rebuild()
- assert build_volume.getMeshData() is None
- def test_noGlobalStack(self, build_volume: BuildVolume):
- build_volume.setWidth(10)
- build_volume.setHeight(10)
- build_volume.setDepth(10)
- # Fake the the "engine is created callback"
- build_volume._onEngineCreated()
- build_volume.rebuild()
- assert build_volume.getMeshData() is None
- def test_updateBoundingBox(self, build_volume: BuildVolume):
- build_volume.setWidth(10)
- build_volume.setHeight(10)
- build_volume.setDepth(10)
- mocked_global_stack = MagicMock()
- build_volume._global_container_stack = mocked_global_stack
- build_volume.getEdgeDisallowedSize = MagicMock(return_value = 0)
- build_volume.updateNodeBoundaryCheck = MagicMock()
- # Fake the the "engine is created callback"
- build_volume._onEngineCreated()
- build_volume.rebuild()
- bounding_box = build_volume.getBoundingBox()
- assert bounding_box.minimum == Vector(-5.0, -1.0, -5.0)
- assert bounding_box.maximum == Vector(5.0, 10.0, 5.0)
- class TestUpdateMachineSizeProperties:
- setting_property_dict = {"machine_width": {"value": 50},
- "machine_depth": {"value": 100},
- "machine_height": {"value": 200},
- "machine_shape": {"value": "DERP!"}}
- def getPropertySideEffect(*args, **kwargs):
- properties = TestUpdateMachineSizeProperties.setting_property_dict.get(args[1])
- if properties:
- return properties.get(args[2])
- def test_noGlobalStack(self, build_volume: BuildVolume):
- build_volume._updateMachineSizeProperties()
- assert build_volume._width == 0
- assert build_volume._height == 0
- assert build_volume._depth == 0
- assert build_volume._shape == ""
- def test_happy(self, build_volume: BuildVolume):
- mocked_global_stack = MagicMock(name="mocked_global_stack")
- mocked_global_stack.getProperty = MagicMock(side_effect=self.getPropertySideEffect)
- build_volume._global_container_stack = mocked_global_stack
- build_volume._updateMachineSizeProperties()
- assert build_volume._width == 50
- assert build_volume._height == 200
- assert build_volume._depth == 100
- assert build_volume._shape == "DERP!"
- class TestGetEdgeDisallowedSize:
- setting_property_dict = {}
- bed_adhesion_size = 1
- @pytest.fixture()
- def build_volume(self, build_volume):
- build_volume._calculateBedAdhesionSize = MagicMock(return_value = 1)
- return build_volume
- def getPropertySideEffect(*args, **kwargs):
- properties = TestGetEdgeDisallowedSize.setting_property_dict.get(args[1])
- if properties:
- return properties.get(args[2])
- def createMockedStack(self):
- mocked_global_stack = MagicMock(name="mocked_global_stack")
- mocked_global_stack.getProperty = MagicMock(side_effect=self.getPropertySideEffect)
- return mocked_global_stack
- def test_noGlobalContainer(self, build_volume: BuildVolume):
- assert build_volume.getEdgeDisallowedSize() == 0
- def test_unknownAdhesion(self, build_volume: BuildVolume):
- build_volume._global_container_stack = self.createMockedStack()
- with patch("cura.Settings.ExtruderManager.ExtruderManager.getInstance"):
- #with pytest.raises(Exception):
- # Since we don't have any adhesion set, this should break.
- build_volume.getEdgeDisallowedSize()
- def test_oneAtATime(self, build_volume: BuildVolume):
- build_volume._global_container_stack = self.createMockedStack()
- with patch("cura.Settings.ExtruderManager.ExtruderManager.getInstance"):
- with patch.dict(self.setting_property_dict, {"print_sequence": {"value": "one_at_a_time"}}):
- assert build_volume.getEdgeDisallowedSize() == 0.1
|