TestArrange.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381
  1. # Copyright (c) 2018 Ultimaker B.V.
  2. # Cura is released under the terms of the LGPLv3 or higher.
  3. import numpy
  4. from cura.Arranging.Arrange import Arrange
  5. from cura.Arranging.ShapeArray import ShapeArray
  6. ## Triangle of area 12
  7. def gimmeTriangle():
  8. return numpy.array([[-3, 1], [3, 1], [0, -3]], dtype=numpy.int32)
  9. ## Boring square
  10. def gimmeSquare():
  11. return numpy.array([[-2, -2], [2, -2], [2, 2], [-2, 2]], dtype=numpy.int32)
  12. ## Triangle of area 12
  13. def gimmeShapeArray(scale = 1.0):
  14. vertices = gimmeTriangle()
  15. shape_arr = ShapeArray.fromPolygon(vertices, scale = scale)
  16. return shape_arr
  17. ## Boring square
  18. def gimmeShapeArraySquare(scale = 1.0):
  19. vertices = gimmeSquare()
  20. shape_arr = ShapeArray.fromPolygon(vertices, scale = scale)
  21. return shape_arr
  22. ## Smoke test for Arrange
  23. def test_smoke_arrange():
  24. ar = Arrange.create(fixed_nodes = [])
  25. ## Smoke test for ShapeArray
  26. def test_smoke_ShapeArray():
  27. shape_arr = gimmeShapeArray()
  28. ## Test ShapeArray
  29. def test_ShapeArray():
  30. scale = 1
  31. ar = Arrange(16, 16, 8, 8, scale = scale)
  32. ar.centerFirst()
  33. shape_arr = gimmeShapeArray(scale)
  34. print(shape_arr.arr)
  35. count = len(numpy.where(shape_arr.arr == 1)[0])
  36. print(count)
  37. assert count >= 10 # should approach 12
  38. ## Test ShapeArray with scaling
  39. def test_ShapeArray_scaling():
  40. scale = 2
  41. ar = Arrange(16, 16, 8, 8, scale = scale)
  42. ar.centerFirst()
  43. shape_arr = gimmeShapeArray(scale)
  44. print(shape_arr.arr)
  45. count = len(numpy.where(shape_arr.arr == 1)[0])
  46. print(count)
  47. assert count >= 40 # should approach 2*2*12 = 48
  48. ## Test ShapeArray with scaling
  49. def test_ShapeArray_scaling2():
  50. scale = 0.5
  51. ar = Arrange(16, 16, 8, 8, scale = scale)
  52. ar.centerFirst()
  53. shape_arr = gimmeShapeArray(scale)
  54. print(shape_arr.arr)
  55. count = len(numpy.where(shape_arr.arr == 1)[0])
  56. print(count)
  57. assert count >= 1 # should approach 3, but it can be inaccurate due to pixel rounding
  58. ## Test centerFirst
  59. def test_centerFirst():
  60. ar = Arrange(300, 300, 150, 150, scale = 1)
  61. ar.centerFirst()
  62. assert ar._priority[150][150] < ar._priority[170][150]
  63. assert ar._priority[150][150] < ar._priority[150][170]
  64. assert ar._priority[150][150] < ar._priority[170][170]
  65. assert ar._priority[150][150] < ar._priority[130][150]
  66. assert ar._priority[150][150] < ar._priority[150][130]
  67. assert ar._priority[150][150] < ar._priority[130][130]
  68. ## Test centerFirst
  69. def test_centerFirst_rectangular():
  70. ar = Arrange(400, 300, 200, 150, scale = 1)
  71. ar.centerFirst()
  72. assert ar._priority[150][200] < ar._priority[150][220]
  73. assert ar._priority[150][200] < ar._priority[170][200]
  74. assert ar._priority[150][200] < ar._priority[170][220]
  75. assert ar._priority[150][200] < ar._priority[180][150]
  76. assert ar._priority[150][200] < ar._priority[130][200]
  77. assert ar._priority[150][200] < ar._priority[130][180]
  78. ## Test centerFirst
  79. def test_centerFirst_rectangular2():
  80. ar = Arrange(10, 20, 5, 10, scale = 1)
  81. ar.centerFirst()
  82. print(ar._priority)
  83. assert ar._priority[10][5] < ar._priority[10][7]
  84. ## Test backFirst
  85. def test_backFirst():
  86. ar = Arrange(300, 300, 150, 150, scale = 1)
  87. ar.backFirst()
  88. assert ar._priority[150][150] < ar._priority[170][150]
  89. assert ar._priority[150][150] < ar._priority[170][170]
  90. assert ar._priority[150][150] > ar._priority[130][150]
  91. assert ar._priority[150][150] > ar._priority[130][130]
  92. ## See if the result of bestSpot has the correct form
  93. def test_smoke_bestSpot():
  94. ar = Arrange(30, 30, 15, 15, scale = 1)
  95. ar.centerFirst()
  96. shape_arr = gimmeShapeArray()
  97. best_spot = ar.bestSpot(shape_arr)
  98. assert hasattr(best_spot, "x")
  99. assert hasattr(best_spot, "y")
  100. assert hasattr(best_spot, "penalty_points")
  101. assert hasattr(best_spot, "priority")
  102. ## Real life test
  103. def test_bestSpot():
  104. ar = Arrange(16, 16, 8, 8, scale = 1)
  105. ar.centerFirst()
  106. shape_arr = gimmeShapeArray()
  107. best_spot = ar.bestSpot(shape_arr)
  108. assert best_spot.x == 0
  109. assert best_spot.y == 0
  110. ar.place(best_spot.x, best_spot.y, shape_arr)
  111. # Place object a second time
  112. best_spot = ar.bestSpot(shape_arr)
  113. assert best_spot.x is not None # we found a location
  114. assert best_spot.x != 0 or best_spot.y != 0 # it can't be on the same location
  115. ar.place(best_spot.x, best_spot.y, shape_arr)
  116. print(ar._occupied) # For debugging
  117. ## Real life test rectangular build plate
  118. def test_bestSpot_rectangular_build_plate():
  119. ar = Arrange(16, 40, 8, 20, scale = 1)
  120. ar.centerFirst()
  121. shape_arr = gimmeShapeArray()
  122. best_spot = ar.bestSpot(shape_arr)
  123. ar.place(best_spot.x, best_spot.y, shape_arr)
  124. assert best_spot.x == 0
  125. assert best_spot.y == 0
  126. # Place object a second time
  127. best_spot2 = ar.bestSpot(shape_arr)
  128. assert best_spot2.x is not None # we found a location
  129. assert best_spot2.x != 0 or best_spot2.y != 0 # it can't be on the same location
  130. ar.place(best_spot2.x, best_spot2.y, shape_arr)
  131. # Place object a 3rd time
  132. best_spot3 = ar.bestSpot(shape_arr)
  133. assert best_spot3.x is not None # we found a location
  134. assert best_spot3.x != best_spot.x or best_spot3.y != best_spot.y # it can't be on the same location
  135. assert best_spot3.x != best_spot2.x or best_spot3.y != best_spot2.y # it can't be on the same location
  136. ar.place(best_spot3.x, best_spot3.y, shape_arr)
  137. best_spot_x = ar.bestSpot(shape_arr)
  138. ar.place(best_spot_x.x, best_spot_x.y, shape_arr)
  139. best_spot_x = ar.bestSpot(shape_arr)
  140. ar.place(best_spot_x.x, best_spot_x.y, shape_arr)
  141. best_spot_x = ar.bestSpot(shape_arr)
  142. ar.place(best_spot_x.x, best_spot_x.y, shape_arr)
  143. print(ar._occupied) # For debugging
  144. ## Real life test
  145. def test_bestSpot_scale():
  146. scale = 0.5
  147. ar = Arrange(16, 16, 8, 8, scale = scale)
  148. ar.centerFirst()
  149. shape_arr = gimmeShapeArray(scale)
  150. best_spot = ar.bestSpot(shape_arr)
  151. assert best_spot.x == 0
  152. assert best_spot.y == 0
  153. ar.place(best_spot.x, best_spot.y, shape_arr)
  154. print(ar._occupied)
  155. # Place object a second time
  156. best_spot = ar.bestSpot(shape_arr)
  157. assert best_spot.x is not None # we found a location
  158. assert best_spot.x != 0 or best_spot.y != 0 # it can't be on the same location
  159. ar.place(best_spot.x, best_spot.y, shape_arr)
  160. print(ar._occupied) # For debugging
  161. ## Real life test
  162. def test_bestSpot_scale_rectangular():
  163. scale = 0.5
  164. ar = Arrange(16, 40, 8, 20, scale = scale)
  165. ar.centerFirst()
  166. shape_arr = gimmeShapeArray(scale)
  167. shape_arr_square = gimmeShapeArraySquare(scale)
  168. best_spot = ar.bestSpot(shape_arr_square)
  169. assert best_spot.x == 0
  170. assert best_spot.y == 0
  171. ar.place(best_spot.x, best_spot.y, shape_arr_square)
  172. print(ar._occupied)
  173. # Place object a second time
  174. best_spot = ar.bestSpot(shape_arr)
  175. assert best_spot.x is not None # we found a location
  176. assert best_spot.x != 0 or best_spot.y != 0 # it can't be on the same location
  177. ar.place(best_spot.x, best_spot.y, shape_arr)
  178. best_spot = ar.bestSpot(shape_arr_square)
  179. ar.place(best_spot.x, best_spot.y, shape_arr_square)
  180. print(ar._occupied) # For debugging
  181. ## Try to place an object and see if something explodes
  182. def test_smoke_place():
  183. ar = Arrange(30, 30, 15, 15)
  184. ar.centerFirst()
  185. shape_arr = gimmeShapeArray()
  186. assert not numpy.any(ar._occupied)
  187. ar.place(0, 0, shape_arr)
  188. assert numpy.any(ar._occupied)
  189. ## See of our center has less penalty points than out of the center
  190. def test_checkShape():
  191. ar = Arrange(30, 30, 15, 15)
  192. ar.centerFirst()
  193. shape_arr = gimmeShapeArray()
  194. points = ar.checkShape(0, 0, shape_arr)
  195. points2 = ar.checkShape(5, 0, shape_arr)
  196. points3 = ar.checkShape(0, 5, shape_arr)
  197. assert points2 > points
  198. assert points3 > points
  199. ## See of our center has less penalty points than out of the center
  200. def test_checkShape_rectangular():
  201. ar = Arrange(20, 30, 10, 15)
  202. ar.centerFirst()
  203. print(ar._priority)
  204. shape_arr = gimmeShapeArray()
  205. points = ar.checkShape(0, 0, shape_arr)
  206. points2 = ar.checkShape(5, 0, shape_arr)
  207. points3 = ar.checkShape(0, 5, shape_arr)
  208. assert points2 > points
  209. assert points3 > points
  210. ## Check that placing an object on occupied place returns None.
  211. def test_checkShape_place():
  212. ar = Arrange(30, 30, 15, 15)
  213. ar.centerFirst()
  214. shape_arr = gimmeShapeArray()
  215. points = ar.checkShape(3, 6, shape_arr)
  216. ar.place(3, 6, shape_arr)
  217. points2 = ar.checkShape(3, 6, shape_arr)
  218. assert points2 is None
  219. ## Test the whole sequence
  220. def test_smoke_place_objects():
  221. ar = Arrange(20, 20, 10, 10, scale = 1)
  222. ar.centerFirst()
  223. shape_arr = gimmeShapeArray()
  224. for i in range(5):
  225. best_spot_x, best_spot_y, score, prio = ar.bestSpot(shape_arr)
  226. ar.place(best_spot_x, best_spot_y, shape_arr)
  227. # Test some internals
  228. def test_compare_occupied_and_priority_tables():
  229. ar = Arrange(10, 15, 5, 7)
  230. ar.centerFirst()
  231. assert ar._priority.shape == ar._occupied.shape
  232. ## Polygon -> array
  233. def test_arrayFromPolygon():
  234. vertices = numpy.array([[-3, 1], [3, 1], [0, -3]])
  235. array = ShapeArray.arrayFromPolygon([5, 5], vertices)
  236. assert numpy.any(array)
  237. ## Polygon -> array
  238. def test_arrayFromPolygon2():
  239. vertices = numpy.array([[-3, 1], [3, 1], [2, -3]])
  240. array = ShapeArray.arrayFromPolygon([5, 5], vertices)
  241. assert numpy.any(array)
  242. ## Polygon -> array
  243. def test_fromPolygon():
  244. vertices = numpy.array([[0, 0.5], [0, 0], [0.5, 0]])
  245. array = ShapeArray.fromPolygon(vertices, scale=0.5)
  246. assert numpy.any(array.arr)
  247. ## Line definition -> array with true/false
  248. def test_check():
  249. base_array = numpy.zeros([5, 5], dtype=float)
  250. p1 = numpy.array([0, 0])
  251. p2 = numpy.array([4, 4])
  252. check_array = ShapeArray._check(p1, p2, base_array)
  253. assert numpy.any(check_array)
  254. assert check_array[3][0]
  255. assert not check_array[0][3]
  256. ## Line definition -> array with true/false
  257. def test_check2():
  258. base_array = numpy.zeros([5, 5], dtype=float)
  259. p1 = numpy.array([0, 3])
  260. p2 = numpy.array([4, 3])
  261. check_array = ShapeArray._check(p1, p2, base_array)
  262. assert numpy.any(check_array)
  263. assert not check_array[3][0]
  264. assert check_array[3][4]
  265. ## Just adding some stuff to ensure fromNode works as expected. Some parts should actually be in UM
  266. def test_parts_of_fromNode():
  267. from UM.Math.Polygon import Polygon
  268. p = Polygon(numpy.array([[-2, -2], [2, -2], [2, 2], [-2, 2]], dtype=numpy.int32))
  269. offset = 1
  270. print(p._points)
  271. p_offset = p.getMinkowskiHull(Polygon.approximatedCircle(offset))
  272. print("--------------")
  273. print(p_offset._points)
  274. assert len(numpy.where(p_offset._points[:, 0] >= 2.9)) > 0
  275. assert len(numpy.where(p_offset._points[:, 0] <= -2.9)) > 0
  276. assert len(numpy.where(p_offset._points[:, 1] >= 2.9)) > 0
  277. assert len(numpy.where(p_offset._points[:, 1] <= -2.9)) > 0
  278. def test_parts_of_fromNode2():
  279. from UM.Math.Polygon import Polygon
  280. p = Polygon(numpy.array([[-2, -2], [2, -2], [2, 2], [-2, 2]], dtype=numpy.int32) * 2) # 4x4
  281. offset = 13.3
  282. scale = 0.5
  283. p_offset = p.getMinkowskiHull(Polygon.approximatedCircle(offset))
  284. shape_arr1 = ShapeArray.fromPolygon(p._points, scale = scale)
  285. shape_arr2 = ShapeArray.fromPolygon(p_offset._points, scale = scale)
  286. assert shape_arr1.arr.shape[0] >= (4 * scale) - 1 # -1 is to account for rounding errors
  287. assert shape_arr2.arr.shape[0] >= (2 * offset + 4) * scale - 1