Modify arrange() to optionally create AddSceneNodeOperations

Then the MultiplyObjectsJob can use the arrange function instead of duplicating the code

CURA-7440
This commit is contained in:
Kostas Karmas 2020-10-09 17:12:59 +02:00
parent 518003f027
commit f9bd5e3dcd
2 changed files with 19 additions and 36 deletions

View file

@ -2,10 +2,12 @@ import numpy
from pynest2d import Point, Box, Item, NfpConfig, nest from pynest2d import Point, Box, Item, NfpConfig, nest
from typing import List, TYPE_CHECKING, Optional, Tuple from typing import List, TYPE_CHECKING, Optional, Tuple
from UM.Application import Application
from UM.Math.Matrix import Matrix from UM.Math.Matrix import Matrix
from UM.Math.Polygon import Polygon from UM.Math.Polygon import Polygon
from UM.Math.Quaternion import Quaternion from UM.Math.Quaternion import Quaternion
from UM.Math.Vector import Vector from UM.Math.Vector import Vector
from UM.Operations.AddSceneNodeOperation import AddSceneNodeOperation
from UM.Operations.GroupedOperation import GroupedOperation from UM.Operations.GroupedOperation import GroupedOperation
from UM.Operations.RotateOperation import RotateOperation from UM.Operations.RotateOperation import RotateOperation
from UM.Operations.TranslateOperation import TranslateOperation 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 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. 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. :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 :param fixed_nodes: List of nods that should not be moved, but should be used when deciding where the others nodes
are placed. are placed.
:param factor: The library that we use is int based. This factor defines how accuracte we want it to be. :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: :return:
""" """
scene_root = Application.getInstance().getController().getScene().getRoot()
found_solution_for_all, node_items = findNodePlacement(nodes_to_arrange, build_volume, fixed_nodes, factor) found_solution_for_all, node_items = findNodePlacement(nodes_to_arrange, build_volume, fixed_nodes, factor)
not_fit_count = 0 not_fit_count = 0
grouped_operation = GroupedOperation() grouped_operation = GroupedOperation()
for node, node_item in zip(nodes_to_arrange, node_items): 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: if node_item.binId() == 0:
# We found a spot for it # We found a spot for it

View file

@ -4,24 +4,16 @@
import copy import copy
from typing import List from typing import List
from UM.Application import Application
from UM.Job import Job 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.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.Iterator.DepthFirstIterator import DepthFirstIterator
from UM.Scene.SceneNode import SceneNode from UM.Scene.SceneNode import SceneNode
from UM.i18n import i18nCatalog from UM.i18n import i18nCatalog
from cura.Arranging.Nest2DArrange import findNodePlacement from cura.Arranging.Nest2DArrange import arrange
i18n_catalog = i18nCatalog("cura") i18n_catalog = i18nCatalog("cura")
from UM.Application import Application
from UM.Operations.AddSceneNodeOperation import AddSceneNodeOperation
class MultiplyObjectsJob(Job): class MultiplyObjectsJob(Job):
def __init__(self, objects, count, min_offset = 8): def __init__(self, objects, count, min_offset = 8):
@ -31,8 +23,9 @@ class MultiplyObjectsJob(Job):
self._min_offset = min_offset self._min_offset = min_offset
def run(self) -> None: def run(self) -> None:
status_message = Message(i18n_catalog.i18nc("@info:status", "Multiplying and placing objects"), lifetime=0, 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")) dismissable = False, progress = 0,
title = i18n_catalog.i18nc("@info:title", "Placing Objects"))
status_message.show() status_message.show()
scene = Application.getInstance().getController().getScene() scene = Application.getInstance().getController().getScene()
@ -71,30 +64,15 @@ class MultiplyObjectsJob(Job):
child.callDecoration("setBuildPlateNumber", build_plate_number) child.callDecoration("setBuildPlateNumber", build_plate_number)
nodes.append(new_node) nodes.append(new_node)
factor = 10000
found_solution_for_all, node_items = findNodePlacement(nodes, Application.getInstance().getBuildVolume(), fixed_nodes, factor = factor) found_solution_for_all = True
not_fit_count = 0
if nodes: if nodes:
operation = GroupedOperation() found_solution_for_all = arrange(nodes, Application.getInstance().getBuildVolume(), fixed_nodes,
for new_node, node_item in zip(nodes, node_items): factor = 10000, add_new_nodes_in_scene = True)
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()
status_message.hide() status_message.hide()
if not found_solution_for_all: 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() no_full_solution_message.show()