递归检索四叉树中的邻居

时间:2015-02-22 19:59:59

标签: python algorithm data-structures collision-detection quadtree

我正在开发一个简单的四叉树实现来进行圆圈的碰撞检测。现在插入的逻辑是:

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))

任何人都可以帮我弄清楚为什么我的四胞胎会让很多孩子回来吗?

谢谢!

0 个答案:

没有答案