5 def __init__(self, x=0.0, y=0.0, z=0.0):
11 return Vector3(self.x, self.y, self.z)
14 return Vector3(self.x, self.y, self.z)
17 return 'V[%s, %s, %s]' % ( self.x, self.y, self.z )
20 return Vector3( self.x + v.x, self.y + v.y, self.z + v.z )
23 return Vector3( self.x - v.x, self.y - v.y, self.z - v.z )
26 return Vector3( self.x * v, self.y * v, self.z * v )
29 return Vector3( self.x / v, self.y / v, self.z / v )
33 return Vector3( - self.x, - self.y, - self.z )
35 def __iadd__(self, v):
41 def __isub__(self, v):
47 def __imul__(self, v):
53 def __idiv__(self, v):
59 def almostEqual(self, v):
60 return (abs(self.x - v.x) + abs(self.y - v.y) + abs(self.z - v.z)) < 0.00001
63 return Vector3(self.y * v.z - self.z * v.y, -self.x * v.z + self.z * v.x, self.x * v.y - self.y * v.x)
66 return math.sqrt( self.x * self.x + self.y * self.y + self.z * self.z )
76 return Vector3(min(self.x, v.x), min(self.y, v.y), min(self.z, v.z))
79 return Vector3(max(self.x, v.x), max(self.y, v.y), max(self.z, v.z))
82 def __init__(self, vMin, vMax):
85 self.perimeter = numpy.sum(self.vMax - self.vMin)
87 def combine(self, aabb):
88 return AABB(numpy.minimum(self.vMin, aabb.vMin), numpy.maximum(self.vMax, aabb.vMax))
90 def overlap(self, aabb):
91 if aabb.vMin[0] - self.vMax[0] > 0.0 or aabb.vMin[1] - self.vMax[1] > 0.0 or aabb.vMin[2] - self.vMax[2] > 0.0:
93 if self.vMin[0] - aabb.vMax[0] > 0.0 or self.vMin[1] - aabb.vMax[1] > 0.0 or self.vMin[2] - aabb.vMax[2] > 0.0:
98 return "AABB:%s - %s" % (str(self.vMin), str(self.vMax))
100 class _AABBNode(object):
101 def __init__(self, aabb):
109 return self.child1 == None
111 class AABBTree(object):
115 def insert(self, aabb):
116 newNode = _AABBNode(aabb)
117 if self.root == None:
122 while not node.isLeaf():
126 area = node.aabb.perimeter
127 combinedAABB = node.aabb.combine(aabb)
128 combinedArea = combinedAABB.perimeter
130 cost = 2.0 * combinedArea
131 inheritanceCost = 2.0 * (combinedArea - area)
134 cost1 = aabb.combine(child1.aabb).perimeter + inheritanceCost
136 oldArea = child1.aabb.perimeter
137 newArea = aabb.combine(child1.aabb).perimeter
138 cost1 = (newArea - oldArea) + inheritanceCost
141 cost2 = aabb.combine(child1.aabb).perimeter + inheritanceCost
143 oldArea = child2.aabb.perimeter
144 newArea = aabb.combine(child2.aabb).perimeter
145 cost2 = (newArea - oldArea) + inheritanceCost
147 if cost < cost1 and cost < cost2:
157 # Create a new parent.
158 oldParent = sibling.parent
159 newParent = _AABBNode(aabb.combine(sibling.aabb))
160 newParent.parent = oldParent
161 newParent.height = sibling.height + 1
163 if oldParent != None:
164 # The sibling was not the root.
165 if oldParent.child1 == sibling:
166 oldParent.child1 = newParent
168 oldParent.child2 = newParent
170 newParent.child1 = sibling
171 newParent.child2 = newNode
172 sibling.parent = newParent
173 newNode.parent = newParent
175 # The sibling was the root.
176 newParent.child1 = sibling
177 newParent.child2 = newNode
178 sibling.parent = newParent
179 newNode.parent = newParent
180 self.root = newParent
182 # Walk back up the tree fixing heights and AABBs
183 node = newNode.parent
185 node = self._balance(node)
190 node.height = 1 + max(child1.height, child2.height)
191 node.aabb = child1.aabb.combine(child2.aabb)
195 def _balance(self, A):
196 if A.isLeaf() or A.height < 2:
202 balance = C.height - B.height
214 # A's old parent should point to C
216 if C.parent.child1 == A:
224 if F.height > G.height:
228 A.aabb = B.aabb.combine(G.aabb)
229 C.aabb = A.aabb.combine(F.aabb)
231 A.height = 1 + max(B.height, G.height)
232 C.height = 1 + max(A.height, F.height)
237 A.aabb = B.aabb.combine(F.aabb)
238 C.aabb = A.aabb.combine(G.aabb)
240 A.height = 1 + max(B.height, F.height)
241 C.height = 1 + max(A.height, G.height)
255 # A's old parent should point to B
257 if B.parent.child1 == A:
265 if D.height > E.height:
269 A.aabb = C.aabb.combine(E.aabb)
270 B.aabb = A.aabb.combine(D.aabb)
272 A.height = 1 + max(C.height, E.height)
273 B.height = 1 + max(A.height, D.height)
278 A.aabb = C.aabb.combine(D.aabb)
279 B.aabb = A.aabb.combine(E.aabb)
281 A.height = 1 + max(C.height, D.height)
282 B.height = 1 + max(A.height, E.height)
288 def query(self, aabb):
290 if self.root != None:
291 self._query(self.root, aabb, resultList)
294 def _query(self, node, aabb, resultList):
295 if not aabb.overlap(node.aabb):
298 resultList.append(node.aabb)
300 self._query(node.child1, aabb, resultList)
301 self._query(node.child2, aabb, resultList)
305 s += str(self.root.aabb)
308 if __name__ == '__main__':
310 tree.insert(AABB(Vector3(0,0,0), Vector3(0,0,0)))
311 tree.insert(AABB(Vector3(1,1,1), Vector3(1,1,1)))
312 tree.insert(AABB(Vector3(0.5,0.5,0.5), Vector3(0.5,0.5,0.5)))
314 print(tree.query(AABB(Vector3(0,0,0), Vector3(0,0,0))))