用于存储嵌套框的数据结构?

时间:2013-01-11 07:05:36

标签: python algorithm data-structures geospatial r-tree

我有一个存储为点的矩形列表。目前,数据看起来像这样:

boxes = [{'p1': (0,0), 'p2': (100,20)},
         {'p1': (5,5), 'p2': (15,15)}, 
         {'p1': (20,5), 'p2': (30,15)},
         {'p1': (35,5), 'p2': (45,15)},
         {'p1': (70,5), 'p2': (80,15)}]

我还有一个基本功能,可以测试矩形是否包含在另一个矩形中:

def isChild(b1,b2):
    return (b1 != b2 and 
            (b1['p2'][0]-b1['p1'][0] * b1['p2'][1]-b1['p1'][1]) > (b2['p2'][0]-b2['p1'][0] * b2['p2'][1]-b2['p1'][1]) and
            b1['p1'][0] < b2['p2'][0] and 
            b1['p2'][0] > b2['p1'][0] and 
            b1['p1'][1] < b2['p2'][1] and 
            b1['p2'][1] > b2['p1'][1])

我想结束一组长方形和他们的孩子,但我不确定应该如何储存它们。我在想这样的事情:

[{'p1': (0,0), 
  'p2': (100,20),
  'children': [{'p1': (5,5), 'p2': (15,15)}, 
               {'p1': (20,5), 'p2': (30,15)},
               {'p1': (35,5), 'p2': (45,15)},
               {'p1': (70,5), 'p2': (80,15)}]}]

这样的上下文是框表示网页上的元素。数据结构用于生成基本标记,因此上面的结构最终将会是这样的:

<div>
    <div></div>
    <div></div>
    <div></div>
    <div></div>
</div>
  1. 源/目标数据结构是否适合这种情况?如果没有,那是什么?
  2. 我如何从源头到达目标?
  3. 一位朋友建议使用r-trees。这会有意义吗?

2 个答案:

答案 0 :(得分:3)

使用课程。这是OO编程的典型用例。创建一个Rectangle

from random import random

class Rectangle(object):
    def __init__(self, x1, y1, x2, y2):
        self._p1 = (x1, y1)
        self._p2 = (x2,y2)
        self._children = []

    def __str__(self):
        return "Rectangle defined by %s, %s, %i children" % (self._p1, self._p2, len(self._children))

    def is_child_of(self, other):
        return (self is not other and 
            self._p1[0] > other._p1[0] and 
            self._p2[0] < other._p2[0] and 
            self._p1[1] > other._p1[1] and 
            self._p2[1] < other._p2[1])

    def add_child(self, other):
        self._children.append(other)

    def check_relation_and_connect(self, other):
        if self.is_child_of(other):
            other.add_child(self)
        elif other.is_child_of(self):
            self.add_child(other)


if __name__=="__main__":
    rectangles = [Rectangle(random()*5, random()*5, random()*5+5, random()*5+5) for i in range(10)]

    for i in range(len(rectangles)):
        for j in range(i):
            rectangles[i].check_relation_and_connect(rectangles[j])

    for rectangle in rectangles:
        print rectangle

该类包含两个点,_p1和_p2,以及一个子列表。找到父子关系的逻辑进入了这个类的一个方法(顺便说一句,你的方法是否有效?我改变了它,因为它对我来说是无意义的。也许我对如何定义矩形有不同的理解。)

当你在谈论网站和<div>时,我假设你不会有数以千计的矩形。所以这种方法应该没问题。

此示例也可以扩展为绘制所有矩形,因此可以检查矩形和计算的亲缘关系。保持类Rectangle不变,可以写:

if __name__=="__main__":
    import matplotlib.pyplot as plt
    from matplotlib import patches

    rectangles = [Rectangle(random()*5, random()*5, random()*5+5, random()*5+5) for i in range(5)]

    for i in range(len(rectangles)):
        for j in range(i):
            rectangles[i].check_relation_and_connect(rectangles[j])

    for rectangle in rectangles:
        print rectangle

    colormap = plt.get_cmap("Paired")
    for i, rect in enumerate(rectangles):
        ax = plt.axes()
        color = colormap((1.*i)/len(rectangles))
        patch = patches.Rectangle(rect.p1, rect.p2[0]-rect.p1[0], rect.p2[1]-rect.p1[1], fc="none", ec=color, lw=2)
        ax.add_patch(patch)
    plt.xlim(-1,11)
    plt.ylim(-1,11)
    plt.show()

这给出了如下情节: enter image description here

对于这个例子,只有一个Rectangle有一个孩子(紫色是绿色的孩子)。

答案 1 :(得分:0)

四叉树或R树(或任何其他2维空间数据结构)将非常适合。但是如果你没有很多这样的嵌套框(数十或数百),你可以在每次需要查询数据结构时枚举它们。如果您有许多,数千或更多,并且需要有效地查询它们 - 使用空间数据结构。