0

added a tree class to keep track of dirty tiles

This commit is contained in:
Andrew Brown
2011-10-30 00:14:03 -04:00
parent 96cf62bd14
commit ab53a9bd3e
3 changed files with 123 additions and 4 deletions

View File

@@ -379,7 +379,7 @@ dir but you forgot to put quotes around the directory, since it contains spaces.
# Create the quadtrees. There is one quadtree per rendermode requested, and # Create the quadtrees. There is one quadtree per rendermode requested, and
# therefore, per output directory hierarchy of tiles. Each quadtree # therefore, per output directory hierarchy of tiles. Each quadtree
# individually computes its depth and size. The constructor computes the # individually computes its depth and size. The constructor computes the
# depth of the tree, while the go() method re-arranges tiles if teh current # depth of the tree, while the go() method re-arranges tiles if the current
# depth differs from the computed depth. # depth differs from the computed depth.
q = [] q = []
qtree_args = {'depth' : options.zoom, qtree_args = {'depth' : options.zoom,

View File

@@ -500,3 +500,121 @@ class QuadtreeGen(object):
if self.optimizeimg: if self.optimizeimg:
optimize_image(imgpath, self.imgformat, self.optimizeimg) optimize_image(imgpath, self.imgformat, self.optimizeimg)
class DirtyTiles(object):
"""This tree holds which tiles need rendering.
Each instance is a node, and the root of a subtree.
Each node knows its "level", which corresponds to the zoom level where 0 is
the inner-most (most zoomed in) tiles.
Instances hold the clean/dirty state of their children. Leaf nodes are
images and do not physically exist in the tree, level 1 nodes keep track of
leaf image state. Level 2 nodes keep track of level 1 state, and so fourth.
In attempt to keep things memory efficient, subtrees that are completely
dirty are collapsed
"""
def __init__(self, level):
"""Initialize a new node of the tree at the specified level
"""
self.level = level
# the self.children array holds the 4 children of this node. This
# follows the same quadtree convention as elsewhere: children 0, 1, 2,
# 3 are the upper-left, upper-right, lower-left, and lower-right
# respectively
# Values are:
# False
# All children down this subtree are clean
# True
# All children down this subtree are dirty
# A DirtyTileTree instance
# the instance defines which children down that subtree are
# clean/dirty.
# A node with level=1 cannot have a DirtyTileTree instance in its
# children since its leaves are images, not more tree
self.children = [False] * 4
def set_dirty(self, path):
"""Marks the requested leaf node as "dirty".
Path is a list of integers representing the path to the leaf node
that is requested to be marked as dirty. Path must be presented in
reverse order (leaf node at index 0, root node at index -1)
If *all* the nodes below this one are dirty, this function returns
true. Otherwise, returns None.
"""
assert len(path) == self.level
if self.level == 1:
# Base case
self.children[path[0]] = True
# Check to see if all children are dirty
if all(self.children):
return True
else:
# Recursive case
if not isinstance(path,list):
path = list(path)
childnum = path.pop()
child = self.children[childnum]
if child == False:
# Create a new node
child = self.__class__(self.level-1)
child.set_dirty(path)
self.children[childnum] = child
elif child == True:
# Every child is already dirty. Nothing to do.
return
else:
# subtree is mixed clean/dirty. Recurse
ret = child.set_dirty(path)
if ret:
# Child says it's completely dirty, so we can purge the
# subtree and mark it as dirty. The subtree will be garbage
# collected when this method exits.
self.children[childnum] = True
# Since we've marked an entire sub-tree as dirty, we may be
# able to signal to our parent
if all(x is True for x in self.children):
return True
def iterate_dirty(self):
"""Returns an iterator over every dirty tile in this subtree. Each item
yielded is a sequence of integers representing the quadtree path to the
dirty tile. Yielded sequences are of length self.level.
Remember yielded paths are in reverse order. Leaf nodes at index 0!
"""
if self.level == 1:
# Base case
if self.children[0]: yield [0]
if self.children[1]: yield [1]
if self.children[2]: yield [2]
if self.children[3]: yield [3]
else:
# Higher levels:
for c, child in enumerate(self.children):
if child == True:
# All dirty down this subtree, iterate over every leaf
for x in quadtree.iterate_base4(self.level-1):
x = list(x)
x.append(c)
yield x
elif child != False:
# Mixed dirty/clean down this subtree, recurse
for path in child.iterate_dirty():
path.append(c)
yield path

View File

@@ -24,13 +24,13 @@ import logging
import cPickle import cPickle
import collections import collections
import itertools import itertools
import time
import numpy import numpy
from chunk import ChunkCorrupt import chunk
import nbt import nbt
import textures import textures
import time
""" """
This module has routines for extracting information about available worlds This module has routines for extracting information about available worlds
@@ -291,7 +291,7 @@ class World(object):
spawnY += 1 spawnY += 1
if spawnY == 128: if spawnY == 128:
break break
except ChunkCorrupt: except chunk.ChunkCorrupt:
#ignore corrupt spawn, and continue #ignore corrupt spawn, and continue
pass pass
self.POI.append( dict(x=disp_spawnX, y=spawnY, z=disp_spawnZ, self.POI.append( dict(x=disp_spawnX, y=spawnY, z=disp_spawnZ,
@@ -447,3 +447,4 @@ def get_worlds():
ret[info['Data']['LevelName']] = info['Data'] ret[info['Data']['LevelName']] = info['Data']
return ret return ret