1 from __future__ import absolute_import
7 numpy.seterr(all='ignore')
9 class printableObject(object):
12 self._position = numpy.array([0.0, 0.0])
13 self._matrix = numpy.matrix([[1,0,0],[0,1,0],[0,0,1]], numpy.float64)
14 self._transformedMin = None
15 self._transformedMax = None
16 self._transformedSize = None
17 self._boundaryCircleSize = None
18 self._drawOffset = None
22 ret = printableObject()
23 ret._matrix = self._matrix.copy()
24 ret._meshList = self._meshList[:]
25 ret._transformedMin = self._transformedMin
26 ret._transformedMax = self._transformedMin
27 ret._transformedSize = self._transformedSize
28 ret._boundaryCircleSize = self._boundaryCircleSize
29 ret._drawOffset = self._drawOffset
30 for m in ret._meshList:
36 self._meshList.append(m)
39 def _postProcessAfterLoad(self):
40 for m in self._meshList:
44 def applyMatrix(self, m):
48 def processMatrix(self):
49 self._transformedMin = numpy.array([999999999999,999999999999,999999999999], numpy.float64)
50 self._transformedMax = numpy.array([-999999999999,-999999999999,-999999999999], numpy.float64)
51 self._boundaryCircleSize = 0
53 for m in self._meshList:
54 transformedVertexes = (numpy.matrix(m.vertexes, copy = False) * numpy.matrix(self._matrix, numpy.float32)).getA()
55 transformedMin = transformedVertexes.min(0)
56 transformedMax = transformedVertexes.max(0)
57 for n in xrange(0, 3):
58 self._transformedMin[n] = min(transformedMin[n], self._transformedMin[n])
59 self._transformedMax[n] = max(transformedMax[n], self._transformedMax[n])
61 #Calculate the boundary circle
62 transformedSize = transformedMax - transformedMin
63 center = transformedMin + transformedSize / 2.0
64 boundaryCircleSize = round(math.sqrt(numpy.max(((transformedVertexes[::,0] - center[0]) * (transformedVertexes[::,0] - center[0])) + ((transformedVertexes[::,1] - center[1]) * (transformedVertexes[::,1] - center[1])) + ((transformedVertexes[::,2] - center[2]) * (transformedVertexes[::,2] - center[2])))), 3)
65 self._boundaryCircleSize = max(self._boundaryCircleSize, boundaryCircleSize)
66 self._transformedSize = self._transformedMax - self._transformedMin
67 self._drawOffset = (self._transformedMax + self._transformedMin) / 2
68 self._drawOffset[2] = self._transformedMin[2]
69 self._transformedMax -= self._drawOffset
70 self._transformedMin -= self._drawOffset
72 def getPosition(self):
74 def setPosition(self, newPos):
75 self._position = newPos
80 return self._transformedMax
82 return self._transformedMin
84 return self._transformedSize
85 def getDrawOffset(self):
86 return self._drawOffset
87 def getBoundaryCircle(self):
88 return self._boundaryCircleSize
90 def mirror(self, axis):
91 matrix = [[1,0,0], [0, 1, 0], [0, 0, 1]]
92 matrix[axis][axis] = -1
93 self.applyMatrix(numpy.matrix(matrix, numpy.float64))
97 numpy.linalg.norm(self._matrix[::,0].getA().flatten()),
98 numpy.linalg.norm(self._matrix[::,1].getA().flatten()),
99 numpy.linalg.norm(self._matrix[::,2].getA().flatten())], numpy.float64);
101 def setScale(self, scale, axis, uniform):
102 currentScale = numpy.linalg.norm(self._matrix[::,axis].getA().flatten())
103 scale /= currentScale
107 matrix = [[scale,0,0], [0, scale, 0], [0, 0, scale]]
109 matrix = [[1.0,0,0], [0, 1.0, 0], [0, 0, 1.0]]
110 matrix[axis][axis] = scale
111 self.applyMatrix(numpy.matrix(matrix, numpy.float64))
113 def setSize(self, size, axis, uniform):
114 scale = self.getSize()[axis]
119 matrix = [[scale,0,0], [0, scale, 0], [0, 0, scale]]
121 matrix = [[1,0,0], [0, 1, 0], [0, 0, 1]]
122 matrix[axis][axis] = scale
123 self.applyMatrix(numpy.matrix(matrix, numpy.float64))
125 def resetScale(self):
126 x = 1/numpy.linalg.norm(self._matrix[::,0].getA().flatten())
127 y = 1/numpy.linalg.norm(self._matrix[::,1].getA().flatten())
128 z = 1/numpy.linalg.norm(self._matrix[::,2].getA().flatten())
129 self.applyMatrix(numpy.matrix([[x,0,0],[0,y,0],[0,0,z]], numpy.float64))
131 def resetRotation(self):
132 x = numpy.linalg.norm(self._matrix[::,0].getA().flatten())
133 y = numpy.linalg.norm(self._matrix[::,1].getA().flatten())
134 z = numpy.linalg.norm(self._matrix[::,2].getA().flatten())
135 self._matrix = numpy.matrix([[x,0,0],[0,y,0],[0,0,z]], numpy.float64)
139 transformedVertexes = (numpy.matrix(self._meshList[0].vertexes, copy = False) * self._matrix).getA()
140 minZvertex = transformedVertexes[transformedVertexes.argmin(0)[2]]
143 for v in transformedVertexes:
144 diff = v - minZvertex
145 len = math.sqrt(diff[0] * diff[0] + diff[1] * diff[1] + diff[2] * diff[2])
148 dot = (diff[2] / len)
154 rad = -math.atan2(dotV[1], dotV[0])
155 self._matrix *= numpy.matrix([[math.cos(rad), math.sin(rad), 0], [-math.sin(rad), math.cos(rad), 0], [0,0,1]], numpy.float64)
156 rad = -math.asin(dotMin)
157 self._matrix *= numpy.matrix([[math.cos(rad), 0, math.sin(rad)], [0,1,0], [-math.sin(rad), 0, math.cos(rad)]], numpy.float64)
160 transformedVertexes = (numpy.matrix(self._meshList[0].vertexes, copy = False) * self._matrix).getA()
161 minZvertex = transformedVertexes[transformedVertexes.argmin(0)[2]]
164 for v in transformedVertexes:
165 diff = v - minZvertex
166 len = math.sqrt(diff[1] * diff[1] + diff[2] * diff[2])
169 dot = (diff[2] / len)
176 rad = math.asin(dotMin)
178 rad = -math.asin(dotMin)
179 self.applyMatrix(numpy.matrix([[1,0,0], [0, math.cos(rad), math.sin(rad)], [0, -math.sin(rad), math.cos(rad)]], numpy.float64))
181 def scaleUpTo(self, size):
182 vMin = self._transformedMin
183 vMax = self._transformedMax
185 scaleX1 = (size[0] / 2 - self._position[0]) / ((vMax[0] - vMin[0]) / 2)
186 scaleY1 = (size[1] / 2 - self._position[1]) / ((vMax[1] - vMin[1]) / 2)
187 scaleX2 = (self._position[0] + size[0] / 2) / ((vMax[0] - vMin[0]) / 2)
188 scaleY2 = (self._position[1] + size[1] / 2) / ((vMax[1] - vMin[1]) / 2)
189 scaleZ = size[2] / (vMax[2] - vMin[2])
190 print scaleX1, scaleY1, scaleX2, scaleY2, scaleZ
191 scale = min(scaleX1, scaleY1, scaleX2, scaleY2, scaleZ)
193 self.applyMatrix(numpy.matrix([[scale,0,0],[0,scale,0],[0,0,scale]], numpy.float64))
197 for oriMesh in self._meshList:
198 for m in oriMesh.split():
199 obj = printableObject()
200 obj._meshList.append(m)
201 obj._postProcessAfterLoad()
211 def _addFace(self, x0, y0, z0, x1, y1, z1, x2, y2, z2):
213 self.vertexes[n][0] = x0
214 self.vertexes[n][1] = y0
215 self.vertexes[n][2] = z0
217 self.vertexes[n][0] = x1
218 self.vertexes[n][1] = y1
219 self.vertexes[n][2] = z1
221 self.vertexes[n][0] = x2
222 self.vertexes[n][1] = y2
223 self.vertexes[n][2] = z2
224 self.vertexCount += 3
226 def _prepareFaceCount(self, faceNumber):
227 #Set the amount of faces before loading data in them. This way we can create the numpy arrays before we fill them.
228 self.vertexes = numpy.zeros((faceNumber*3, 3), numpy.float32)
229 self.normal = numpy.zeros((faceNumber*3, 3), numpy.float32)
232 def _calculateNormals(self):
233 #Calculate the normals
234 tris = self.vertexes.reshape(self.vertexCount / 3, 3, 3)
235 normals = numpy.cross( tris[::,1 ] - tris[::,0] , tris[::,2 ] - tris[::,0] )
236 lens = numpy.sqrt( normals[:,0]**2 + normals[:,1]**2 + normals[:,2]**2 )
241 n = numpy.zeros((self.vertexCount / 3, 9), numpy.float32)
245 self.normal = n.reshape(self.vertexCount, 3)
246 self.invNormal = -self.normal
248 def _vertexHash(self, idx):
249 v = self.vertexes[idx]
250 return int(v[0] * 100) | int(v[1] * 100) << 8 | int(v[2] * 100) << 16
252 def _idxFromHash(self, map, idx):
253 vHash = self._vertexHash(idx)
255 if numpy.linalg.norm(self.vertexes[i] - self.vertexes[idx]) < 0.001:
262 for idx in xrange(0, self.vertexCount):
263 print idx, self.vertexCount
264 vHash = self._vertexHash(idx)
265 if vHash not in vertexMap:
266 vertexMap[vHash] = []
267 vertexMap[vHash].append(idx)
268 vertexToFace.append([])
271 for idx in xrange(0, self.vertexCount, 3):
272 print idx, self.vertexCount
273 f = [self._idxFromHash(vertexMap, idx), self._idxFromHash(vertexMap, idx+1), self._idxFromHash(vertexMap, idx+2)]
274 vertexToFace[f[0]].append(idx / 3)
275 vertexToFace[f[1]].append(idx / 3)
276 vertexToFace[f[2]].append(idx / 3)
281 for idx in xrange(0, len(faceList)):
287 while len(todoList) > 0:
289 meshFaceList.append(idx)
290 for n in xrange(0, 3):
291 for i in vertexToFace[faceList[idx][n]]:
297 m._prepareFaceCount(len(meshFaceList))
298 for idx in meshFaceList:
299 m.vertexes[m.vertexCount] = self.vertexes[faceList[idx][0]]
301 m.vertexes[m.vertexCount] = self.vertexes[faceList[idx][1]]
303 m.vertexes[m.vertexCount] = self.vertexes[faceList[idx][2]]