def test_corner_overlap(self): # a box around the corner of a tile should return the four # neighbours of that tile. from tilequeue.query.rawr import _tiles from raw_tiles.tile import Tile from raw_tiles.util import bbox_for_tile tile = Tile(15, 5241, 12665) zoom = tile.z tile_bbox = bbox_for_tile(tile.z, tile.x, tile.y) # extract the top left corner x = tile_bbox[0] y = tile_bbox[3] # make a small bounding box around that w = 10 unpadded_bounds = (x - w, y - w, x + w, y + w) tiles = set(_tiles(zoom, unpadded_bounds)) expected = set() for dx in (0, -1): for dy in (0, -1): expected.add(Tile(tile.z, tile.x + dx, tile.y + dy)) self.assertEquals(expected, tiles)
def test_coverage_point(self): # test the coverage of a simple point object, which will generally be # a single tile, unless it's on the border of two tiles, or the corner # of 4. from raw_tiles.tile import Tile, shape_tile_coverage from shapely.geometry.point import Point # -122.4112, 37.7454 pt = Point(-13626752.45, 4543521.54) cov = shape_tile_coverage(pt, 16, Tile(0, 0, 0)) self.assertEquals(1, len(cov)) self.assertEquals(set([Tile(16, 10483, 25337)]), cov)
def test_coverage_pyramid(self): # test that the coverage of a tile over its own shape at a different # zoom returns all the tiles at the base of the pyramid. from raw_tiles.tile import Tile, shape_tile_coverage t = Tile(10, 255, 123) cov = shape_tile_coverage(t.as_shapely(), 12, t) self.assertEquals(16, len(cov)) expected = set() for x in range(1020, 1024): for y in range(492, 496): expected.add(Tile(12, x, y)) self.assertEquals(expected, cov)
def _tiles(zoom, unpadded_bounds): from tilequeue.tile import mercator_point_to_coord_fractional from raw_tiles.tile import Tile import math minx, miny, maxx, maxy = unpadded_bounds topleft = mercator_point_to_coord_fractional(zoom, minx, maxy) bottomright = mercator_point_to_coord_fractional(zoom, maxx, miny) # make sure that the bottom right coordinate is below and to the right # of the top left coordinate. it can happen that the coordinates are # mixed up due to small numerical precision artefacts being enlarged # by the conversion to integer and y-coordinate flip. assert topleft.zoom == bottomright.zoom minx = min(topleft.column, bottomright.column) maxx = max(topleft.column, bottomright.column) miny = min(topleft.row, bottomright.row) maxy = max(topleft.row, bottomright.row) eps = 1.0e-5 minx = _snapping_round(minx, eps, math.floor) maxx = _snapping_round(maxx, eps, math.ceil) miny = _snapping_round(miny, eps, math.floor) maxy = _snapping_round(maxy, eps, math.ceil) for x in range(minx, maxx): for y in range(miny, maxy): tile = Tile(zoom, x, y) yield tile
def test_coverage_null_island(self): # null island at (0, 0) should hit 4 tiles, since it's on the corner. from raw_tiles.tile import Tile, shape_tile_coverage from shapely.geometry.point import Point pt = Point(0, 0) cov = shape_tile_coverage(pt, 16, Tile(0, 0, 0)) self.assertEquals(4, len(cov)) expected = set([ Tile(16, 32767, 32767), Tile(16, 32767, 32768), Tile(16, 32768, 32767), Tile(16, 32768, 32768), ]) self.assertEquals(expected, cov)
def _make_stub_rawr_tile(self): from raw_tiles.tile import Tile props = dict( all_formatted_data=[], tile=Tile(3, 2, 1), ) return type('stub-rawr-tile', (), props)
def test_osm_source(self): from raw_tiles.source.osm import OsmSource from raw_tiles.tile import Tile reader = MockTableReader() src = OsmSource() locations, timing = src(reader, Tile(0, 0, 0)) self.assertEquals([ 'planet_osm_point', 'planet_osm_line', 'planet_osm_polygon', 'planet_osm_ways', 'planet_osm_rels', ], [l.name for l in locations]) for l in locations: self.assertEquals([], l.records) # should have 6 executions of templates - one for each table, plus one # for "setup.sql" expected_executions = [ ('base_table.sql', ['st_box2d']), # planet_osm_point ('base_table.sql', ['st_box2d']), # planet_osm_line ('base_table.sql', ['st_box2d']), # planet_osm_polygon ('setup.sql', ['box']), ('ways.sql', []), ('relations.sql', []), ] self.assertEquals(len(expected_executions), len(reader.executed)) for expect, actual in zip(expected_executions, reader.executed): expect_sql, expect_keys = expect actual_sql, actual_kwargs = actual self.assertEquals(expect_sql, actual_sql) self.assertEquals(set(expect_keys), set(actual_kwargs.keys()))
def test_coverage_empty(self): # an empty geometry should have no coverage from raw_tiles.tile import Tile, shape_tile_coverage from shapely.geometry.polygon import Polygon empty = Polygon() cov = shape_tile_coverage(empty, 16, Tile(0, 0, 0)) self.assertEquals(set([]), cov)
def test_coverage_trivial(self): # test that the trivial coverage - a tile's shape with itself as the # parent - returns that single tile. from raw_tiles.tile import Tile, shape_tile_coverage t = Tile(10, 255, 123) cov = shape_tile_coverage(t.as_shapely(), 10, t) self.assertEquals(1, len(cov)) self.assertEquals(set([t]), cov)
def raw_tiles_main(): import argparse parser = argparse.ArgumentParser(description='Generate RAWR tiles') parser.add_argument('zoom', metavar='Z', type=int, nargs=1, help='The zoom level.') parser.add_argument('x', metavar='X', nargs=1, help='The x coordinate, or coordinate range ' '(e.g: 0-8). Use * to indicate the whole range.') parser.add_argument('y', metavar='Y', nargs=1, help='The y coordinate, or coordinate range ' '(e.g: 0-8). Use * to indicate the whole range.') parser.add_argument('--dbparams', help='Database parameters') parser.add_argument('--sources', nargs='?', default=','.join(DEFAULT_SOURCES), help='The comma-separated list of sources to create ' 'RAWR tiles from.') # TODO: tests for the generic table source args = parser.parse_args() z = int(args.zoom[0]) x_range = parse_range(z, args.x) y_range = parse_range(z, args.y) conn_ctx = ConnectionContextManager(args.dbparams) src = parse_sources(args.sources.split(',')) fmt = Msgpack() sink = LocalSink('tiles', '.msgpack') rawr_gen = RawrGenerator(src, fmt, sink) # grab connection with conn_ctx() as conn: # commit transaction with conn as conn: # cleanup cursor resources with conn.cursor() as cur: table_reader = TableReader(cur) for x in x_range: for y in y_range: tile = Tile(z, x, y) rawr_gen(table_reader, tile)
def test_single_tile(self): from tilequeue.query.rawr import _tiles from raw_tiles.tile import Tile from raw_tiles.util import bbox_for_tile tile = Tile(15, 5241, 12665) zoom = tile.z unpadded_bounds = bbox_for_tile(tile.z, tile.x, tile.y) tiles = _tiles(zoom, unpadded_bounds) self.assertEquals([tile], list(tiles))
def test_multiple_tiles(self): from tilequeue.query.rawr import _tiles from raw_tiles.tile import Tile from raw_tiles.util import bbox_for_tile tile = Tile(15, 5241, 12665) # query at one zoom higher - should get 4 child tiles. zoom = tile.z + 1 unpadded_bounds = bbox_for_tile(tile.z, tile.x, tile.y) tiles = list(_tiles(zoom, unpadded_bounds)) self.assertEquals(4, len(tiles)) for child in tiles: self.assertEquals(tile, child.parent())
def test_round_trip(self): from raw_tiles.gen import RawrGenerator from raw_tiles.formatter.msgpack import Msgpack from raw_tiles.tile import Tile source_name = 'test' source_data = [(1, 'a', {'key': 'value'})] source = MockSource(source_name, source_data) formatter = Msgpack() sink = MockSink() table_reader = None gen = RawrGenerator(source, formatter, sink) tile = Tile(0, 0, 0) gen(table_reader, tile) # check the format (structures) of the returned data. should be using # the namedtuple types at the top level of the raw_tiles module from raw_tiles import RawrTile from raw_tiles import FormattedData self.assertIsInstance(sink.tile, RawrTile) self.assertEquals(tile, sink.tile.tile) self.assertEquals(1, len(sink.tile.all_formatted_data)) formatted_data = sink.tile.all_formatted_data[0] self.assertIsInstance(formatted_data, FormattedData) self.assertEquals(source_name, formatted_data.name) self.assertIsInstance(formatted_data.data, (str, bytes)) # check that the packed data contains the same thing as we put in! from msgpack import Unpacker from io import BytesIO unpacker = Unpacker(BytesIO(formatted_data.data)) unpacked_data = list(unpacker) self.assertEquals(1, len(unpacked_data)) source_datum = source_data[0] unpacked_datum = unpacked_data[0] # expect that the unpacked version has been turned into a list, but # is otherwise identical in contents. self.assertEquals(source_datum, tuple(unpacked_datum))
def test_multi_source(self): from raw_tiles.source.multi import MultiSource from raw_tiles.tile import Tile src1 = MockSource("src1", ["record1"], {"timing1": 123}) src2 = MockSource("src2", ["record2"], {"timing2": 321}) multi = MultiSource([src1, src2]) table_reader = None locs, times = multi(table_reader, Tile(0, 0, 0)) self.assertEquals(2, len(locs)) self.assertEquals("src1", locs[0].name) self.assertEquals(["record1"], locs[0].records) self.assertEquals("src2", locs[1].name) self.assertEquals(["record2"], locs[1].records) self.assertEquals(123, times.get("timing1")) self.assertEquals(321, times.get("timing2"))
import argparse parser = argparse.ArgumentParser(description='Generate RAWR tiles') parser.add_argument('zoom', metavar='Z', type=int, nargs=1, help='The zoom level.') parser.add_argument('x', metavar='X', nargs=1, help='The x coordinate, or coordinate range ' '(e.g: 0-8). Use * to indicate the whole range.') parser.add_argument('y', metavar='Y', nargs=1, help='The y coordinate, or coordinate range ' '(e.g: 0-8). Use * to indicate the whole range.') parser.add_argument('--dbparams', help='Database parameters') args = parser.parse_args() z = int(args.zoom[0]) x_range = parse_range(z, args.x) y_range = parse_range(z, args.y) conn_ctx = ConnectionContextManager(args.dbparams) src = OsmSource(conn_ctx) fmt = Gzip(Msgpack()) sink = LocalSink('tiles', '.msgpack.gz') rawr_gen = RawrGenerator(src, fmt, sink) for x in x_range: for y in y_range: tile = Tile(z, x, y) rawr_gen(tile)
def test_parent(self): from raw_tiles.tile import Tile self.assertEquals(Tile(0, 0, 0), Tile(1, 0, 0).parent()) self.assertEquals(Tile(1, 0, 0), Tile(2, 1, 1).parent())
def tile(self): from raw_tiles.tile import Tile return Tile(self.z, self.x, self.y)
def convert_coord_object(coord): """Convert ModestMaps.Core.Coordinate -> raw_tiles.tile.Tile""" assert isinstance(coord, Coordinate) coord = coord.container() return Tile(int(coord.zoom), int(coord.column), int(coord.row))
# for example, run as: # # $ python raw_tiles/command.py --dbparams dbname=california 10 163 395 # $ python raw_tiles/index/index.py 10/163/395 w225516713 w123741422 \ # n298078639 t10/163/395 t15/5241/12668 # # the first command generates a z10 tile over San Francisco. the second # indexes that tile and looks up a couple of ways which are part of route # relations, a node which is a gate and a couple of tiles containing # various bits of landuse. # if __name__ == '__main__': import sys z, x, y = map(int, sys.argv[1].split("/")) tile = Tile(z, x, y) extension = '.msgpack' def get_table(table): return tile_contents(tile, table, extension) rt_idx = RouteIndex() hw_idx = HighwayIndex() landuse_idx = FeatureTileIndex(tile, tile.z + 5, landuse_min_zoom) index( get_table, { 'planet_osm_rels': [rt_idx], 'planet_osm_ways': [hw_idx], 'planet_osm_polygon': [landuse_idx], })