import wx from math import floor, ceil from tilecache import TileCoord def intfloor(value): return int(floor(value)) def intceil(value): return int(ceil(value)) class MapPanel(wx.Panel): def __init__(self, parent, tilecache): wx.Panel.__init__(self, parent) self.mapzoom = 3 self.mapx = 1.0 self.mapy = 1.0 self.tilecache = tilecache self.missingtiles = [] self.Bind(wx.EVT_PAINT, self.OnPaint) def Reposition(self): self.Refresh() def OnPaint(self, evt): dc = wx.PaintDC(self) newmissingtiles = [] for coords in self._gettilesinarea(self.GetClientRect()): drawpos = self._gettiledrawpos(coords) if self.IsExposedRect(drawpos) or coords in self.missingtiles: if not self._drawtile(dc, coords, drawpos): newmissingtiles.append(coords) self.missingtiles = newmissingtiles if self.missingtiles: wx.FutureCall(500, self.Refresh) def _gettilesinarea(self, area): # The size of tiles tile_w, tile_h = self.tilecache.tilesize # The tile-coordinates of the upper left corner tilepos_x = self.mapx + float(area.x) / tile_w tilepos_y = self.mapy + float(area.y) / tile_h # The location of the upper left tile outside the area offset_x = (tilepos_x % 1.) * tile_w offset_y = (tilepos_y % 1.) * tile_h # How many tiles? tilecount_x = intceil(float(area.width + offset_x) / tile_w) tilecount_y = intceil(float(area.height + offset_y) / tile_h) for x in range(tilecount_x): for y in range(tilecount_y): curtilepos_x = intfloor(tilepos_x) + x curtilepos_y = intfloor(tilepos_y) + y yield TileCoord(curtilepos_x, curtilepos_y, self.mapzoom) def _gettiledrawpos(self, coords): # The size of tiles tile_w, tile_h = self.tilecache.tilesize # The location of the upper left tile outside the window offset_x = (self.mapx % 1.) * tile_w offset_y = (self.mapy % 1.) * tile_h # The position to draw to pos_x = tile_w * (coords.x - intfloor(self.mapx)) - offset_x pos_y = tile_h * (coords.y - intfloor(self.mapy)) - offset_y return wx.Rect(pos_x, pos_y, tile_w, tile_h) def _drawtile(self, dc, coords, rect): image = self.tilecache.getTile(coords) if not image: dc.SetBrush(wx.Brush("WHITE")) dc.SetPen(wx.Pen("GRAY")) dc.DrawRectangleRect(rect) return False bitmap = image.ConvertToBitmap() dc.DrawBitmap(bitmap, rect.x, rect.y) return True