0

dirtytile trees can now iterate at any level

Fixed some broken tests too.
This commit is contained in:
Andrew Brown
2011-11-20 10:50:37 -05:00
parent 83663733af
commit c6b56030ec
2 changed files with 37 additions and 13 deletions

View File

@@ -621,7 +621,8 @@ class DirtyTiles(object):
""" """
# Stores the depth of the tree according to this node. This is not the # Stores the depth of the tree according to this node. This is not the
# depth of this node, but rather the number of levels below this node. # depth of this node, but rather the number of levels below this node
# (including this node).
self.depth = depth self.depth = depth
# the self.children array holds the 4 children of this node. This # the self.children array holds the 4 children of this node. This
@@ -697,21 +698,31 @@ class DirtyTiles(object):
if all(x is True for x in self.children): if all(x is True for x in self.children):
return True return True
def iterate_dirty(self, depth=None): def iterate_dirty(self, level=None):
"""Returns an iterator over every dirty tile in this subtree. Each item """Returns an iterator over every dirty tile in this subtree. Each item
yielded is a sequence of integers representing the quadtree path to the yielded is a sequence of integers representing the quadtree path to the
dirty tile. Yielded sequences are of length self.depth. dirty tile. Yielded sequences are of length self.depth.
If zoom is None, iterates over tiles of the highest level, i.e. If level is None, iterates over tiles of the highest level, i.e.
worldtiles. If zoom is a value between 0 and the depth, iterates over worldtiles. If level is a value between 0 and the depth of this tree,
tiles at that zoom level. Zoom level 0 is zoomed all the way out, zoom this method iterates over tiles at that level. Zoom level 0 is zoomed
level `depth` is all the way in. all the way out, zoom level `depth` is all the way in.
In other words, specifying level causes the tree to be iterated as if
it was only that depth.
""" """
return (tuple(reversed(rpath)) for rpath in self._iterate_dirty_helper()) if level is None:
todepth = 1
else:
if not (level > 0 and level <= self.depth):
raise ValueError("Level parameter must be between 1 and %s" % self.depth)
todepth = self.depth - level + 1
def _iterate_dirty_helper(self): return (tuple(reversed(rpath)) for rpath in self._iterate_dirty_helper(todepth))
if self.depth == 1:
def _iterate_dirty_helper(self, todepth):
if self.depth == todepth:
# Base case # Base case
if self.children[0]: yield [0] if self.children[0]: yield [0]
if self.children[1]: yield [1] if self.children[1]: yield [1]
@@ -723,13 +734,13 @@ class DirtyTiles(object):
for c, child in enumerate(self.children): for c, child in enumerate(self.children):
if child == True: if child == True:
# All dirty down this subtree, iterate over every leaf # All dirty down this subtree, iterate over every leaf
for x in iterate_base4(self.depth-1): for x in iterate_base4(self.depth-todepth):
x = list(x) x = list(x)
x.append(c) x.append(c)
yield x yield x
elif child != False: elif child != False:
# Mixed dirty/clean down this subtree, recurse # Mixed dirty/clean down this subtree, recurse
for path in child._iterate_dirty_helper(): for path in child._iterate_dirty_helper(todepth):
path.append(c) path.append(c)
yield path yield path

View File

@@ -59,6 +59,19 @@ class DirtyTilesTest(unittest.TestCase):
# Make sure they were all returned # Make sure they were all returned
self.assertEqual(len(dirty), 0) self.assertEqual(len(dirty), 0)
def test_iterate_levelmax(self):
"""Same as test_iterate, but specifies the level explicitly"""
dirty = set(self.dirty_paths)
for p in self.tree.iterate_dirty(3):
# Can't use assertIn, was only added in 2.7
self.assertTrue(p in dirty)
# Should not see this one again
dirty.remove(p)
# Make sure they were all returned
self.assertEqual(len(dirty), 0)
def test_iterate_fail(self): def test_iterate_fail(self):
"""Meta-test: Make sure test_iterate() would actually fail""" """Meta-test: Make sure test_iterate() would actually fail"""
# if an extra item were returned""" # if an extra item were returned"""
@@ -114,7 +127,7 @@ class DirtyTilesTest(unittest.TestCase):
for p in self.tree.iterate_dirty(2): for p in self.tree.iterate_dirty(2):
self.assertTrue(p in l2, "%s was not supposed to be returned!" % (p,)) self.assertTrue(p in l2, "%s was not supposed to be returned!" % (p,))
l2.remove(p) l2.remove(p)
self.assertEqual(len(dirty), 0, "Never iterated over these items: %s" % l2) self.assertEqual(len(l2), 0, "Never iterated over these items: %s" % l2)
# level 1 # level 1
l1 = set() l1 = set()
@@ -123,7 +136,7 @@ class DirtyTilesTest(unittest.TestCase):
for p in self.tree.iterate_dirty(1): for p in self.tree.iterate_dirty(1):
self.assertTrue(p in l1, "%s was not supposed to be returned!" % (p,)) self.assertTrue(p in l1, "%s was not supposed to be returned!" % (p,))
l1.remove(p) l1.remove(p)
self.assertEqual(len(dirty), 0, "Never iterated over these items: %s" % l1) self.assertEqual(len(l1), 0, "Never iterated over these items: %s" % l1)
if __name__ == "__main__": if __name__ == "__main__":
unittest.main() unittest.main()