mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-06 22:47:29 -06:00
Fix duplicating / multiplicating support blockers
CURA-7851
This commit is contained in:
parent
f749bbef46
commit
44eb3201a9
2 changed files with 54 additions and 23 deletions
|
@ -110,18 +110,11 @@ 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, add_new_nodes_in_scene: bool = False) -> bool:
|
def createGroupOperationForArrange(nodes_to_arrange: List["SceneNode"],
|
||||||
"""
|
build_volume: "BuildVolume",
|
||||||
Find placement for a set of scene nodes, and move them by using a single grouped operation.
|
fixed_nodes: Optional[List["SceneNode"]] = None,
|
||||||
:param nodes_to_arrange: The list of nodes that need to be moved.
|
factor = 10000,
|
||||||
:param build_volume: The build volume that we want to place the nodes in. It gets size & disallowed areas from this.
|
add_new_nodes_in_scene: bool = False):
|
||||||
: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: found_solution_for_all: Whether the algorithm found a place on the buildplate for all the objects
|
|
||||||
"""
|
|
||||||
scene_root = Application.getInstance().getController().getScene().getRoot()
|
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)
|
||||||
|
|
||||||
|
@ -141,8 +134,30 @@ def arrange(nodes_to_arrange: List["SceneNode"], build_volume: "BuildVolume", fi
|
||||||
else:
|
else:
|
||||||
# We didn't find a spot
|
# We didn't find a spot
|
||||||
grouped_operation.addOperation(
|
grouped_operation.addOperation(
|
||||||
TranslateOperation(node, Vector(200, node.getWorldPosition().y, -not_fit_count * 20), set_position = True))
|
TranslateOperation(node, Vector(200, node.getWorldPosition().y, -not_fit_count * 20),
|
||||||
|
set_position=True))
|
||||||
not_fit_count += 1
|
not_fit_count += 1
|
||||||
grouped_operation.push()
|
|
||||||
|
|
||||||
return found_solution_for_all
|
return grouped_operation, not_fit_count
|
||||||
|
|
||||||
|
|
||||||
|
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.
|
||||||
|
:param build_volume: The build volume that we want to place the nodes in. It gets size & disallowed areas from this.
|
||||||
|
: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: found_solution_for_all: Whether the algorithm found a place on the buildplate for all the objects
|
||||||
|
"""
|
||||||
|
|
||||||
|
grouped_operation, not_fit_count = createGroupOperationForArrange(nodes_to_arrange, build_volume, fixed_nodes, factor, add_new_nodes_in_scene)
|
||||||
|
grouped_operation.redo()
|
||||||
|
return not_fit_count != 0
|
||||||
|
|
|
@ -7,10 +7,12 @@ from typing import List
|
||||||
from UM.Application import Application
|
from UM.Application import Application
|
||||||
from UM.Job import Job
|
from UM.Job import Job
|
||||||
from UM.Message import Message
|
from UM.Message import Message
|
||||||
|
from UM.Operations.AddSceneNodeOperation import AddSceneNodeOperation
|
||||||
|
from UM.Operations.GroupedOperation import GroupedOperation
|
||||||
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 arrange
|
from cura.Arranging.Nest2DArrange import arrange, createGroupOperationForArrange
|
||||||
|
|
||||||
i18n_catalog = i18nCatalog("cura")
|
i18n_catalog = i18nCatalog("cura")
|
||||||
|
|
||||||
|
@ -43,11 +45,11 @@ class MultiplyObjectsJob(Job):
|
||||||
# Only count sliceable objects
|
# Only count sliceable objects
|
||||||
if node_.callDecoration("isSliceable"):
|
if node_.callDecoration("isSliceable"):
|
||||||
fixed_nodes.append(node_)
|
fixed_nodes.append(node_)
|
||||||
|
nodes_to_add_without_arrange = []
|
||||||
for node in self._objects:
|
for node in self._objects:
|
||||||
# If object is part of a group, multiply group
|
# If object is part of a group, multiply group
|
||||||
current_node = node
|
current_node = node
|
||||||
while current_node.getParent() and (current_node.getParent().callDecoration("isGroup") or current_node.getParent().callDecoration("isSliceable")):
|
while current_node.getParent() and current_node.getParent().callDecoration("isGroup"):
|
||||||
current_node = current_node.getParent()
|
current_node = current_node.getParent()
|
||||||
|
|
||||||
if current_node in processed_nodes:
|
if current_node in processed_nodes:
|
||||||
|
@ -56,19 +58,33 @@ class MultiplyObjectsJob(Job):
|
||||||
|
|
||||||
for _ in range(self._count):
|
for _ in range(self._count):
|
||||||
new_node = copy.deepcopy(node)
|
new_node = copy.deepcopy(node)
|
||||||
|
|
||||||
# Same build plate
|
# Same build plate
|
||||||
build_plate_number = current_node.callDecoration("getBuildPlateNumber")
|
build_plate_number = current_node.callDecoration("getBuildPlateNumber")
|
||||||
new_node.callDecoration("setBuildPlateNumber", build_plate_number)
|
new_node.callDecoration("setBuildPlateNumber", build_plate_number)
|
||||||
for child in new_node.getChildren():
|
for child in new_node.getChildren():
|
||||||
child.callDecoration("setBuildPlateNumber", build_plate_number)
|
child.callDecoration("setBuildPlateNumber", build_plate_number)
|
||||||
|
if not current_node.getParent().callDecoration("isSliceable"):
|
||||||
nodes.append(new_node)
|
nodes.append(new_node)
|
||||||
|
else:
|
||||||
|
# The node we're trying to place has another node that is sliceable as a parent.
|
||||||
|
# As such, we shouldn't arrange it (but it should be added to the scene!)
|
||||||
|
nodes_to_add_without_arrange.append(new_node)
|
||||||
|
new_node.setParent(current_node.getParent())
|
||||||
|
|
||||||
found_solution_for_all = True
|
found_solution_for_all = True
|
||||||
if nodes:
|
if nodes:
|
||||||
found_solution_for_all = arrange(nodes, Application.getInstance().getBuildVolume(), fixed_nodes,
|
group_operation, not_fit_count = createGroupOperationForArrange(nodes,
|
||||||
factor = 10000, add_new_nodes_in_scene = True)
|
Application.getInstance().getBuildVolume(),
|
||||||
|
fixed_nodes,
|
||||||
|
factor=10000, add_new_nodes_in_scene=True)
|
||||||
|
else:
|
||||||
|
group_operation = GroupedOperation()
|
||||||
|
|
||||||
|
if nodes_to_add_without_arrange:
|
||||||
|
for nested_node in nodes_to_add_without_arrange:
|
||||||
|
group_operation.addOperation(AddSceneNodeOperation(nested_node, nested_node.getParent()))
|
||||||
|
|
||||||
|
group_operation.redo()
|
||||||
status_message.hide()
|
status_message.hide()
|
||||||
|
|
||||||
if not found_solution_for_all:
|
if not found_solution_for_all:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue