import wx from time import time from mathtools import ifloor class TileCoord: def __init__(self, x, y, zoom): self.x = ifloor(x) self.y = ifloor(y) self.zoom = zoom def __hash__(self): return hash(self.x) ^ hash(self.y) ^ hash(self.zoom) def __eq__(self, other): return self.x == other.x and self.y == other.y and self.zoom == other.zoom def __repr__(self): return "TileCoord(%d, %d, %d)" % (self.x, self.y, self.zoom) class TileManager: upkeep_interval = 0.25 upkeep_last = 0.0 def __init__(self, zoomlevels = (1,2,4,8,16), tilesize = (256, 256)): self.fetchers = [] self.zoomlevels = zoomlevels self.tilesize = tilesize tile_w, tile_h = self.tilesize self.emptytile = wx.EmptyImage(tile_w, tile_h) def upkeep(self): if self.upkeep_last + self.upkeep_interval < time(): self.upkeep_last = time() for fetcher in self.fetchers: fetcher.upkeep() def push_back(self, coords, image): '''Put a tile in caches. This should not be called for tiles that are returned through get_tile.''' for fetcher in self.fetchers: fetcher.put_tile(coords, image) def has_tile(self, coords): #if coords.zoom not in self.zoomlevels: #return False for fetcher in self.fetchers: if fetcher.has_tile(coords): return True else: return False def get_tile(self, coords, block = False): '''Returns wx.Image, or None if the tile is not yet available. Returns an all-black image if the tile won't be available in future either. ''' #assert coords.zoom in self.zoomlevels self.upkeep() if not self.has_tile(coords): return self.emptytile for fetcher in self.fetchers: image = fetcher.get_tile(coords, block) if image: break else: return None # Put the image in caches that are above the used fetcher idx = self.fetchers.index(fetcher) for fetcher in self.fetchers[:idx]: fetcher.put_tile(coords, image) return image