Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/Ultimaker/Cura.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJaime van Kessel <nallath@gmail.com>2020-09-28 17:16:47 +0300
committerJaime van Kessel <nallath@gmail.com>2020-09-28 17:16:47 +0300
commitb0a8a5ccabe4c8fe3a85c5c755b4a7b235afe684 (patch)
tree8a78f1235cd8f1cee0a8647772434b6681169ffd
parentd16ab4fdd681a56cf5b5aa66cfda8279700c27cc (diff)
Switch out the arranger algorithm for arrange all
CURA-7440
-rw-r--r--cura/Arranging/ArrangeObjectsJob.py79
-rwxr-xr-xcura_app.py1
2 files changed, 26 insertions, 54 deletions
diff --git a/cura/Arranging/ArrangeObjectsJob.py b/cura/Arranging/ArrangeObjectsJob.py
index 387bf92688..38fbd0c3b4 100644
--- a/cura/Arranging/ArrangeObjectsJob.py
+++ b/cura/Arranging/ArrangeObjectsJob.py
@@ -4,6 +4,9 @@ from PyQt5.QtCore import QCoreApplication
from UM.Application import Application
from UM.Job import Job
+from UM.Math.Matrix import Matrix
+from UM.Math.Quaternion import Quaternion
+from UM.Operations.RotateOperation import RotateOperation
from UM.Scene.SceneNode import SceneNode
from UM.Math.Vector import Vector
from UM.Operations.TranslateOperation import TranslateOperation
@@ -18,6 +21,7 @@ from cura.Arranging.Arrange import Arrange
from cura.Arranging.ShapeArray import ShapeArray
from typing import List
+from pynest2d import *
class ArrangeObjectsJob(Job):
@@ -38,64 +42,31 @@ class ArrangeObjectsJob(Job):
machine_width = global_container_stack.getProperty("machine_width", "value")
machine_depth = global_container_stack.getProperty("machine_depth", "value")
- arranger = Arrange.create(x = machine_width, y = machine_depth, fixed_nodes = self._fixed_nodes, min_offset = self._min_offset)
+ factor = 10000
- # Build set to exclude children (those get arranged together with the parents).
- included_as_child = set()
- for node in self._nodes:
- included_as_child.update(node.getAllChildren())
+ build_plate_bounding_box = Box(machine_width * factor, machine_depth * factor )
- # Collect nodes to be placed
- nodes_arr = [] # fill with (size, node, offset_shape_arr, hull_shape_arr)
+ node_items = []
for node in self._nodes:
- if node in included_as_child:
- continue
- offset_shape_arr, hull_shape_arr = ShapeArray.fromNode(node, min_offset = self._min_offset, include_children = True)
- if offset_shape_arr is None:
- Logger.log("w", "Node [%s] could not be converted to an array for arranging...", str(node))
- continue
- nodes_arr.append((offset_shape_arr.arr.shape[0] * offset_shape_arr.arr.shape[1], node, offset_shape_arr, hull_shape_arr))
-
- # Sort the nodes with the biggest area first.
- nodes_arr.sort(key=lambda item: item[0])
- nodes_arr.reverse()
-
- # Place nodes one at a time
- start_priority = 0
- last_priority = start_priority
- last_size = None
+ hull_polygon = node.callDecoration("getConvexHull")
+ converted_points = []
+ for point in hull_polygon.getPoints():
+ converted_points.append(Point(point[0] * factor, point[1] * factor))
+ item = Item(converted_points)
+ node_items.append(item)
+
+ config = NfpConfig()
+ config.accuracy = 1.0
+ num_bins = nest(node_items, build_plate_bounding_box, 1, config)
+ found_solution_for_all = num_bins == 1
+
grouped_operation = GroupedOperation()
- found_solution_for_all = True
- not_fit_count = 0
- for idx, (size, node, offset_shape_arr, hull_shape_arr) in enumerate(nodes_arr):
- # For performance reasons, we assume that when a location does not fit,
- # it will also not fit for the next object (while what can be untrue).
- if last_size == size: # This optimization works if many of the objects have the same size
- start_priority = last_priority
- else:
- start_priority = 0
- best_spot = arranger.bestSpot(hull_shape_arr, start_prio = start_priority)
- x, y = best_spot.x, best_spot.y
- node.removeDecorator(ZOffsetDecorator)
- if node.getBoundingBox():
- center_y = node.getWorldPosition().y - node.getBoundingBox().bottom
- else:
- center_y = 0
- if x is not None: # We could find a place
- last_size = size
- last_priority = best_spot.priority
-
- arranger.place(x, y, offset_shape_arr) # take place before the next one
- grouped_operation.addOperation(TranslateOperation(node, Vector(x, center_y, y), set_position = True))
- else:
- Logger.log("d", "Arrange all: could not find spot!")
- found_solution_for_all = False
- grouped_operation.addOperation(TranslateOperation(node, Vector(200, center_y, -not_fit_count * 20), set_position = True))
- not_fit_count += 1
-
- status_message.setProgress((idx + 1) / len(nodes_arr) * 100)
- Job.yieldThread()
- QCoreApplication.processEvents()
+ for node, node_item in zip(self._nodes, node_items):
+ rotation_matrix = Matrix()
+ rotation_matrix.setByRotationAxis(node_item.rotation(),Vector(0, -1, 0))
+
+ grouped_operation.addOperation(RotateOperation(node, Quaternion.fromMatrix(rotation_matrix)))
+ grouped_operation.addOperation(TranslateOperation(node, Vector(node_item.translation().x() / factor, 0, node_item.translation().y() / factor)))
grouped_operation.push()
diff --git a/cura_app.py b/cura_app.py
index 61fd544f8f..cc8a1d575c 100755
--- a/cura_app.py
+++ b/cura_app.py
@@ -22,6 +22,7 @@ import os
# tries to create PyQt objects on a non-main thread.
import Arcus # @UnusedImport
import Savitar # @UnusedImport
+import pynest2d # @UnusedImport
from PyQt5.QtNetwork import QSslConfiguration, QSslSocket