diff --git a/cura/Arranging/Nest2DArrange.py b/cura/Arranging/Nest2DArrange.py index 8e87228ded..b41c164147 100644 --- a/cura/Arranging/Nest2DArrange.py +++ b/cura/Arranging/Nest2DArrange.py @@ -2,10 +2,12 @@ import numpy from pynest2d import Point, Box, Item, NfpConfig, nest from typing import List, TYPE_CHECKING, Optional, Tuple +from UM.Application import Application from UM.Math.Matrix import Matrix from UM.Math.Polygon import Polygon from UM.Math.Quaternion import Quaternion from UM.Math.Vector import Vector +from UM.Operations.AddSceneNodeOperation import AddSceneNodeOperation from UM.Operations.GroupedOperation import GroupedOperation from UM.Operations.RotateOperation import RotateOperation from UM.Operations.TranslateOperation import TranslateOperation @@ -96,7 +98,7 @@ def findNodePlacement(nodes_to_arrange: List["SceneNode"], build_volume: "BuildV return found_solution_for_all, node_items -def arrange(nodes_to_arrange: List["SceneNode"], build_volume: "BuildVolume", fixed_nodes: Optional[List["SceneNode"]] = None, factor = 10000) -> bool: +def arrange(nodes_to_arrange: List["SceneNode"], build_volume: "BuildVolume", fixed_nodes: Optional[List["SceneNode"]] = None, factor = 10000, add_new_nodes_in_scene: bool = False) -> bool: """ Find placement for a set of scene nodes, and move them by using a single grouped operation. :param nodes_to_arrange: The list of nodes that need to be moved. @@ -104,14 +106,17 @@ def arrange(nodes_to_arrange: List["SceneNode"], build_volume: "BuildVolume", fi :param fixed_nodes: List of nods that should not be moved, but should be used when deciding where the others nodes are placed. :param factor: The library that we use is int based. This factor defines how accuracte we want it to be. + :param add_new_nodes_in_scene: Whether to create new scene nodes before applying the transformations and rotations :return: """ - + scene_root = Application.getInstance().getController().getScene().getRoot() found_solution_for_all, node_items = findNodePlacement(nodes_to_arrange, build_volume, fixed_nodes, factor) not_fit_count = 0 grouped_operation = GroupedOperation() for node, node_item in zip(nodes_to_arrange, node_items): + if add_new_nodes_in_scene: + grouped_operation.addOperation(AddSceneNodeOperation(node, scene_root)) if node_item.binId() == 0: # We found a spot for it diff --git a/cura/MultiplyObjectsJob.py b/cura/MultiplyObjectsJob.py index 25b3aad171..1ba78edacf 100644 --- a/cura/MultiplyObjectsJob.py +++ b/cura/MultiplyObjectsJob.py @@ -4,24 +4,16 @@ import copy from typing import List +from UM.Application import Application from UM.Job import Job -from UM.Math.Matrix import Matrix -from UM.Math.Quaternion import Quaternion -from UM.Math.Vector import Vector -from UM.Operations.GroupedOperation import GroupedOperation from UM.Message import Message -from UM.Operations.RotateOperation import RotateOperation -from UM.Operations.TranslateOperation import TranslateOperation from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator from UM.Scene.SceneNode import SceneNode from UM.i18n import i18nCatalog -from cura.Arranging.Nest2DArrange import findNodePlacement +from cura.Arranging.Nest2DArrange import arrange i18n_catalog = i18nCatalog("cura") -from UM.Application import Application -from UM.Operations.AddSceneNodeOperation import AddSceneNodeOperation - class MultiplyObjectsJob(Job): def __init__(self, objects, count, min_offset = 8): @@ -31,8 +23,9 @@ class MultiplyObjectsJob(Job): self._min_offset = min_offset def run(self) -> None: - status_message = Message(i18n_catalog.i18nc("@info:status", "Multiplying and placing objects"), lifetime=0, - dismissable=False, progress=0, title = i18n_catalog.i18nc("@info:title", "Placing Objects")) + status_message = Message(i18n_catalog.i18nc("@info:status", "Multiplying and placing objects"), lifetime = 0, + dismissable = False, progress = 0, + title = i18n_catalog.i18nc("@info:title", "Placing Objects")) status_message.show() scene = Application.getInstance().getController().getScene() @@ -71,30 +64,15 @@ class MultiplyObjectsJob(Job): child.callDecoration("setBuildPlateNumber", build_plate_number) nodes.append(new_node) - factor = 10000 - found_solution_for_all, node_items = findNodePlacement(nodes, Application.getInstance().getBuildVolume(), fixed_nodes, factor = factor) - not_fit_count = 0 + + found_solution_for_all = True if nodes: - operation = GroupedOperation() - for new_node, node_item in zip(nodes, node_items): - operation.addOperation(AddSceneNodeOperation(new_node, root)) - - if node_item.binId() == 0: - # We found a spot for it - rotation_matrix = Matrix() - rotation_matrix.setByRotationAxis(node_item.rotation(), Vector(0, -1, 0)) - operation.addOperation(RotateOperation(new_node, Quaternion.fromMatrix(rotation_matrix))) - operation.addOperation( - TranslateOperation(new_node, Vector(node_item.translation().x() / factor, 0, - node_item.translation().y() / factor))) - else: - # We didn't find a spot - operation.addOperation(TranslateOperation(new_node, Vector(200, new_node.getWorldPosition().y, -not_fit_count * 20), set_position = True)) - not_fit_count += 1 - - operation.push() + found_solution_for_all = arrange(nodes, Application.getInstance().getBuildVolume(), fixed_nodes, + factor = 10000, add_new_nodes_in_scene = True) status_message.hide() if not found_solution_for_all: - no_full_solution_message = Message(i18n_catalog.i18nc("@info:status", "Unable to find a location within the build volume for all objects"), title = i18n_catalog.i18nc("@info:title", "Placing Object")) + no_full_solution_message = Message( + i18n_catalog.i18nc("@info:status", "Unable to find a location within the build volume for all objects"), + title = i18n_catalog.i18nc("@info:title", "Placing Object")) no_full_solution_message.show()