?本文示例代碼已上傳至我的Github倉庫https://github.com/CNFeffery/DataScienceStudyNotes
?
大家好我是費(fèi)老師,在日常研發(fā)地圖類應(yīng)用的場景中,為了在地圖上快速加載大量的矢量要素,且方便快捷的在前端處理矢量的樣式,且矢量數(shù)據(jù)可以攜帶對應(yīng)的若干屬性字段,目前主流的做法是使用矢量切片(vector tiles)的方式將矢量數(shù)據(jù)發(fā)布為服務(wù)進(jìn)行調(diào)用:
而可用于發(fā)布矢量切片服務(wù)的工具,主流的有g(shù)eoserver、tippecanoe等,但是使用起來方式比較繁瑣,且很容易遇到性能瓶頸。
除此之外,PostGIS中也提供了ST_AsMVT等函數(shù)可以直接通過書寫SQL來生成矢量切片數(shù)據(jù),但是需要額外進(jìn)行服務(wù)化的開發(fā)封裝,較為繁瑣。
而我在最近的工作中,接觸到由maplibre開源的高性能矢量切片服務(wù)器martin
( https://github.com/maplibre/martin ),它基于Rust進(jìn)行開發(fā),官方宣傳其性能快到瘋狂(Blazing fast),而在我實(shí)際的使用體驗中也確實(shí)如此,在今天的文章中我就將為大家分享有關(guān)martin發(fā)布矢量切片地圖服務(wù)的常用知識??。
martin可在windows、linux、mac等主流系統(tǒng)上運(yùn)行,其最經(jīng)典的用法是配合PostGIS,下面我們以linux系統(tǒng)為例,介紹martin的部署使用方法:
martin提供了多種多樣的安裝方式,其中我體驗下來比較簡單穩(wěn)定的安裝方式是基于cargo
,這是Rust的包管理器(因為martin基于Rust開發(fā),這也是其超高性能的原因之一),martin可以直接當(dāng)作Rust包進(jìn)行安裝。因此我們首先需要安裝cargo:
apt-get update
apt-get install cargo
cargo
完成安裝后,為了加速其國內(nèi)下載速度,我們可以使用由字節(jié)跳動維護(hù)的鏡像源( https://rsproxy.cn/ ):
mkdir ~/.cargo
vim ~/.cargo/config
# 在vim中粘貼下列內(nèi)容后保存退出
[source.crates-io]
replace-with = 'rsproxy'
[source.rsproxy]
registry = 'https://rsproxy.cn/crates.io-index'
[source.rsproxy-sparse]
registry = 'sparse+https://rsproxy.cn/index/'
[registries.rsproxy]
index = 'https://rsproxy.cn/crates.io-index'
[net]
git-fetch-with-cli = true
接著逐一執(zhí)行下列命令即可完成martin
及其必要依賴的安裝:
# 安裝必要依賴以防m(xù)artin安裝失敗
apt-get install pkg-config
apt-get install libssl-dev
cargo install martin
接下來我們利用geopandas來讀入及生成一些示例用ostGIS數(shù)據(jù)庫表,完整的代碼及示例數(shù)據(jù)可以在文章開頭的倉庫中找到:
import random
import geopandas as gpd
from shapely import Point
from sqlalchemy import create_engine
engine = create_engine('postgresql://postgres:mypassword@127.0.0.1:5432/gis_demo')
# 讀取測試矢量數(shù)據(jù)1(數(shù)據(jù)來自阿里DataV地圖選擇器)
demo_gdf1 = gpd.read_file('中華人民共和國.json')[['adcode', 'name', 'geometry']]
# 生成示例矢量數(shù)據(jù)2
demo_gdf2 = gpd.GeoDataFrame(
{
'id': range(100000),
'geometry': [Point(random.normalvariate(0, 20),
random.normalvariate(0, 20))
for i in range(100000)]
},
crs='EPSG:4326'
)
# 推送至數(shù)據(jù)庫
demo_gdf1.to_postgis(name='demo_gdf1', con=engine, if_exists='replace')
demo_gdf2.to_postgis(name='demo_gdf2', con=engine, if_exists='replace')
通過上面的Python代碼,我們將兩張帶有矢量數(shù)據(jù)且坐標(biāo)參考系為WGS84的數(shù)據(jù)表demo_gdf1、demo_gdf2分別推送至演示用PostGIS數(shù)據(jù)庫中:
接下來我們就可以愉快的使用martin來發(fā)布矢量切片服務(wù)了~
martin的基礎(chǔ)使用超級簡單,只需要在啟動martin服務(wù)時設(shè)置好目標(biāo)PostGIS數(shù)據(jù)庫的連接參數(shù)字符串,它就可以自動發(fā)現(xiàn)數(shù)據(jù)庫中具有合法坐標(biāo)系(默認(rèn)為EPSG:4326)的所有矢量表,并自動發(fā)布為相應(yīng)的地圖服務(wù),以我們的示例數(shù)據(jù)庫為例,參考下列命令:
/root/.cargo/bin/martin postgresql://postgres:mypassword@127.0.0.1:5432/gis_demo
從輸出結(jié)果中可以看到示例數(shù)據(jù)庫中的demo_gdf1、emo_gdf2表均被martin自動發(fā)現(xiàn),我們的martin服務(wù)被正常啟動:
這時直接訪問本機(jī)IP地址對應(yīng)的3000端口,即可看到相應(yīng)的提示信息:
訪問上面對應(yīng)地址下的/catalog頁面,可以看到被當(dāng)前martin務(wù)所架起的圖層信息:
當(dāng)以各個圖層id作為路徑進(jìn)行訪問時,就可以看到其對應(yīng)地圖服務(wù)的完整參數(shù)信息了,以demo_gdf1為例:
對mapbox、maplibre等地圖框架了解的朋友,就知道上述信息可以直接用于向地圖實(shí)例中添加相應(yīng)的source和layer,下面是一個簡單的基于maplibre的地圖示例,要素加載速度非常之快,可以說唯一限制要素加載速度上限的瓶頸是帶寬??:
除此之外,martin還有相當(dāng)多的額外功能,譬如基于PostGIS自定義運(yùn)算函數(shù)、基于nginx實(shí)現(xiàn)切片緩存等,更多martin使用相關(guān)內(nèi)容請移步官網(wǎng)
https://maplibre.org/martin/。