金字塔結構的瓦片數量有多大
以目前互聯網常用的WebMecator為例
- 第一層:4幅256*256影像瓦片(JPG或PNG等)
- 第二層:42
- 第三層:43
- 依次類推
比如計算第1層至第18層的瓦片總數目(等比數列求和)91625968980個,大約916億,存盤空間估算在近百T,
瓦片直接存盤在檔案系統中的缺點
- 檔案系統對檔案數量、大小的限制
- 不易遷移、備份
- 等等
解決方案
這個問題本質上是對海量小資料的管理,很多互聯網大廠都有比較成熟的方案,只需要根據具體情況進行選擇調整即可,
單機存盤
采用sqlite
存盤在多個sqlite中,sqlite檔案名保證了唯一性,與(row,column, level)一一對應,
- (row,column, level)可以轉為唯一數字,比如QuadKey,或者其他編碼方式
- sqlite移動與管理就比較方便,
注意sqlite單檔案的大小不要太大,
集群存盤
使用HDFS等網路化存盤方案,
一個試驗
# -*- coding: utf-8 -*-"""下載區域影像從第一層到指定層 多執行緒版 存盤到sqlite中 """ import requests# python3的thread模塊import _threadimport randomimport timefrom random import randomimport os.pathimport QuadKey.quadkey as quadkeyimport shutilimport secrets as secrets import sqlite_util as dbutil # 下載的最細層tileZoom = 10rootTileDir = "tiles_db" # 分的db數量,采用質數 db_num = 1511lat_min = -90lat_max = 90lon_min = -180lon_max = 180# MS doesn't want you hardcoding the URLs to the tile server. This request asks for the Aerial# url template. Replace {quadkey}response = requests.get("https://dev.virtualearth.net/REST/V1/Imagery/Metadata/Aerial?key=%s" % (secrets.bingKey)) # 回傳結果data = https://www.cnblogs.com/giserhome/p/response.json()print(data) # grabs the data we need from the response.# 例如:http://ecn.{subdomain}.tiles.virtualearth.net/tiles/a{quadkey}.jpeg?g=7786tileUrlTemplate = data['resourceSets'][0]['resources'][0]['imageUrl']# 例如:['t0', 't1', 't2', 't3']imageDomains = data['resourceSets'][0]['resources'][0]['imageUrlSubdomains'] if (os.path.exists(rootTileDir) == False):os.mkdir(rootTileDir) bingTilesDir = os.path.join(rootTileDir, "bing") if (os.path.exists(bingTilesDir) == False):os.mkdir(bingTilesDir) def get_tiles_by_pixel(tilePixel):"""下載該點之上的瓦片 :param lat::param lon::return:""" """get pixel coordinates"""# tilePixel = quadkey.TileSystem.geo_to_pixel((lat, lon), tileZoom) # print(tilePixel) pixel = tilePixelgeo = quadkey.TileSystem.pixel_to_geo(pixel, tileZoom)# 計算四鍵qk = quadkey.from_geo(geo, tileZoom) # 四鍵qkStr = str(qk) #qkArray = []for index in range(tileZoom):qkArray.append(qkStr[0:index + 1]) print(qkArray)# 存放路徑for qk in qkArray:# db位置dbPath = "%s/%s.db" % (bingTilesDir, int(qk) % db_num )print(dbPath) if (os.path.exists(dbPath) == False):# os.mkdir(dbPath)dbutil.create_db(dbPath) # 下載影像 if (dbutil.is_exists(dbPath, qk)):# already downloadeddbutil.save_images(dbPath, qk)ok = 1else:print("下載中", end='') url = tileUrlTemplate.replace("{subdomain}", imageDomains[0])url = url.replace("{quadkey}", qk)url = "%s&key=%s" % (url, secrets.bingKey) response = requests.get(url, stream=True)print(response)dbutil.insert(dbPath, qk, response.content) del response# 強制睡一會,防止bing服務器限制sleepTime = random() * 3time.sleep(sleepTime) # 左上為原點tilePixelMax = quadkey.TileSystem.geo_to_pixel((lat_max, lon_max), tileZoom)tilePixelMin = quadkey.TileSystem.geo_to_pixel((lat_min, lon_min), tileZoom)print(tilePixelMax)print(tilePixelMin) tile_pixel_list = [] for x in range(tilePixelMin[0], tilePixelMax[0], 256):for y in range(tilePixelMax[1], tilePixelMin[1], 246):tile_pixel_list.append((x, y)) # 取決與服務器的硬體性能thread_pause = 30for i in range(len(tile_pixel_list)):print("處理"+str(i))_thread.start_new_thread(get_tiles_by_pixel,(tile_pixel_list[i],) ) if(i % thread_pause == (thread_pause-1)):print("讓正常運行的執行緒執行完,睡眠開始")time.sleep(5)print("睡眠結束") # _thread.start_new_thread( get_tiles_by_pixel, ( ) ) print('下載完畢')
可以優化的點很多
- 修改執行緒使用方式
- 提高查詢影像是否存在的效率
- 減少建立sqlite連接的次數
原始碼
更多的詳情見小專欄文章:GIS之家小專欄
文章尾部提供源代碼下載,對本專欄感興趣的話,可以關注一波
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/2301.html
標籤:GIS
