CURA-5370 Small refactor for Arranger: make x and y consistent (numpy arrays start with y first in general), faster, cleanup, more unit tests, take actual build plate size in Arranger instances

This commit is contained in:
Jack Ha 2018-05-22 17:13:35 +02:00
parent 310aee07ac
commit f5bed242ed
8 changed files with 287 additions and 73 deletions

View file

@ -4,9 +4,17 @@ from cura.Arranging.Arrange import Arrange
from cura.Arranging.ShapeArray import ShapeArray
def gimmeShapeArray():
vertices = numpy.array([[-3, 1], [3, 1], [0, -3]])
shape_arr = ShapeArray.fromPolygon(vertices)
## Triangle of area 12
def gimmeShapeArray(scale = 1.0):
vertices = numpy.array([[-3, 1], [3, 1], [0, -3]], dtype=numpy.int32)
shape_arr = ShapeArray.fromPolygon(vertices, scale = scale)
return shape_arr
## Boring square
def gimmeShapeArraySquare(scale = 1.0):
vertices = numpy.array([[-2, -2], [2, -2], [2, 2], [-2, 2]], dtype=numpy.int32)
shape_arr = ShapeArray.fromPolygon(vertices, scale = scale)
return shape_arr
@ -20,6 +28,45 @@ def test_smoke_ShapeArray():
shape_arr = gimmeShapeArray()
## Test ShapeArray
def test_ShapeArray():
scale = 1
ar = Arrange(16, 16, 8, 8, scale = scale)
ar.centerFirst()
shape_arr = gimmeShapeArray(scale)
print(shape_arr.arr)
count = len(numpy.where(shape_arr.arr == 1)[0])
print(count)
assert count >= 10 # should approach 12
## Test ShapeArray with scaling
def test_ShapeArray_scaling():
scale = 2
ar = Arrange(16, 16, 8, 8, scale = scale)
ar.centerFirst()
shape_arr = gimmeShapeArray(scale)
print(shape_arr.arr)
count = len(numpy.where(shape_arr.arr == 1)[0])
print(count)
assert count >= 40 # should approach 2*2*12 = 48
## Test ShapeArray with scaling
def test_ShapeArray_scaling2():
scale = 0.5
ar = Arrange(16, 16, 8, 8, scale = scale)
ar.centerFirst()
shape_arr = gimmeShapeArray(scale)
print(shape_arr.arr)
count = len(numpy.where(shape_arr.arr == 1)[0])
print(count)
assert count >= 1 # should approach 3, but it can be inaccurate due to pixel rounding
## Test centerFirst
def test_centerFirst():
ar = Arrange(300, 300, 150, 150)
@ -32,13 +79,33 @@ def test_centerFirst():
assert ar._priority[150][150] < ar._priority[130][130]
## Test centerFirst
def test_centerFirst_rectangular():
ar = Arrange(400, 300, 200, 150)
ar.centerFirst()
assert ar._priority[150][200] < ar._priority[150][220]
assert ar._priority[150][200] < ar._priority[170][200]
assert ar._priority[150][200] < ar._priority[170][220]
assert ar._priority[150][200] < ar._priority[180][150]
assert ar._priority[150][200] < ar._priority[130][200]
assert ar._priority[150][200] < ar._priority[130][180]
## Test centerFirst
def test_centerFirst_rectangular():
ar = Arrange(10, 20, 5, 10)
ar.centerFirst()
print(ar._priority)
assert ar._priority[10][5] < ar._priority[10][7]
## Test backFirst
def test_backFirst():
ar = Arrange(300, 300, 150, 150)
ar.backFirst()
assert ar._priority[150][150] < ar._priority[150][170]
assert ar._priority[150][150] < ar._priority[170][150]
assert ar._priority[150][150] < ar._priority[170][170]
assert ar._priority[150][150] > ar._priority[150][130]
assert ar._priority[150][150] > ar._priority[130][150]
assert ar._priority[150][150] > ar._priority[130][130]
@ -55,6 +122,113 @@ def test_smoke_bestSpot():
assert hasattr(best_spot, "priority")
## Real life test
def test_bestSpot():
ar = Arrange(16, 16, 8, 8)
ar.centerFirst()
shape_arr = gimmeShapeArray()
best_spot = ar.bestSpot(shape_arr)
assert best_spot.x == 0
assert best_spot.y == 0
ar.place(best_spot.x, best_spot.y, shape_arr)
# Place object a second time
best_spot = ar.bestSpot(shape_arr)
assert best_spot.x is not None # we found a location
assert best_spot.x != 0 or best_spot.y != 0 # it can't be on the same location
ar.place(best_spot.x, best_spot.y, shape_arr)
print(ar._occupied) # For debugging
## Real life test rectangular build plate
def test_bestSpot_rectangular_build_plate():
ar = Arrange(16, 40, 8, 20)
ar.centerFirst()
shape_arr = gimmeShapeArray()
best_spot = ar.bestSpot(shape_arr)
ar.place(best_spot.x, best_spot.y, shape_arr)
assert best_spot.x == 0
assert best_spot.y == 0
# Place object a second time
best_spot2 = ar.bestSpot(shape_arr)
assert best_spot2.x is not None # we found a location
assert best_spot2.x != 0 or best_spot2.y != 0 # it can't be on the same location
ar.place(best_spot2.x, best_spot2.y, shape_arr)
# Place object a 3rd time
best_spot3 = ar.bestSpot(shape_arr)
assert best_spot3.x is not None # we found a location
assert best_spot3.x != best_spot.x or best_spot3.y != best_spot.y # it can't be on the same location
assert best_spot3.x != best_spot2.x or best_spot3.y != best_spot2.y # it can't be on the same location
ar.place(best_spot3.x, best_spot3.y, shape_arr)
best_spot_x = ar.bestSpot(shape_arr)
ar.place(best_spot_x.x, best_spot_x.y, shape_arr)
best_spot_x = ar.bestSpot(shape_arr)
ar.place(best_spot_x.x, best_spot_x.y, shape_arr)
best_spot_x = ar.bestSpot(shape_arr)
ar.place(best_spot_x.x, best_spot_x.y, shape_arr)
print(ar._occupied) # For debugging
## Real life test
def test_bestSpot_scale():
scale = 0.5
ar = Arrange(16, 16, 8, 8, scale = scale)
ar.centerFirst()
shape_arr = gimmeShapeArray(scale)
best_spot = ar.bestSpot(shape_arr)
assert best_spot.x == 0
assert best_spot.y == 0
ar.place(best_spot.x, best_spot.y, shape_arr)
print(ar._occupied)
# Place object a second time
best_spot = ar.bestSpot(shape_arr)
assert best_spot.x is not None # we found a location
assert best_spot.x != 0 or best_spot.y != 0 # it can't be on the same location
ar.place(best_spot.x, best_spot.y, shape_arr)
print(ar._occupied) # For debugging
## Real life test
def test_bestSpot_scale_rectangular():
scale = 0.5
ar = Arrange(16, 40, 8, 20, scale = scale)
ar.centerFirst()
shape_arr = gimmeShapeArray(scale)
shape_arr_square = gimmeShapeArraySquare(scale)
best_spot = ar.bestSpot(shape_arr_square)
assert best_spot.x == 0
assert best_spot.y == 0
ar.place(best_spot.x, best_spot.y, shape_arr_square)
print(ar._occupied)
# Place object a second time
best_spot = ar.bestSpot(shape_arr)
assert best_spot.x is not None # we found a location
assert best_spot.x != 0 or best_spot.y != 0 # it can't be on the same location
ar.place(best_spot.x, best_spot.y, shape_arr)
best_spot = ar.bestSpot(shape_arr_square)
ar.place(best_spot.x, best_spot.y, shape_arr_square)
print(ar._occupied) # For debugging
## Try to place an object and see if something explodes
def test_smoke_place():
ar = Arrange(30, 30, 15, 15)
@ -80,6 +254,20 @@ def test_checkShape():
assert points3 > points
## See of our center has less penalty points than out of the center
def test_checkShape_rectangular():
ar = Arrange(20, 30, 10, 15)
ar.centerFirst()
print(ar._priority)
shape_arr = gimmeShapeArray()
points = ar.checkShape(0, 0, shape_arr)
points2 = ar.checkShape(5, 0, shape_arr)
points3 = ar.checkShape(0, 5, shape_arr)
assert points2 > points
assert points3 > points
## Check that placing an object on occupied place returns None.
def test_checkShape_place():
ar = Arrange(30, 30, 15, 15)
@ -104,6 +292,13 @@ def test_smoke_place_objects():
ar.place(best_spot_x, best_spot_y, shape_arr)
# Test some internals
def test_compare_occupied_and_priority_tables():
ar = Arrange(10, 15, 5, 7)
ar.centerFirst()
assert ar._priority.shape == ar._occupied.shape
## Polygon -> array
def test_arrayFromPolygon():
vertices = numpy.array([[-3, 1], [3, 1], [0, -3]])
@ -145,3 +340,5 @@ def test_check2():
assert numpy.any(check_array)
assert not check_array[3][0]
assert check_array[3][4]