chiark / gitweb /
Merge branch 'master' into SteamEngine
[cura.git] / Cura / util / objectScene.py
1 import random
2 import numpy
3
4 class Scene():
5         def __init__(self):
6                 self._objectList = []
7                 self._sizeOffsets = numpy.array([3.0,3.0], numpy.float32)
8                 self._machineSize = numpy.array([100,100,100], numpy.float32)
9
10         def setMachineSize(self, machineSize):
11                 self._machineSize = machineSize
12
13         def objects(self):
14                 return self._objectList
15
16         def add(self, obj):
17                 self._findFreePositionFor(obj)
18                 self._objectList.append(obj)
19                 self.pushFree()
20
21         def remove(self, obj):
22                 self._objectList.remove(obj)
23
24         def pushFree(self):
25                 n = 1000
26                 while self._pushFree():
27                         n -= 1
28                         if n < 0:
29                                 return
30
31         def arrangeAll(self):
32                 oldList = self._objectList
33                 self._objectList = []
34                 for obj in oldList:
35                         obj.setPosition(numpy.array([0,0], numpy.float32))
36                         self.add(obj)
37
38         def _pushFree(self):
39                 for a in self._objectList:
40                         for b in self._objectList:
41                                 if not self._checkHit(a, b):
42                                         continue
43                                 posDiff = a.getPosition() - b.getPosition()
44                                 if posDiff[0] == 0.0 and posDiff[1] == 0.0:
45                                         posDiff[1] = 1.0
46                                 if abs(posDiff[0]) > abs(posDiff[1]):
47                                         axis = 0
48                                 else:
49                                         axis = 1
50                                 aPos = a.getPosition()
51                                 bPos = b.getPosition()
52                                 center = (aPos[axis] + bPos[axis]) / 2
53                                 distance = (a.getSize()[axis] + b.getSize()[axis]) / 2 + 0.1 + self._sizeOffsets[axis] * 2
54                                 if posDiff[axis] < 0:
55                                         distance = -distance
56                                 aPos[axis] = center + distance / 2
57                                 bPos[axis] = center - distance / 2
58                                 a.setPosition(aPos)
59                                 b.setPosition(bPos)
60                                 return True
61                 return False
62
63         def _checkHit(self, a, b):
64                 if a == b:
65                         return False
66                 posDiff = a.getPosition() - b.getPosition()
67                 if abs(posDiff[0]) < (a.getSize()[0] + b.getSize()[0]) / 2 + self._sizeOffsets[0] * 2 and abs(posDiff[1]) < (a.getSize()[1] + b.getSize()[1]) / 2 + self._sizeOffsets[1] * 2:
68                         return True
69                 return False
70
71         def checkPlatform(self, obj):
72                 p = obj.getPosition()
73                 s = obj.getSize()[0:2] / 2 + self._sizeOffsets
74                 if p[0] - s[0] < -self._machineSize[0] / 2:
75                         return False
76                 if p[0] + s[0] > self._machineSize[0] / 2:
77                         return False
78                 if p[1] - s[1] < -self._machineSize[1] / 2:
79                         return False
80                 if p[1] + s[1] > self._machineSize[1] / 2:
81                         return False
82                 return True
83
84         def _findFreePositionFor(self, obj):
85                 posList = []
86                 for a in self._objectList:
87                         p = a.getPosition()
88                         s = (a.getSize()[0:2] + obj.getSize()[0:2]) / 2 + self._sizeOffsets * 2
89                         posList.append(p + s * ( 1, 1))
90                         posList.append(p + s * ( 0, 1))
91                         posList.append(p + s * (-1, 1))
92                         posList.append(p + s * ( 1, 0))
93                         posList.append(p + s * (-1, 0))
94                         posList.append(p + s * ( 1,-1))
95                         posList.append(p + s * ( 0,-1))
96                         posList.append(p + s * (-1,-1))
97
98                 best = None
99                 bestDist = None
100                 for p in posList:
101                         obj.setPosition(p)
102                         ok = True
103                         for a in self._objectList:
104                                 if self._checkHit(a, obj):
105                                         ok = False
106                                         break
107                         if not ok:
108                                 continue
109                         dist = numpy.linalg.norm(p)
110                         if not self.checkPlatform(obj):
111                                 dist *= 3
112                         if best is None or dist < bestDist:
113                                 best = p
114                                 bestDist = dist
115                 if best is not None:
116                         obj.setPosition(best)