Tuned arranger a bit, good enough for proof of concept. CURA-3239

This commit is contained in:
Jack Ha 2017-03-29 09:32:29 +02:00
parent bf08d30e7d
commit f357dea086
2 changed files with 27 additions and 41 deletions

View File

@ -12,20 +12,17 @@ class ShapeArray:
def from_polygon(cls, vertices, scale = 1):
# scale
vertices = vertices * scale
# flip x, y
# flip y, x -> x, y
flip_vertices = np.zeros((vertices.shape))
flip_vertices[:, 0] = vertices[:, 1]
flip_vertices[:, 1] = vertices[:, 0]
flip_vertices = flip_vertices[::-1]
# offset
# offset, we want that all coordinates have positive values
offset_y = int(np.amin(flip_vertices[:, 0]))
offset_x = int(np.amin(flip_vertices[:, 1]))
# offset to 0
flip_vertices[:, 0] = np.add(flip_vertices[:, 0], -offset_y)
flip_vertices[:, 1] = np.add(flip_vertices[:, 1], -offset_x)
shape = [int(np.amax(flip_vertices[:, 0])), int(np.amax(flip_vertices[:, 1]))]
#from UM.Logger import Logger
#Logger.log("d", " Vertices: %s" % str(flip_vertices))
arr = cls.array_from_polygon(shape, flip_vertices)
return cls(arr, offset_x, offset_y)
@ -85,6 +82,7 @@ class Arrange:
def __init__(self, x, y, offset_x, offset_y, scale=1):
self.shape = (y, x)
self._priority = np.zeros((x, y), dtype=np.int32)
self._priority_unique_values = []
self._occupied = np.zeros((x, y), dtype=np.int32)
self._scale = scale # convert input coordinates to arrange coordinates
self._offset_x = offset_x
@ -92,8 +90,12 @@ class Arrange:
## Fill priority, take offset as center. lower is better
def centerFirst(self):
#self._priority = np.fromfunction(
# lambda i, j: abs(self._offset_x-i)+abs(self._offset_y-j), self.shape)
self._priority = np.fromfunction(
lambda i, j: abs(self._offset_x-i)+abs(self._offset_y-j), self.shape)
lambda i, j: abs(self._offset_x-i)**2+abs(self._offset_y-j)**2, self.shape, dtype=np.int32)
self._priority_unique_values = np.unique(self._priority)
self._priority_unique_values.sort()
## Return the amount of "penalty points" for polygon, which is the sum of priority
# 999999 if occupied
@ -115,24 +117,14 @@ class Arrange:
offset_x:offset_x + shape_arr.arr.shape[1]]
return np.sum(prio_slice[np.where(shape_arr.arr == 1)])
## Slower but better (it tries all possible locations)
def bestSpot2(self, shape_arr):
best_x, best_y, best_points = None, None, None
min_y = max(-shape_arr.offset_y, 0) - self._offset_y
max_y = self.shape[0] - shape_arr.arr.shape[0] - self._offset_y
min_x = max(-shape_arr.offset_x, 0) - self._offset_x
max_x = self.shape[1] - shape_arr.arr.shape[1] - self._offset_x
for y in range(min_y, max_y):
for x in range(min_x, max_x):
penalty_points = self.check_shape(x, y, shape_arr)
if best_points is None or penalty_points < best_points:
best_points = penalty_points
best_x, best_y = x, y
return best_x, best_y, best_points
## Faster
## Find "best" spot
def bestSpot(self, shape_arr, start_prio = 0):
for prio in range(start_prio, 300):
start_idx_list = np.where(self._priority_unique_values == start_prio)
if start_idx_list:
start_idx = start_idx_list[0]
else:
start_idx = 0
for prio in self._priority_unique_values[start_idx:]:
tryout_idx = np.where(self._priority == prio)
for idx in range(len(tryout_idx[0])):
x = tryout_idx[0][idx]

View File

@ -848,7 +848,9 @@ class CuraApplication(QtApplication):
## Testing, prepare arranger for use
def _prepareArranger(self, fixed_nodes = None):
arranger = Arrange(215, 215, 107, 107) # TODO: fill in dimensions
#arranger = Arrange(215, 215, 107, 107) # TODO: fill in dimensions
scale = 0.5
arranger = Arrange(250, 250, 125, 125, scale = scale) # TODO: fill in dimensions
arranger.centerFirst()
if fixed_nodes is None:
@ -864,13 +866,14 @@ class CuraApplication(QtApplication):
vertices = fixed_node.callDecoration("getConvexHull")
points = copy.deepcopy(vertices._points)
shape_arr = ShapeArray.from_polygon(points)
shape_arr = ShapeArray.from_polygon(points, scale=scale)
arranger.place(0, 0, shape_arr)
Logger.log("d", "Current buildplate: \n%s" % str(arranger._occupied[::10, ::10]))
return arranger
@classmethod
def _nodeAsShapeArr(cls, node, min_offset):
scale = 0.5
# hacky way to undo transformation
transform = node._transformation
transform_x = transform._data[0][3]
@ -881,12 +884,12 @@ class CuraApplication(QtApplication):
offset_points = copy.deepcopy(offset_verts._points) # x, y
offset_points[:, 0] = numpy.add(offset_points[:, 0], -transform_x)
offset_points[:, 1] = numpy.add(offset_points[:, 1], -transform_y)
offset_shape_arr = ShapeArray.from_polygon(offset_points)
offset_shape_arr = ShapeArray.from_polygon(offset_points, scale = scale)
hull_points = copy.deepcopy(hull_verts._points)
hull_points[:, 0] = numpy.add(hull_points[:, 0], -transform_x)
hull_points[:, 1] = numpy.add(hull_points[:, 1], -transform_y)
hull_shape_arr = ShapeArray.from_polygon(hull_points) # x, y
hull_shape_arr = ShapeArray.from_polygon(hull_points, scale = scale) # x, y
return offset_shape_arr, hull_shape_arr
@ -913,7 +916,6 @@ class CuraApplication(QtApplication):
transformation._data[0][3] = 200
transformation._data[2][3] = -100 + i * 20
# new_node.setTransformation(transformation)
nodes.append(new_node)
return nodes
@ -922,7 +924,7 @@ class CuraApplication(QtApplication):
# count: number of copies
# min_offset: minimum offset to other objects.
@pyqtSlot("quint64", int)
def multiplyObject(self, object_id, count, min_offset = 5):
def multiplyObject(self, object_id, count, min_offset = 8):
node = self.getController().getScene().findObject(object_id)
if not node and object_id != 0: # Workaround for tool handles overlapping the selected object
@ -1063,7 +1065,7 @@ class CuraApplication(QtApplication):
## Testing: arrange selected objects or all objects
@pyqtSlot()
def arrange(self):
min_offset = 5
min_offset = 8
if Selection.getAllSelectedObjects():
nodes = Selection.getAllSelectedObjects()
@ -1374,9 +1376,8 @@ class CuraApplication(QtApplication):
self._currently_loading_files.remove(filename)
arranger = self._prepareArranger()
min_offset = 5
min_offset = 8
total_time = 0
import time
for node in nodes:
node.setSelectable(True)
@ -1403,13 +1404,8 @@ class CuraApplication(QtApplication):
node.addDecorator(ConvexHullDecorator())
# find node location
if 1:
start_time = time.time()
offset_shape_arr, hull_shape_arr = self._nodeAsShapeArr(node, min_offset = min_offset)
nodes = self._findNodePlacements(arranger, node, offset_shape_arr, hull_shape_arr, count = 1)
total_time += (time.time() - start_time)
else:
nodes = [node]
offset_shape_arr, hull_shape_arr = self._nodeAsShapeArr(node, min_offset = min_offset)
nodes = self._findNodePlacements(arranger, node, offset_shape_arr, hull_shape_arr, count = 1)
for new_node in nodes:
op = AddSceneNodeOperation(new_node, scene.getRoot())
@ -1417,8 +1413,6 @@ class CuraApplication(QtApplication):
scene.sceneChanged.emit(node)
Logger.log("d", "Placement of %s objects took %.1f seconds" % (len(nodes), total_time))
def addNonSliceableExtension(self, extension):
self._non_sliceable_extensions.append(extension)