chiark / gitweb /
Add option to save GCode file. Re-center the objects on the bed when you add a new...
[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                 self._headOffsets = numpy.array([18.0,18.0], numpy.float32)
10
11         def setMachineSize(self, machineSize):
12                 self._machineSize = machineSize
13
14         def objects(self):
15                 return self._objectList
16
17         def add(self, obj):
18                 self._findFreePositionFor(obj)
19                 self._objectList.append(obj)
20                 self.pushFree()
21
22         def remove(self, obj):
23                 self._objectList.remove(obj)
24
25         def pushFree(self):
26                 n = 1000
27                 while self._pushFree():
28                         n -= 1
29                         if n < 0:
30                                 return
31
32         def arrangeAll(self):
33                 oldList = self._objectList
34                 self._objectList = []
35                 for obj in oldList:
36                         obj.setPosition(numpy.array([0,0], numpy.float32))
37                         self.add(obj)
38
39         def centerAll(self):
40                 minPos = numpy.array([9999999,9999999], numpy.float32)
41                 maxPos = numpy.array([-9999999,-9999999], numpy.float32)
42                 for obj in self._objectList:
43                         pos = obj.getPosition()
44                         size = obj.getSize()
45                         minPos[0] = min(minPos[0], pos[0] - size[0] / 2)
46                         minPos[1] = min(minPos[1], pos[1] - size[1] / 2)
47                         maxPos[0] = max(maxPos[0], pos[0] + size[0] / 2)
48                         maxPos[1] = max(maxPos[1], pos[1] + size[1] / 2)
49                 offset = -(maxPos + minPos) / 2
50                 for obj in self._objectList:
51                         obj.setPosition(obj.getPosition() + offset)
52
53         def _pushFree(self):
54                 for a in self._objectList:
55                         for b in self._objectList:
56                                 if not self._checkHit(a, b):
57                                         continue
58                                 posDiff = a.getPosition() - b.getPosition()
59                                 if posDiff[0] == 0.0 and posDiff[1] == 0.0:
60                                         posDiff[1] = 1.0
61                                 if abs(posDiff[0]) > abs(posDiff[1]):
62                                         axis = 0
63                                 else:
64                                         axis = 1
65                                 aPos = a.getPosition()
66                                 bPos = b.getPosition()
67                                 center = (aPos[axis] + bPos[axis]) / 2
68                                 distance = (a.getSize()[axis] + b.getSize()[axis]) / 2 + 0.1 + self._sizeOffsets[axis] + self._headOffsets[axis]
69                                 if posDiff[axis] < 0:
70                                         distance = -distance
71                                 aPos[axis] = center + distance / 2
72                                 bPos[axis] = center - distance / 2
73                                 a.setPosition(aPos)
74                                 b.setPosition(bPos)
75                                 return True
76                 return False
77
78         def _checkHit(self, a, b):
79                 if a == b:
80                         return False
81                 posDiff = a.getPosition() - b.getPosition()
82                 if abs(posDiff[0]) < (a.getSize()[0] + b.getSize()[0]) / 2 + self._sizeOffsets[0] + self._headOffsets[0]:
83                         if abs(posDiff[1]) < (a.getSize()[1] + b.getSize()[1]) / 2 + self._sizeOffsets[1] + self._headOffsets[1]:
84                                 return True
85                 return False
86
87         def checkPlatform(self, obj):
88                 p = obj.getPosition()
89                 s = obj.getSize()[0:2] / 2 + self._sizeOffsets
90                 if p[0] - s[0] < -self._machineSize[0] / 2:
91                         return False
92                 if p[0] + s[0] > self._machineSize[0] / 2:
93                         return False
94                 if p[1] - s[1] < -self._machineSize[1] / 2:
95                         return False
96                 if p[1] + s[1] > self._machineSize[1] / 2:
97                         return False
98                 return True
99
100         def _findFreePositionFor(self, obj):
101                 posList = []
102                 for a in self._objectList:
103                         p = a.getPosition()
104                         s = (a.getSize()[0:2] + obj.getSize()[0:2]) / 2 + self._sizeOffsets + self._headOffsets
105                         posList.append(p + s * ( 1, 1))
106                         posList.append(p + s * ( 0, 1))
107                         posList.append(p + s * (-1, 1))
108                         posList.append(p + s * ( 1, 0))
109                         posList.append(p + s * (-1, 0))
110                         posList.append(p + s * ( 1,-1))
111                         posList.append(p + s * ( 0,-1))
112                         posList.append(p + s * (-1,-1))
113
114                 best = None
115                 bestDist = None
116                 for p in posList:
117                         obj.setPosition(p)
118                         ok = True
119                         for a in self._objectList:
120                                 if self._checkHit(a, obj):
121                                         ok = False
122                                         break
123                         if not ok:
124                                 continue
125                         dist = numpy.linalg.norm(p)
126                         if not self.checkPlatform(obj):
127                                 dist *= 3
128                         if best is None or dist < bestDist:
129                                 best = p
130                                 bestDist = dist
131                 if best is not None:
132                         obj.setPosition(best)