mapbox-vector-tile, 用于编码&解码Mapbox向量平铺的python 包

分享于 

13分钟阅读

GitHub

  繁體 雙語
Python package for encoding & decoding Mapbox Vector Tiles
  • 源代码名称:mapbox-vector-tile
  • 源代码网址:http://www.github.com/tilezen/mapbox-vector-tile
  • mapbox-vector-tile源代码文档
  • mapbox-vector-tile源代码下载
  • Git URL:
    git://www.github.com/tilezen/mapbox-vector-tile.git
    Git Clone代码到本地:
    git clone http://www.github.com/tilezen/mapbox-vector-tile
    Subversion代码到本地:
    $ svn co --depth empty http://www.github.com/tilezen/mapbox-vector-tile
    Checked out revision 1.
    $ cd repo
    $ svn up trunk
    
    Mapbox矢量平铺

    Build StatusCoverage Status

    安装

    mapbox-vector-tile与 python 2.6,2.7和 3.5兼容。 它在PyPi上列出为 mapbox-vector-tile。 推荐的安装方式是通过 pip:

    pip install mapbox-vector-tile

    注意,mapbox-vector-tile 依赖于 Shapely,它是计算几何的一个 python 库,需要一个库调用 GEOS。 有关如何安装它的必备组件的信息,请参见 shapely的说明。

    编码

    编码方法需要一个层的array 或者至少一个有效的层。 有效的图层是带有下列键的字典

    • name: 图层名称

    • features: 特性的array。 功能是带有以下键的字典:

      • geometry: 在 WKT,WKB或者shapely几何图元中表示特征几何图形。 坐标是相对于平铺的,在范围 [0, 4096) 中缩放。 请参见下面的代码,以执行必要的转换。 注意:不支持 GeometryCollection 类型,并且会触发 ValueError
      • properties: 带有几个键及其对应值的字典。
    >>>import mapbox_vector_tile
     # Using WKT>>> mapbox_vector_tile.encode([
     {
     "name": "water",
     "features": [
     {
     "geometry":"POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0))",
     "properties":{
     "uid":123,
     "foo":"bar",
     "cat":"flew" }
     }
     ]
     },
     {
     "name": "air",
     "features": [
     {
     "geometry":"LINESTRING(159 3877, -1570 3877)",
     "properties":{
     "uid":1234,
     "foo":"bar",
     "cat":"flew" }
     }
     ]
     }
     ])
     'x1aHnx05waterx12x18x12x06x00x00x01x01x02x02x18x03"x0ctx00x80@x1ax00x01x02x00x00x02x0fx1ax03foox1ax03uidx1ax03cat"x05nx03bar"x02 {"x06nx04flew(x80 xx02x1aDnx03airx12x15x12x06x00x00x01x01x02x02x18x02"ttxbex02xb6x03nx81x1bx00x1ax03foox1ax03uidx1ax03cat"x05nx03bar"x03xd2t"x06nx04flew(x80 xx02'# Using WKB>>> mapbox_vector_tile.encode([
     {
     "name": "water",
     "features": [
     {
     "geometry":"01030000000100000005000000000000000000000000000000000000000000000000000000000000000000360?000000000000360?000000000000360?000000000000360?000000000000000000000000000000000000000000000000",
     "properties":{
     "uid":123,
     "foo":"bar",
     "cat":"flew" }
     }
     ]
     },
     {
     "name": "air",
     "features": [
     {
     "geometry":"01030000000100000005000000000000000000000000000000000000000000000000000000000000000000360?000000000000360?000000000000360?000000000000360?000000000000000000000000000000000000000000000000",
     "properties":{
     "uid":1234,
     "foo":"bar",
     "cat":"flew" }
     }
     ]
     }
     ])
     'x1aJnx05waterx12x1ax08x01x12x06x00x00x01x01x02x02x18x03"x0ctx00x80@x1ax00x01x02x00x00x02x0fx1ax03foox1ax03uidx1ax03cat"x05nx03bar"x02 {"x06nx04flew(x80 xx02x1aYnx03airx12x1cx08x01x12x08x00x00x01x01x02x02x03x03x18x03"x0ctx00x80@x1ax00x01x02x00x00x02x0fx1ax03foox1ax03uidx1ax05ballsx1ax03cat"x05nx03bar"x03xd2t"x05nx03foo"x06nx04flew(x80 xx02'

    基于的编码坐标变换

    编码器需要几何体之一:

    • 在平铺相对坐标中,左下角的原点和值向右和向右增长,平铺为 4096像素方形。 例如,POINT(0 0) 是瓦的左下角,POINT(4096, 4096) 是砖块的右上角。 在这种情况下,库没有投影,坐标被编码为。
    • 在另一个坐标系中,使用 quantize_bounds 参数给出的平铺边界。 在这种情况下,库将缩放坐标,以便 quantize_bounds 适合 xy 方向的范围( 0,4096 )。 除了仿射变换之外,库没有其他投影。

    通过在调用 encode() 中设置参数 y_coord_down=True,可以控制是否在"向下"坐标系中进行控制。 默认值为"向上"。

    可以通过在调用 encode() 时设置 extents 参数来控制平铺范围( 默认情况下,上示例中使用的4096 )。 默认值为 4096.

    在经纬度( epsg: 4326 ) 中,只要先投影到 Spherical ( epsg: 3857 ),然后计算瓷砖内的Pixel 位置,就可以转换为基于平铺的坐标系。 这里示例代码使用 Django GEOS库的包含来对 LineString 对象进行转换:

    SRID_SPHERICAL_MERCATOR=3857deflinestring_in_tile(tile_bounds, line):
     # `mapbox-vector-tile` has a hardcoded tile extent of 4096 units.MVT_EXTENT=4096from django.contrib.gis.geos import LineString
     # We need tile bounds in spherical mercatorassert tile_bounds.srid ==SRID_SPHERICAL_MERCATOR# And we need the line to be in a known projection so we can re-projectassert line.srid isnotNone line.transform(SRID_SPHERICAL_MERCATOR)
     (x0, y0, x_max, y_max) = tile_bounds.extent
     x_span = x_max - x0
     y_span = y_max - y0
     tile_based_coords = []
     for x_merc, y_merc in line:
     tile_based_coord = (int((x_merc - x0) *MVT_EXTENT/ x_span),
     int((y_merc - y0) *MVT_EXTENT/ y_span))
     tile_based_coords.append(tile_based_coord)
     return LineString(*tile_based_coords)

    可以使用 mercantile 找到平铺边界,因此一个完整的用法示例可能如下所示:

    from django.contrib.gis.geos import LineString, Polygon
     import mercantile
     import mapbox_vector_tile
     SRID_LNGLAT=4326SRID_SPHERICAL_MERCATOR=3857 tile_xyz = (2452, 3422, 18)
     tile_bounds = Polygon.from_bbox(mercantile.bounds(*tile_xyz))
     tile_bounds.srid =SRID_LNGLAT tile_bounds.transform(SRID_SPHERICAL_MERCATOR)
     lnglat_line = LineString(((-122.1, 45.1), (-122.2, 45.2)), srid=SRID_LNGLAT)
     tile_line = linestring_in_tile(tile_bounds, lnglat_line)
     tile_pbf = mapbox_vector_tile.encode({
     "name": "my-layer",
     "features": [ {
     "geometry": tile_line.wkt,
     "properties": { "stuff": "things" },
     } ]
     })

    注意,这里示例在渲染时可能在平铺内没有任何可见的内容。 这取决于你是否把正确的数据放在瓷砖上。

    还要注意,规范允许修改范围,即使通常按约定设置为 4096. mapbox-vector-tile 假定范围为 4096.

    量化

    编码器还有选项可以通过 quantize_bounds 选项为你量化数据。 编码时,在表单(。minx,miny,maxx,maxy ) 中传递边界,并且在编码过程中适当地缩放坐标。

    mapbox_vector_tile.encode([
     {
     "name": "water",
     "features": [
     {
     "geometry":"POINT(15 15)",
     "properties":{
     "foo":"bar",
     }
     }
     ]
     }
     ], quantize_bounds=(10.0, 10.0, 20.0, 20.0))

    在本示例中,将得到编码的坐标为( 2048,2048 )

    这里外,如果数据已经在cooridnate系统中,则编码器支持一个选项 y_coord_down,它可以设置为 true。 这将禁止在编码期间翻转y 坐标值。

    自定义范围

    编码器还支持传入自定义范围。 这些将被传递到pbf中的层,并在任何量化或者y 坐标翻转过程中进行。

    mapbox_vector_tile.encode([
     {
     "name": "water",
     "features": [
     {
     "geometry":"POINT(15 15)",
     "properties":{
     "foo":"bar",
     }
     }
     ]
     }
     ], quantize_bounds=(0.0, 0.0, 10.0, 10.0), extents=50)

    自定义舍入函数

    为了保持 python 2和 3之间的一致性,使用 decimal MODULE 将 ROUND_HALF_EVEN 定义为round方法。 这可能比内置 round() 函数慢。 encoding采用可选的round_fn,你可以在其中指定要使用的round函数。

    mapbox_vector_tile.encode([
     {
     "name": "water",
     "features": [
     {
     "geometry":"POINT(15 15)",
     "properties":{
     "foo":"bar",
     }
     }
     ]
     }
     ], quantize_bounds=(0.0, 0.0, 10.0, 10.0), round_fn=round)

    解码

    解码方法采用有效的google.protobuf.message Tile,并以以下格式返回解码的字符串:

     {
     layername: {
     'extent': 'integer layer extent''version': 'integer''features': [{
     'geometry': 'list of points',
     'properties': 'dictionary of key/value pairs',
     'id': 'unique id for the given feature within the layer ' }, ... ]
     },
     layername2: {
     #.. . }
     }
    >>>import mapbox_vector_tile
     >>> mapbox_vector_tile.decode('x1aJnx05waterx12x1ax08x01x12x06x00x00x01x01x02x02x18x03"x0ctx00x80@x1ax00x01x02x00x00x02x0fx1ax03foox1ax03uidx1ax03cat"x05nx03bar"x02 {"x06nx04flew(x80 xx02x1aYnx03airx12x1cx08x01x12x08x00x00x01x01x02x02x03x03x18x03"x0ctx00x80@x1ax00x01x02x00x00x02x0fx1ax03foox1ax03uidx1ax05ballsx1ax03cat"x05nx03bar"x03xd2t"x05nx03foo"x06nx04flew(x80 xx02')
     {
     'water': {
     'extent': 4096,
     'version': 2,
     'features': [{
     'geometry': {'type': 'Polygon', 'coordinates': [[0, 0], [0, 1], [1, 1], [1, 0], [0, 0]]},
     'properties': {
     'foo': 'bar',
     'uid': 123,
     'cat': 'flew' },
     'type': 3,
     'id': 1 }
     ]
     },
     'air': {
     'extent': 4096,
     'version': 2,
     'features': [{
     'geometry': {'type': 'Polygon', 'coordinates': [[0, 0], [0, 1], [1, 1], [1, 0], [0, 0]]},
     'properties': {
     'foo': 'bar',
     'uid': 1234,
     'balls': 'foo',
     'cat': 'flew' },
     'type': 3,
     'id': 1 }
     ]
     }
     }

    下面是如何从文件中解码瓦片的方法。

    >>>import mapbox_vector_tile
     >>>withopen('tile.mvt', 'rb') as f:
     >>> data = f.read()
     >>> decoded_data = mapbox_vector_tile.decode(data)
     >>>withopen('out.txt', 'w') as f:
     >>> f.write(repr(decoded_data))

    使用本机protobuf库实现性能

    底层protobuf库的C++ 实现比纯 python 库具有更高的性能。 你可能需要编译 C++ 库插件或者安装它,具体取决于操作系统。

    debian Jessie

    protobuf ( libprotobuf9 ) 可用的版本在 debian Jessie的 2.6.1. 你可以从软件包管理器中使用适当的python 绑定安装它:

    
    $ sudo apt-get install libprotoc9 libprotobuf9 protobuf-compiler python-protobuf
    
    
    
    

    然后,在运行 python 程序之前,你必须启用两个environnement变量:

    
    $ export PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=cpp
    
    
    $ export PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION=2
    
    
    
    

    变更日志

    在这里点击查看不同版本的时间变化。


    PAC  PACK  dec  TILE  Vector  Tiles  
    相关文章