diff --git a/cura/BuildVolume.py b/cura/BuildVolume.py index 37a2a9895e..0bfbe2b1d5 100755 --- a/cura/BuildVolume.py +++ b/cura/BuildVolume.py @@ -28,10 +28,11 @@ import numpy import math import copy -from typing import List, Optional, TYPE_CHECKING, Any, Set, cast, Iterable +from typing import List, Optional, TYPE_CHECKING, Any, Set, cast, Iterable, Dict if TYPE_CHECKING: from cura.CuraApplication import CuraApplication + from cura.Settings.ExtruderStack import ExtruderStack # Radius of disallowed area in mm around prime. I.e. how much distance to keep from prime position. PRIME_CLEARANCE = 6.5 @@ -868,9 +869,10 @@ class BuildVolume(SceneNode): # \param used_extruders The extruder stacks to generate disallowed areas # for. # \return A dictionary with for each used extruder ID the prime areas. - def _computeDisallowedAreasPrimeBlob(self, border_size, used_extruders): - result = {} - + def _computeDisallowedAreasPrimeBlob(self, border_size: float, used_extruders: List["ExtruderStack"]) -> Dict[str, List[Polygon]]: + result = {} # type: Dict[str, List[Polygon]] + if not self._global_container_stack: + return result machine_width = self._global_container_stack.getProperty("machine_width", "value") machine_depth = self._global_container_stack.getProperty("machine_depth", "value") for extruder in used_extruders: @@ -878,13 +880,13 @@ class BuildVolume(SceneNode): prime_x = extruder.getProperty("extruder_prime_pos_x", "value") prime_y = -extruder.getProperty("extruder_prime_pos_y", "value") - #Ignore extruder prime position if it is not set or if blob is disabled + # Ignore extruder prime position if it is not set or if blob is disabled if (prime_x == 0 and prime_y == 0) or not prime_blob_enabled: result[extruder.getId()] = [] continue if not self._global_container_stack.getProperty("machine_center_is_zero", "value"): - prime_x = prime_x - machine_width / 2 #Offset by half machine_width and _depth to put the origin in the front-left. + prime_x = prime_x - machine_width / 2 # Offset by half machine_width and _depth to put the origin in the front-left. prime_y = prime_y + machine_depth / 2 prime_polygon = Polygon.approximatedCircle(PRIME_CLEARANCE) diff --git a/tests/TestBuildVolume.py b/tests/TestBuildVolume.py index facdbfe143..640673e773 100644 --- a/tests/TestBuildVolume.py +++ b/tests/TestBuildVolume.py @@ -2,11 +2,16 @@ from unittest.mock import MagicMock, patch import pytest -from cura.BuildVolume import BuildVolume +from UM.Math.Polygon import Polygon +from UM.Settings.SettingInstance import InstanceState +from cura.BuildVolume import BuildVolume, PRIME_CLEARANCE import numpy + + + @pytest.fixture -def build_volume(): +def build_volume() -> BuildVolume: mocked_application = MagicMock() mocked_platform = MagicMock(name="platform") with patch("cura.BuildVolume.Platform", mocked_platform): @@ -36,3 +41,48 @@ 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()) + + +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]}