def do_supertile(lon, lat, zoom, size, margin=128): """render the supertile containing lon,lat int zoom is the GYM tile zoom level. size and margin are in pixels. """ tilesize = 256 # difference in zoom between tile and supertile dzoom = math.log(size / tilesize, 2) # build a grid where each cell is a supertile at the # target resolution, and look up the requested location within # that grid. stgrid = Grid.gym_tiles(zoom - dzoom) stx, sty = stgrid.ll2i(lon, lat) # get a grid for all tiles at the requested zoom level # that are contained in the supertile. tilegrid = stgrid.expand_tile(int(stx), int(sty), size/tilesize) # and get a grid for pixels within the supertile (this is the geoxf) pixelgrid = stgrid.expand_tile(int(stx), int(sty), size) # to handle boundary conditions, duplicate a margin around all # edges of the supertile. the step that requires the largest # margin is probably label placement? workgrid = pixelgrid.with_margin(margin) # request a directory for temporary files workdir = request_workdir(workgrid) # extract and render the supertile img = doit(workdir, workgrid) # clip off the margin (returning to pixelgrid) and save tiles # destdir should not be on the ramdisk destdir = os.path.join(workdir, 'tiles') if not os.path.isdir(destdir): os.makedirs(destdir) save_tiles(workdir, destdir, zoom, pixelgrid, img[margin:-margin,margin:-margin,:], tilesize) # save the whole thing as a tif for debugging save_raster('%s/geo.tif' % (workdir,), N.array(img*255, N.uint8), attrdict(grid=workgrid)) return img
def build_quarter(fn, info, data): """output an image at half resolution in both x and y. used to prepare for the next zoom level while the data is hot. """ # filter and downsample. could do this more gracefully with broadcasting? if len(data.shape) == 2: print "QD", data.shape, data.dtype data = ndimage.zoom(data, 0.5) print "QS", data.shape, data.dtype elif len(data.shape) == 3: print "QD", data.shape, data.dtype outshape = (data.shape[0] / 2, data.shape[1] / 2, data.shape[2]) data = N.dstack([ndimage.zoom(data[:, :, ci], 0.5) for ci in range(data.shape[2])]) print "QS", data.shape, data.dtype # should this be a convenience function in Grid? # double the scale of pixels in the output geoxf = [] + info.grid.geoxf() for i in (1, 2, 4, 5): geoxf[i] *= 2 qgrid = Grid(info.grid.srs(), geoxf=geoxf, shape=data.shape) save_raster(fn, data, {"grid": qgrid})
def doit(workdir, grid): extract_all(workdir, grid) # create surface lcf = '%s/mrlc' % (workdir,) if os.path.exists(lcf + '.tif'): sfcinfo, surface = load_mrlc(lcf + '.tif') else: sfcinfo, surface = load_quarters(lcf) #print 'SFCI', sfcinfo # get the hydrography #water = map_nhd(sfcinfo.grid) #print 'WWWWS', water.shape #glumpy_loop(water) demf = '%s/dem' % (workdir,) demtif = demf + '.tif' if os.path.exists(demtif): deminfo, demlayers = load_raster(demtif) else: deminfo, demlayers = load_quarters(lcf) dem = demlayers[0] # XXX handle missing values #glumpy_loop(surface) shaded = reliefshade(deminfo, dem, surface) #glumpy_loop(shaded) # test of grid tiling #for (z,ix,iy) in sfcinfo.grid.itertiles(): # print 'TILE %d %d %d' % (z, ix, iy) #print 'TIFF_HISTO', N.histogram(img, new=True) # if we don't have the DEM in a file (because we just composited it from quadrants), # save it to a file so it can be fed to gdal_contour if not os.path.exists(demtif): save_raster(deminfo, demtif, dem) if not os.path.isdir('%s/contour' % workdir): contour_find(demtif, '%s/contour' % workdir) if not os.path.isdir('%s/contourft' % (workdir,)): ContourTweaker().filter('%s/contour' % (workdir,), '%s/contourft' % (workdir,)) feats = render_layer(workdir, 'features', grid, ['nhd_flowline', 'nhd_waterbody', 'nhd_area', 'osm_line', 'contours']) fills = render_layer(workdir, 'fills', grid, ['contours', 'nhd_flowline', 'nhd_waterbody', 'nhd_area', 'osm_line']) labels = render_layer(workdir, 'labels', grid, ['contours', 'nhd_flowline', 'nhd_waterbody', 'nhd_area', 'osm_line']) # add contour labels and features img = asum(shaded, halo_mask(feats, labels)) img = asum(img, fills) img = asum(img, labels) # build half-resolution versions for next zoom level #if not os.path.isdir('%s/quarter' % (workdir,)): # os.mkdir('%s/quarter' % (workdir,)) # XXX doesn't do anything right now parentgrid = sfcinfo.grid # XXX need to figure these out based on ix%2, iy%2 at some zoom? is_east = 0 is_north = 0 quadrant = [['sw', 'se'], ['nw', 'ne']][is_north][is_east] mrlcdir = request_workdir(parentgrid, 'mrlc') build_quarter('%s/%s.tif' % (mrlcdir,quadrant), sfcinfo, surface) demdir = request_workdir(parentgrid, 'dem') build_quarter('%s/%s.tif' % (demdir,quadrant), deminfo, dem) return img