为mapbox部署离线地图

看到一个博客 分析矢量地图切片技术,里面提到MBTiles文件。于是产生了想利用该文件格式部署离线地图想法,也是补充自己在使用mapbox地图数据来源这块短板。

使用mbtiles文件发布地图分为以下几步:

  1. 找到或制作合适的 mbtiles文件。osmlabopenmaptiles
    tippecanoe

  2. 将文件内的发布出去。mbview

以上的解决方案,都是网上搜集的方案。但是存在以下问题:

  • osm在国内数据质量不行,如缺少建筑数据。
  • 使用网上开源的发布程序,没找到自己称手的。

为了解决上面问题,打算自己写代码爬数据然后自己发布数据。

  1. 爬取四维图新的数据
import sqlite3
import requests
from  mbtiles.TileLnglatTransformGoogle import *
from mbtiles.TileLnglatTransformGaode import *
import time

#**创建表格接收数据**
def createDataTable(layerName):
   print(layerName)
   #链接sqlite数据库文件
   conn = sqlite3.connect('minedata.mbtiles')
   c = conn.cursor()
   print("Opened database successfully");
   table_name = layerName;
   sql = "SELECT count(*) FROM sqlite_master WHERE type='table' AND name='" + table_name + "';";
   cursor = c.execute(sql);
   dateArr = cursor.fetchall();
   tableCount = dateArr[0][0];
   if (tableCount > 0):
      print("已存在")
   else:
      print("不存在")
      createSql = "CREATE TABLE " + table_name + " (zoom_level integer, tile_column integer, tile_row integer, tile_data blob,primary key (zoom_level,tile_column,tile_row));"
      cursor.execute(createSql)
      conn.commit();
   print("Operation done successfully");
   cursor.close();
   conn.close()

#瓦片入库
def insert_image_db(z,x,y,image,layerName):
    sql_path = "minedata.mbtiles"
    conn = sqlite3.connect(sql_path, timeout=10)
    try:
        sql="INSERT INTO "+layerName+" (zoom_level, tile_column, tile_row, tile_data) VALUES (?,?,?,?);"
        conn.execute(sql,(z,x,y,image))
        conn.commit()
        conn.close()
    except IOError:
        print ("写入数据库失败")
        conn.close()

#请求瓦片
def downImg(z,x,y,url,layerName):
    url=url+str(z)+"/"+str(x)+"/"+str(y)+"?token=[your_key]&solu=2365";
    print(url)
    try:
        print("url")
        r = requests.get(url, timeout=30)
        r.raise_for_status()
        r.encoding = r.apparent_encoding
        print(len(r.content))
        if(len(r.content)>0):
            img_blob=sqlite3.Binary(r.content);
            insert_image_db(z,x,y,img_blob,layerName);
            time.sleep(2);
    except Exception as e:
        print(e);



def downOneLayer(layerName,lnglatRange,startZ,lastZ):
    url="http://datahive.minedata.cn/data/"+layerName+"/"
    for zlevel in range(startZ,lastZ):
        print(zlevel)
        tilesRange = getTilesRange(lnglatRange, zlevel);
        print(tilesRange)
        minX = tilesRange[0];
        minY = tilesRange[3];
        maxX = tilesRange[2];
        maxY = tilesRange[1];
        print(tilesRange);
        print(minX, maxX);
        print(minY, maxY)
        tiles = [];
        for i in range(minX - 1, maxX + 1):
            for j in range(minY - 1, maxY + 1):
                tile = [i, j, zlevel];
                tiles.append(tile);
        for tile in tiles:
            downImg(tile[2], tile[0], tile[1],url,layerName)



#根据经纬度、层级计算瓦片号
def lnglatToTilesRange(lnglat,z):
    return lnglatToTile_gaode(lnglat[0],lnglat[1],z);

#获取瓦片范围
def getTilesRange(lnglatRange,z):
    # [minX,minY,maxX,maxY]
    return [ lnglatToTilesRange(lnglatRange[0],z)[0],lnglatToTilesRange(lnglatRange[0],z)[1],lnglatToTilesRange(lnglatRange[1],z)[0],lnglatToTilesRange(lnglatRange[1],z)[1]];



#layerName需要爬取的图层名,范围,开始层级,结束层级
def downTileLayer(layerName,minX,minY,maxX,maxY,startZ,lastZ):
   createDataTable(layerName);
   lnglatRange = [
      [minX, minY],  # [minX,minY]
      [maxX, maxY],  # [maxX,maxY]
   ];
   downOneLayer(layerName,lnglatRange,startZ,lastZ);


downTileLayer("Waterface",119.9635, 30.0841,120.3971, 30.4146,12,18)
  1. 发布图层数据
import sqlite3
from django.http import HttpResponse
#发布图层数据
def getXYZ(request,x,y,z,layerName):
    conn = sqlite3.connect('/home/yushi/PycharmProjects/superpower/simulation/view/minedata.mbtiles')
    c = conn.cursor()
    # z = 12;
    # x = 2885;
    # y = 2534;
    sql="SELECT * from "+layerName+" m WHERE m.zoom_level = " + str(
            z) + " AND m.tile_column = " + str(x) + " AND m.tile_row = " + str(y) + ""

    cursor = c.execute(sql)
    dateArr = cursor.fetchall();
    print(len(dateArr))
    print(sql)
    if (len(dateArr) > 0):
        pbfFile=dateArr[0][3];
        FileName=dateArr[0][2];
        cursor.close();
        conn.close();
        response = HttpResponse(pbfFile, content_type='application/octet-stream')
        response['Content-Disposition'] = "filename="+str(FileName)
        return response;
  1. mapbox添加图层,测试结果
//mapbox添加图层
       map.on('load', function () {
            map.addSource('minedata_source', {
                type: 'vector',
                    tiles:['http://192.168.25.44:8000/simulation/getXYZ/{z}/{x}/{y}'],
                    maxzoom: 22
            })
            map.addLayer( {
                "id": "83798d37c86f475985aa16353d0e269f",
                "maxzoom": 17.5,
                "source": "minedata_source",
                "layout": {
                    "visibility": "visible"
                },
                "source-layer": "Waterface",
                "paint": {
                    "fill-outline-color": "#e6120e",
                    "fill-color": "#e6120e",
                    "fill-antialias": true,
                    "fill-translate-anchor": "viewport"
                },
                "minzoom": 5.0,
                "type": "fill",
            })
Waterface图层效果

结果验证,效果还是比较满意,自己爬数据自己发布数据,终于mapbox使用上补上了数据这块。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,482评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,377评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,762评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,273评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,289评论 5 373
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,046评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,351评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,988评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,476评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,948评论 2 324
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,064评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,712评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,261评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,264评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,486评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,511评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,802评论 2 345

推荐阅读更多精彩内容