Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Mapquadlib

 Mapquadlib

Mapquadlib - A Python library that supports multi-level tiled representations of the map of the earth.

Avatar for Christian Stade-Schuldt

Christian Stade-Schuldt

April 22, 2021

Other Decks in Programming

Transcript

  1. Introduction • Lead So tware Engineer @ HERE Get in

    contact • Twitter @ta kas • GitHub Ta kas • Blog blog.ta kas.net GeoPython 2021 - Mapquadlib
  2. What are MapQuads? • Quadtree data structure in which each

    internal node has exactly four children. • Partitions a two-dimensional space by recursively subdividing it into four quadrants. GeoPython 2021 - Mapquadlib
  3. Why using MapQuads? • Very convenient way to represent some

    area on the map • load tiles individually • Binning spatial data • Pre-compute tiles GeoPython 2021 - Mapquadlib
  4. Constructing MapQuads • Depth-first traversal of a quadtree • Z-order

    curve • Morton Codes GeoPython 2021 - Mapquadlib
  5. Morton Codes • Interleaving the binary coordinate values yields binary

    z-values • Connecting the z-values in their numerical order produces the recursively Z-shaped curve • Two-dimensional z-values are also called quadkey GeoPython 2021 - Mapquadlib
  6. Morton Codes - Example Example: A Mapquad of zoom level

    10 with column x=754 and row y=531 1. Convert X and Y to binary values x = 1011110010 y = 1000010011 2. Interleave x and y, with • x on even and • y on odd positions morton_key = 1100 0101 0111 0000 1110 = 11 00 01 01 01 11 10 00 00 11 10 => 3 0 1 1 1 3 2 0 0 3 2 = 30111320032 = quad_key GeoPython 2021 - Mapquadlib
  7. Mapquadlib A Python library for working with MapQuads • Uses

    only Python Standard Library => zero dependencies • Well tested: over 500 tests, 92% test coverage • Currently, supports MercatorQuads and HereQuads • To be open-sourced soon GeoPython 2021 - Mapquadlib
  8. MercatorQuads • Used at Bing Maps, Mapbox • Tiling schema

    with baked in Mercator projection • ! Tile is always a square on the map surface • " Distortion • " Latitude is limited up to ~85.05 degrees north and ~-85.05 south GeoPython 2021 - Mapquadlib
  9. HereQuads • Based on raw, non-projected WGS84 lat/lng coordinate values

    • non-square tiles when viewed on Mercator projected 2D map • ! Tile size in degrees does not change when close to the poles GeoPython 2021 - Mapquadlib
  10. Mapquadlib - GeoCoordinate GeoCoordinate here_office_location = GeoCoordinate(lng=13.3850739, lat=52.5309163) print(f"GeoJSON: {here_office_location.geojson}")

    GeoJSON: {"type": "Point", "coordinates": [13.3850739, 52.5309163]} print(f"WKT: {here_office_location.wkt}") WKT: POINT (13.3850739 52.5309163) GeoPython 2021 - Mapquadlib
  11. Mapquadlib - BoundingBox BoundingBox here_office = BoundingBox(west=13.3839069538, south=52.5302044945, east=13.385562377, north=52.5309703632)

    print(f"GeoJSON: {here_office.geojson}") GeoJSON: {"type": "Polygon", "coordinates": [ [ [13.3839069538, 52.5302044945], [13.385562377, 52.5302044945], [13.385562377, 52.5309703632], [13.3839069538, 52.5309703632], [13.3839069538, 52.5302044945] ] ] } print(f"WKT: {here_office.wkt}") WKT: POLYGON (52.5302044945 13.3839069538, 52.5309703632 13.3839069538, 52.5309703632 13.385562377, 52.5302044945 13.385562377, 52.5302044945 13.3839069538) GeoPython 2021 - Mapquadlib
  12. Mapquadlib - Creating MapQuads • Generate a MapQuad by •

    long key • quad key • latitude, longitude and zoom level • x, y index and zoom level my_quad_1 = HereQuad.from_lat_lng_level(lat=52.5309163, lng=13.3850739, level=10) str(my_quad) str(my_quad_1) HereQuad [quadKey=1220120312, longKey=1476150, x=550, y=405, level=10] my_quad_2 = HereQuad(1476150) my_quad_3 = HereQuad.from_quad_key("1220120312") my_quad_1 == my_quad_2 == my_quad_3 True GeoPython 2021 - Mapquadlib
  13. Mapquadlib - Plotting Draw its bounding box on a map

    bbox = my_quad_1.bounding_box bbox.geojson {"type": "Polygon", "coordinates": [ [ [13.359375, 52.3828125], [13.7109375, 52.3828125], [13.7109375, 52.734375], [13.359375, 52.734375], [13.359375, 52.3828125] ] ] } GeoPython 2021 - Mapquadlib
  14. Mapquadlib - Ancestors Get a MapQuad's ancestor: ancestor = my_quad.ancestor(7)

    ancestor.bounding_box.geojson {"type": "Polygon", "coordinates": [ [ [11.25, 50.625], [14.0625, 50.625], [14.0625, 53.4375], [11.25, 53.4375], [11.25, 50.625] ] ] } GeoPython 2021 - Mapquadlib
  15. Mapquadlib - Descendants Get a MapQuad's descendants: descendants = my_quad.descendants(14)

    geo_collection = { "type": "GeometryCollection", "geometries": [d.bounding_box._geojson() for d in descendants] } GeoPython 2021 - Mapquadlib
  16. Mapquadlib - Neighbors Get a MapQuad's neighbors: neighbors = my_quad.neighbors()

    geo_collection = { "type": "GeometryCollection", "geometries": [d.bounding_box._geojson() for d in neighbors] } GeoPython 2021 - Mapquadlib
  17. Mapquadlib - Neighbors Get a MapQuad's neighbors at a di

    erent level: neighbors = my_quad.neighbors(14) geo_collection = { "type": "GeometryCollection", "geometries": [d.bounding_box._geojson() for d in neighbors] } GeoPython 2021 - Mapquadlib
  18. Mapquadlib - Iterators Get all MapQuads for a given bounding

    box berlin = BoundingBox(west=13.08835, south=52.33826, east=13.76116, north=52.67551) quads = MapQuadIterator(HereQuad,level=14, bounding_box=berlin) geo_collection = { "type": "GeometryCollection", "geometries": [q.bounding_box._geojson() for q in quads] } GeoPython 2021 - Mapquadlib
  19. Mapquadlib - Conversion Convert from one MapQuad type to another

    iterator = MapQuadIterator(MercatorQuad, level=14, bounding_box=berlin) geojson = { "type": "GeometryCollection", "geometries": [q.bounding_box._geojson() for q in iterator] } here_quads = set([HereQuad.from_geocoordinate_level(q.bounding_box.center, level=14) for q in iterator]) geojson = { "type": "GeometryCollection", "geometries": [q.bounding_box._geojson() for q in here_quads] } GeoPython 2021 - Mapquadlib
  20. Mapquadlib - Conversion Convert from one MapQuad type to another

    iterator = MapQuadIterator(MercatorQuad, level=14, bounding_box=berlin) geojson = { "type": "GeometryCollection", "geometries": [q.bounding_box._geojson() for q in iterator] } here_quads = set([HereQuad.from_geocoordinate_level(q.bounding_box.center, level=14) for q in iterator]) geojson = { "type": "GeometryCollection", "geometries": [q.bounding_box._geojson() for q in here_quads] } GeoPython 2021 - Mapquadlib
  21. References 1. Tiled web map 2. Z-order curve 3. Bing

    Maps Tile System 4. Here Developer Portal GeoPython 2021 - Mapquadlib