diff options
author | Casper Lamboo <c.lamboo@ultimaker.com> | 2021-12-15 19:40:27 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-12-15 19:40:27 +0300 |
commit | 7c7a1016d0ea1bdccf84dea6909011309f68e713 (patch) | |
tree | 354db061a0a0dd94ec4bc8fb19dfcedd4983b1bf | |
parent | 03398422ddc300e4cdce6dfa0b352ed17f87c43b (diff) | |
parent | d277109cc806cbb787ab153fc9d169f2fad5620d (diff) |
Merge pull request #11075 from Ultimaker/CURA-8083_separate_z_shrinkage_comp
[CURA-8083] Separate Vertical and Horizontal Shrinkage Compensation.
-rwxr-xr-x | cura/BuildVolume.py | 55 | ||||
-rw-r--r-- | resources/definitions/fdmprinter.def.json | 37 | ||||
-rw-r--r-- | tests/TestBuildVolume.py | 40 |
3 files changed, 110 insertions, 22 deletions
diff --git a/cura/BuildVolume.py b/cura/BuildVolume.py index 8374bddf74..45e4c9901a 100755 --- a/cura/BuildVolume.py +++ b/cura/BuildVolume.py @@ -66,6 +66,7 @@ class BuildVolume(SceneNode): self._height = 0 # type: float self._depth = 0 # type: float self._shape = "" # type: str + self._scale_vector = Vector(1.0, 1.0, 1.0) self._shader = None @@ -513,6 +514,13 @@ class BuildVolume(SceneNode): self._disallowed_area_size = max(size, self._disallowed_area_size) return mb.build() + def _updateScaleFactor(self) -> None: + if not self._global_container_stack: + return + scale_xy = 100.0 / max(100.0, self._global_container_stack.getProperty("material_shrinkage_percentage_xy", "value")) + scale_z = 100.0 / max(100.0, self._global_container_stack.getProperty("material_shrinkage_percentage_z" , "value")) + self._scale_vector = Vector(scale_xy, scale_xy, scale_z) + def rebuild(self) -> None: """Recalculates the build volume & disallowed areas.""" @@ -554,9 +562,12 @@ class BuildVolume(SceneNode): self._error_mesh = self._buildErrorMesh(min_w, max_w, min_h, max_h, min_d, max_d, disallowed_area_height) + self._updateScaleFactor() + self._volume_aabb = AxisAlignedBox( - minimum = Vector(min_w, min_h - 1.0, min_d), - maximum = Vector(max_w, max_h - self._raft_thickness - self._extra_z_clearance, max_d)) + minimum = Vector(min_w, min_h - 1.0, min_d).scale(self._scale_vector), + maximum = Vector(max_w, max_h - self._raft_thickness - self._extra_z_clearance, max_d).scale(self._scale_vector) + ) bed_adhesion_size = self.getEdgeDisallowedSize() @@ -564,15 +575,15 @@ class BuildVolume(SceneNode): # This is probably wrong in all other cases. TODO! # The +1 and -1 is added as there is always a bit of extra room required to work properly. scale_to_max_bounds = AxisAlignedBox( - minimum = Vector(min_w + bed_adhesion_size + 1, min_h, min_d + self._disallowed_area_size - bed_adhesion_size + 1), - maximum = Vector(max_w - bed_adhesion_size - 1, max_h - self._raft_thickness - self._extra_z_clearance, max_d - self._disallowed_area_size + bed_adhesion_size - 1) + minimum = Vector(min_w + bed_adhesion_size + 1, min_h, min_d + self._disallowed_area_size - bed_adhesion_size + 1).scale(self._scale_vector), + maximum = Vector(max_w - bed_adhesion_size - 1, max_h - self._raft_thickness - self._extra_z_clearance, max_d - self._disallowed_area_size + bed_adhesion_size - 1).scale(self._scale_vector) ) self._application.getController().getScene()._maximum_bounds = scale_to_max_bounds # type: ignore self.updateNodeBoundaryCheck() - def getBoundingBox(self): + def getBoundingBox(self) -> Optional[AxisAlignedBox]: return self._volume_aabb def getRaftThickness(self) -> float: @@ -633,18 +644,18 @@ class BuildVolume(SceneNode): for extruder in extruders: extruder.propertyChanged.connect(self._onSettingPropertyChanged) - self._width = self._global_container_stack.getProperty("machine_width", "value") + self._width = self._global_container_stack.getProperty("machine_width", "value") * self._scale_vector.x machine_height = self._global_container_stack.getProperty("machine_height", "value") if self._global_container_stack.getProperty("print_sequence", "value") == "one_at_a_time" and len(self._scene_objects) > 1: - self._height = min(self._global_container_stack.getProperty("gantry_height", "value"), machine_height) - if self._height < machine_height: + self._height = min(self._global_container_stack.getProperty("gantry_height", "value") * self._scale_vector.z, machine_height) + if self._height < (machine_height * self._scale_vector.z): self._build_volume_message.show() else: self._build_volume_message.hide() else: self._height = self._global_container_stack.getProperty("machine_height", "value") self._build_volume_message.hide() - self._depth = self._global_container_stack.getProperty("machine_depth", "value") + self._depth = self._global_container_stack.getProperty("machine_depth", "value") * self._scale_vector.y self._shape = self._global_container_stack.getProperty("machine_shape", "value") self._updateDisallowedAreas() @@ -678,18 +689,18 @@ class BuildVolume(SceneNode): if setting_key == "print_sequence": machine_height = self._global_container_stack.getProperty("machine_height", "value") if self._application.getGlobalContainerStack().getProperty("print_sequence", "value") == "one_at_a_time" and len(self._scene_objects) > 1: - self._height = min(self._global_container_stack.getProperty("gantry_height", "value"), machine_height) - if self._height < machine_height: + self._height = min(self._global_container_stack.getProperty("gantry_height", "value") * self._scale_vector.z, machine_height) + if self._height < (machine_height * self._scale_vector.z): self._build_volume_message.show() else: self._build_volume_message.hide() else: - self._height = self._global_container_stack.getProperty("machine_height", "value") + self._height = self._global_container_stack.getProperty("machine_height", "value") * self._scale_vector.z self._build_volume_message.hide() update_disallowed_areas = True # sometimes the machine size or shape settings are adjusted on the active machine, we should reflect this - if setting_key in self._machine_settings: + if setting_key in self._machine_settings or setting_key in self._material_size_settings: self._updateMachineSizeProperties() update_extra_z_clearance = True update_disallowed_areas = True @@ -738,9 +749,10 @@ class BuildVolume(SceneNode): def _updateMachineSizeProperties(self) -> None: if not self._global_container_stack: return - self._height = self._global_container_stack.getProperty("machine_height", "value") - self._width = self._global_container_stack.getProperty("machine_width", "value") - self._depth = self._global_container_stack.getProperty("machine_depth", "value") + self._updateScaleFactor() + self._height = self._global_container_stack.getProperty("machine_height", "value") * self._scale_vector.z + self._width = self._global_container_stack.getProperty("machine_width", "value") * self._scale_vector.x + self._depth = self._global_container_stack.getProperty("machine_depth", "value") * self._scale_vector.y self._shape = self._global_container_stack.getProperty("machine_shape", "value") def _updateDisallowedAreasAndRebuild(self): @@ -757,6 +769,12 @@ class BuildVolume(SceneNode): self._extra_z_clearance = self._calculateExtraZClearance(ExtruderManager.getInstance().getUsedExtruderStacks()) self.rebuild() + def _scaleAreas(self, result_areas: List["Polygons"]) -> None: + for i, polygon in enumerate(result_areas): + result_areas[i] = polygon.scale( + 100.0 / max(100.0, self._global_container_stack.getProperty("material_shrinkage_percentage_xy", "value")) + ) + def _updateDisallowedAreas(self) -> None: if not self._global_container_stack: return @@ -812,9 +830,11 @@ class BuildVolume(SceneNode): self._disallowed_areas = [] for extruder_id in result_areas: + self._scaleAreas(result_areas[extruder_id]) self._disallowed_areas.extend(result_areas[extruder_id]) self._disallowed_areas_no_brim = [] for extruder_id in result_areas_no_brim: + self._scaleAreas(result_areas_no_brim[extruder_id]) self._disallowed_areas_no_brim.extend(result_areas_no_brim[extruder_id]) def _computeDisallowedAreasPrinted(self, used_extruders): @@ -1200,4 +1220,5 @@ class BuildVolume(SceneNode): _distance_settings = ["infill_wipe_dist", "travel_avoid_distance", "support_offset", "support_enable", "travel_avoid_other_parts", "travel_avoid_supports", "wall_line_count", "wall_line_width_0", "wall_line_width_x"] _extruder_settings = ["support_enable", "support_bottom_enable", "support_roof_enable", "support_infill_extruder_nr", "support_extruder_nr_layer_0", "support_bottom_extruder_nr", "support_roof_extruder_nr", "brim_line_count", "adhesion_extruder_nr", "adhesion_type"] #Settings that can affect which extruders are used. _limit_to_extruder_settings = ["wall_extruder_nr", "wall_0_extruder_nr", "wall_x_extruder_nr", "top_bottom_extruder_nr", "infill_extruder_nr", "support_infill_extruder_nr", "support_extruder_nr_layer_0", "support_bottom_extruder_nr", "support_roof_extruder_nr", "adhesion_extruder_nr"] - _disallowed_area_settings = _skirt_settings + _prime_settings + _tower_settings + _ooze_shield_settings + _distance_settings + _extruder_settings + _material_size_settings = ["material_shrinkage_percentage", "material_shrinkage_percentage_xy", "material_shrinkage_percentage_z"] + _disallowed_area_settings = _skirt_settings + _prime_settings + _tower_settings + _ooze_shield_settings + _distance_settings + _extruder_settings + _material_size_settings diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 49ad2e3c5b..f54e64849c 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -2512,7 +2512,42 @@ "maximum_value_warning": "120", "settable_per_mesh": false, "settable_per_extruder": false, - "resolve": "sum(extruderValues(\"material_shrinkage_percentage\")) / len(extruderValues(\"material_shrinkage_percentage\"))" + "resolve": "sum(extruderValues(\"material_shrinkage_percentage\")) / len(extruderValues(\"material_shrinkage_percentage\"))", + "children": + { + "material_shrinkage_percentage_xy": + { + "label": "Horizontal Scaling Factor Shrinkage Compensation", + "description": "To compensate for the shrinkage of the material as it cools down, the model will be scaled with this factor in the XY-direction (horizontally).", + "unit": "%", + "type": "float", + "default_value": 100.0, + "enabled": false, + "minimum_value": "0.001", + "minimum_value_warning": "100", + "maximum_value_warning": "120", + "settable_per_mesh": false, + "settable_per_extruder": false, + "resolve": "sum(extruderValues(\"material_shrinkage_percentage_xy\")) / len(extruderValues(\"material_shrinkage_percentage_xy\"))", + "value": "material_shrinkage_percentage" + }, + "material_shrinkage_percentage_z": + { + "label": "Vertical Scaling Factor Shrinkage Compensation", + "description": "To compensate for the shrinkage of the material as it cools down, the model will be scaled with this factor in the Z-direction (vertically).", + "unit": "%", + "type": "float", + "default_value": 100.0, + "enabled": false, + "minimum_value": "0.001", + "minimum_value_warning": "100", + "maximum_value_warning": "120", + "settable_per_mesh": false, + "settable_per_extruder": false, + "resolve": "sum(extruderValues(\"material_shrinkage_percentage_z\")) / len(extruderValues(\"material_shrinkage_percentage_z\"))", + "value": "material_shrinkage_percentage" + } + } }, "material_crystallinity": { diff --git a/tests/TestBuildVolume.py b/tests/TestBuildVolume.py index 293b8e0270..f59d83df5e 100644 --- a/tests/TestBuildVolume.py +++ b/tests/TestBuildVolume.py @@ -57,7 +57,10 @@ class TestCalculateBedAdhesionSize: "machine_depth": {"value": 200}, "skirt_line_count": {"value": 0}, "skirt_gap": {"value": 0}, - "raft_margin": {"value": 0} + "raft_margin": {"value": 0}, + "material_shrinkage_percentage": {"value": 100.0}, + "material_shrinkage_percentage_xy": {"value": 100.0}, + "material_shrinkage_percentage_z": {"value": 100.0}, } def getPropertySideEffect(*args, **kwargs): @@ -109,6 +112,9 @@ 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}, + "material_shrinkage_percentage": {"value": 100.0}, + "material_shrinkage_percentage_xy": {"value": 100.0}, + "material_shrinkage_percentage_z": {"value": 100.0}, } def getPropertySideEffect(*args, **kwargs): @@ -157,7 +163,11 @@ class TestUpdateRaftThickness: "raft_surface_thickness": {"value": 1}, "raft_airgap": {"value": 1}, "layer_0_z_overlap": {"value": 1}, - "adhesion_type": {"value": "raft"}} + "adhesion_type": {"value": "raft"}, + "material_shrinkage_percentage": {"value": 100.0}, + "material_shrinkage_percentage_xy": {"value": 100.0}, + "material_shrinkage_percentage_z": {"value": 100.0}, + } def getPropertySideEffect(*args, **kwargs): properties = TestUpdateRaftThickness.setting_property_dict.get(args[1]) @@ -208,6 +218,9 @@ class TestComputeDisallowedAreasPrimeBlob: "extruder_prime_pos_x": {"value": 25}, "extruder_prime_pos_y": {"value": 50}, "machine_center_is_zero": {"value": True}, + "material_shrinkage_percentage": {"value": 100.0}, + "material_shrinkage_percentage_xy": {"value": 100.0}, + "material_shrinkage_percentage_z": {"value": 100.0}, } def getPropertySideEffect(*args, **kwargs): @@ -248,7 +261,11 @@ class TestComputeDisallowedAreasPrimeBlob: class TestCalculateExtraZClearance: setting_property_dict = {"retraction_hop": {"value": 12}, - "retraction_hop_enabled": {"value": True}} + "retraction_hop_enabled": {"value": True}, + "material_shrinkage_percentage": {"value": 100.0}, + "material_shrinkage_percentage_xy": {"value": 100.0}, + "material_shrinkage_percentage_z": {"value": 100.0}, + } def getPropertySideEffect(*args, **kwargs): properties = TestCalculateExtraZClearance.setting_property_dict.get(args[1]) @@ -285,6 +302,16 @@ class TestCalculateExtraZClearance: class TestRebuild: + setting_property_dict = { + "material_shrinkage_percentage": {"value": 100.0}, + "material_shrinkage_percentage_xy": {"value": 100.0}, + "material_shrinkage_percentage_z": {"value": 100.0}, + } + def getPropertySideEffect(*args, **kwargs): + properties = TestCalculateExtraZClearance.setting_property_dict.get(args[1]) + if properties: + return properties.get(args[2]) + def test_zeroWidthHeightDepth(self, build_volume: BuildVolume): build_volume.rebuild() assert build_volume.getMeshData() is None @@ -311,6 +338,7 @@ class TestRebuild: build_volume.setDepth(10) mocked_global_stack = MagicMock() + mocked_global_stack.getProperty = MagicMock(side_effect=self.getPropertySideEffect) build_volume._global_container_stack = mocked_global_stack build_volume.getEdgeDisallowedSize = MagicMock(return_value = 0) build_volume.updateNodeBoundaryCheck = MagicMock() @@ -328,7 +356,11 @@ class TestUpdateMachineSizeProperties: setting_property_dict = {"machine_width": {"value": 50}, "machine_depth": {"value": 100}, "machine_height": {"value": 200}, - "machine_shape": {"value": "DERP!"}} + "machine_shape": {"value": "DERP!"}, + "material_shrinkage_percentage": {"value": 100.0}, + "material_shrinkage_percentage_xy": {"value": 100.0}, + "material_shrinkage_percentage_z": {"value": 100.0}, + } def getPropertySideEffect(*args, **kwargs): properties = TestUpdateMachineSizeProperties.setting_property_dict.get(args[1]) |