我正在开发一个简单的四叉树实现来进行圆圈的碰撞检测。现在插入的逻辑是:
1)检查节点是否有子树。
2)如果它有子树,请使用_get_index()
确定子项应附加到哪个子树。如果返回-1,则子节点将附加到父节点。
3)如果节点没有子树,则将子节点附加到父节点。
为了检索,我应该只检索我在遍历树时遇到的父节点的子节点,以及最后的叶子节点。
逻辑是:
1)将父节点的子节点放入列表中。
2)检查我想找到邻居的目标索引。
3)以递归方式调用该节点上的retrieve_neighbors()
。
然而,当我运行代码时,我发现我总是使用retrieve_neighbors()
返回树中的每个对象,从而无法将所有内容存储在四叉树中。
可能会想到的第一个问题是,当我split()
节点时,孩子们没有被删除,所以每个孩子也在父节点中 - 但是,只需计算数量在树上的孩子们,似乎并不是一种冗余。
代码如下:
class Quadtree(object):
"""
A simple Quadtree implementation. This works with any child object that has a get_position() method that returns a list
or tuple.
"""
def __init__(self, depth, min_x, min_y, max_x, max_y):
self.depth = depth
self.max_depth = 8
self.min_x = min_x
self.max_x = max_x
self.mid_x = (max_x - min_x) / 2.0
self.min_y = min_y
self.max_y = max_y
self.mid_y = (max_y - min_y) / 2.0
self.has_children = False
self.max_children = 4
self.children = []
self.subtrees = []
def _get_index(self, child):
"""
Returns the index of the node that the object belongs to. Returns -1 if the object does not exist in the tree.
"""
index = -1
child_position = child.get_position()
child_radius = child.get_radius()
if len(child_position) != 2:
print "Quadtree is only designed to handle two-dimensional objects! Object will not be added."
return index
#check if it fits in the top or bottom
is_in_top_quadrant = child_position[1] - child_radius > self.mid_y and child_position[1] + child_radius < self.max_y
#check if it fits left
if child_position[0] + child_radius < self.mid_x and child_position[0] - child_radius > self.min_x:
if is_in_top_quadrant:
index = 1
else:
index = 2
#check if it fits right
if child_position[0] - child_radius > self.mid_x and child_position[0] + child_radius < self.mid_x:
if is_in_top_quadrant:
index = 0
else:
index = 3
return index
def insert(self, new_child):
"""
Insert an object into the tree. Returns True if the insert was successful, False otherwise.
"""
index = self._get_index(new_child)
if index != -1 and self.subtrees:
self.subtrees[index].insert(new_child)
return True
else:
#if no subtrees exist, add the child to the child list.
self.children.append(new_child)
#and then check if we need to split the tree
#if there are more than the max children, and we haven't maxed out the tree depth, and there are no subtrees yet
if len(self.children) > self.max_children and self.depth < self.max_depth and not self.subtrees:
#create new subtree lists
self.split()
#iterate over all chidren in this node
for child in self.children:
index = self._get_index(child)
if index != -1:
self.children.remove(child)
self.subtrees[index].insert(child)
return True
def retrieve_neighbors(self, child):
"""
Retrieve all children from the same leaf as the target child.
"""
index = self._get_index(child)
neighbors = []
neighbors += self.children
if self.subtrees and index != -1:
neighbors += self.subtrees[index].retrieve_neighbors(child)
return neighbors
def split(self):
"""
Split the trees into four subtrees.
"""
#top right
self.subtrees.append(Quadtree(self.depth + 1, self.mid_x, self.mid_y, self.max_x, self.max_y))
#top left
self.subtrees.append(Quadtree(self.depth + 1, self.min_x, self.mid_y, self.mid_x, self.max_y))
#bottom left
self.subtrees.append(Quadtree(self.depth + 1, self.min_x, self.min_y, self.mid_x, self.mid_y))
#bottom right
self.subtrees.append(Quadtree(self.depth + 1, self.mid_x, self.min_y, self.max_x, self.mid_y))
任何人都可以帮我弄清楚为什么我的四胞胎会让很多孩子回来吗?
谢谢!