本文隻介紹實際工作中常用的 WMS、WMTS、WFS、TMS 四種,WCS、WPS 等其它 OGC WebService 類型請自行查閱官方資料。
目錄
- 0. 參數傳遞方式
- 1. WMS 速查
- 1.1. 能力
- 1.2. 擷取地圖圖檔舉例(GetMap)
- 1.3. 在 CesiumJS 和 OpenLayers6 中使用 GeoServer WMS
- 1.4. 擷取要素資訊
- 2. WMTS 速查
- 2.1. 軸向
- 2.2. 能力
- 2.3. 示意圖
- 2.4. 請求瓦片舉例(GetTile)
- 2.5. 請求瓦片舉例(GetTile)使用 RESTful
- 2.6. 關于 GeoServer 兩種擷取瓦片的接口風格
- 2.7. 在 CesiumJS 和 OpenLayers6 中使用 GeoServer WMTS
- 3. TMS 速查
- 3.1. 軸向
- 3.2. 中繼資料 XML 文檔
- 3.3. 請求瓦片舉例
- 3.3. 在 QGIS 中加載 GeoServer 的 TMS
- 3.4. 在 CesiumJS 和 OpenLayers6 中使用 GeoServer 的 TMS
- 3.5. GeoServer 是否可以挂接已有的 TMS
- 4. WFS 速查
- 4.1. 能力
- 4.2. 擷取要素(GetFeature)及常用參數
- 4.3. 擷取要素時使用過濾(Filtering)
- 4.4. 簡述事務(Transaction)
- 4.5. 推薦與不推薦
- 5. 什麼是 TileMatrixSet / TileMatrix
- 6. 常見地圖服務接口的軸朝向
- ① 使用 Z-order 降維編碼的微軟必應地圖
- ② 類似 WMTS 的谷歌和 OSM
- ③ 百度地圖
- 參考資料
0. 參數傳遞方式
- 鍵值對
- RESTful API
- SOAP
三種方式對于下文列舉的服務并不是全都存在的,例如 WMS 就隻有第一種。
本文不介紹 SOAP 方式(因為太複雜了)。
1. WMS 速查
以
1.1.0
版本為參考。
1.1. 能力
-
GetCapabilities
-
GetMap
-
GetFeatureInfo
1.2. 擷取地圖圖檔舉例(GetMap)
以這樣一個請求位址為例:
http://localhost:4800/geoserver/spatial_base/wms?<queryString>
queryString
即查詢字元串,我把它列成表格:
param | value | desc |
---|---|---|
service | WMS | 服務類型 |
version | 1.1.0 | 服務版本 |
request | GetMap | 方法 |
layers | spatial_base:guangxi_cities | 哪個圖層 |
bbox | 104.450889587402,20.8992862701416,112.061851501465,26.3855667114258 | 要多大範圍 |
width | 768 | 要傳回的圖像像素寬 |
height | 553 | 要傳回的圖像像素高 |
srs | EPSG:4326 | 用哪個坐标系 |
styles | "" | 用什麼樣式,預設要給空字元串 |
format | image/png | 格式 |
GeoServer 的 layers 參數,是“工作空間名:圖層名”這樣的組合。
那麼,它傳回的就是一張圖:
這是最正常的使用“鍵值對”,也就是 queryString 來請求地圖的 WMS 用法。
1.3. 在 CesiumJS 和 OpenLayers6 中使用 GeoServer WMS
在 CesiumJS 中:
new Cesium.WebMapServiceImageryProvider({
url: 'http://localhost:4800/geoserver/spatial_base/ows',
layers: 'spatial_base:guangxi_cities',
parameters: {
transparent: true,
format: 'image/png',
},
})
隻需要保證坐标系合适即可,當然,url 的
ows
也可以改為
wms
。
OWS 隻是 GeoServer 上的一個通配符,如果你知道你想用的是什麼服務,可以不寫 ows,例如本例,可以直接寫 'http://localhost:4800/geoserver/spatial_base/wms'
在 OpenLayers6 中:
import TileLayer from 'ol/layer/Tile'
import TileWMS from 'ol/source/TileWMS'
new TileLayer({
extent: [104.4509, 20.8993, 112.0619, 26.3856], // 坐标系保持與 View 一緻
source: new TileWMS({
url: 'http://localhost:4800/geoserver/spatial_base/wms',
params: {
'LAYERS': 'spatial_base:guangxi_cities',
},
serverType: 'geoserver', // 有好幾種地理伺服器,要明确指定
}),
})
// View 坐标系的設定
import { View } from 'ol'
new View({
// ...
projection: get('EPSG:4326') // 傳回一個 Projection 執行個體即可
})
根據 OpenLayers 的文檔:
At least aparam is required.
LAYERS
is
STYLES
by default.
''
is
VERSION
by default.
1.3.0
,
WIDTH
,
HEIGHT
and
BBOX
(
CRS
for WMS version < 1.3.0) will be set dynamically.
SRS
也就是至少要設定
LAYERS
參數。如果請求的圖層的坐标系與 View 的一緻,則不需要設定
SRS
。
1.4. 擷取要素資訊
WMS 雖然主要的用途是請求地圖圖檔,是一種經典的伺服器渲染服務,但是也保留了基本的要素查詢功能,也就是
GetFeatureInfo
,舉例:
http://localhost:4800/geoserver/spatial_base/ows
?service=WMS
&version=1.1.1
&request=GetFeatureInfo
&layers=spatial_base:guangxi_cities
&bbox=101.25,22.5,112.50,33.75
&width=256
&height=256
&srs=EPSG:4326
&query_layers=spatial_base:guangxi_cities
&info_format=application/json
&x=181
&y=199
GetFeatureInfo
是一個可選的功能,GeoServer 有這個功能。簡單解釋一下,參數
width
和
height
是參數
bbox
範圍生成的一小塊圖檔,然後去查詢這塊圖檔中像素位置是
x
、
y
的要素資訊,其它參數不難了解。
2. WMTS 速查
2.1. 軸向
WMTS 的軸朝向如下圖所示。
2.2. 能力
-
(擷取WMTS中繼資料文檔,也叫擷取能力文檔)GetCapabilities
-
(擷取一張瓦片)GetTile
-
(可選能力)GetFeatureInfo
2.3. 示意圖
WMTS 的行列号、瓦片陣(TileMatrix,類似層級的概念,參考第 5 節)是從 0 開始算的,例如
TileMatrix=EPSG:4326:0&TileCol=0&TileRow=0
。
2.4. 請求瓦片舉例(GetTile)
以 2.3 小節中的“TileRow=55 & TileCol=103”這張瓦片為例:
它的請求位址是:
http://localhost:4800/geoserver/gwc/service/wmts?layer=spatial_base%3Aguangxi_cities&style=&tilematrixset=EPSG%3A900913&Service=WMTS&Request=GetTile&Version=1.0.0&Format=image%2Fpng&TileMatrix=EPSG%3A900913%3A7&TileCol=103&TileRow=55
把 queryString 列成表格即:
param | value | desc |
---|---|---|
layer | spatial_base:guangxi_cities | 與 WMS 的 layers 意義一緻 |
style | "" | 與 WMS 的 style 意義一緻 |
tilematrixset | EPSG:900913 | 瓦片陣集,見本文第5節 |
TileMatrix | EPSG:900913:7 | 目前級别的瓦片陣,見本文第5節 |
TileCol | 103 | 瓦片列号 |
TileRow | 55 | 瓦片行号 |
Service | WMTS | 與 WMS 的 service 意義一緻 |
Request | GetTile | 與 WMS 的 request 意義一緻 |
Version | 1.0.0 | 與 WMS 的 version 意義一緻 |
Format | image/png | 與 WMS 的 format 意義一緻 |
聰明的你應該注意到了,參數的名稱是大小寫任意的,但是參數值部分大小寫敏感,例如 “EPSG:900913”寫成“epsg:900913”是請求不到的(至少 GeoServer 是這樣);但是“GetTile”寫成“gettile”又是可以的。
2.5. 請求瓦片舉例(GetTile)使用 RESTful
圖與上一小節傳回的是一樣的,使用 RESTful 風格的請求是這樣的:
http://localhost:4800/geoserver/gwc/service/wmts/rest/spatial_base:guangxi_cities/polygon/EPSG:900913/EPSG:900913:7/55/103?format=image/png
2.6. 關于 GeoServer 兩種擷取瓦片的接口風格
- 鍵值對:在 GeoServer 中使用 OpenLayers 預覽,使用浏覽器開發者工具檢視網絡請求,此處的接口風格即鍵值對形式,使用 queryString;
- RESTful:請求 WMTS 的能力文檔,搜尋
标簽,此處的位址是 REST 風格的。ResourceURL
2.7. 在 CesiumJS 和 OpenLayers6 中使用 GeoServer WMTS
在 CesiumJS 中,你要十分小心每一級“TileMatrix”的名稱,因為 CesiumJS 使用的是 REST 風格的請求位址,這就意味着,TileMatrix 必須與能力文檔中對應圖層的 TileMatrix 名稱一緻,才能拼湊出正确的 URL。
CesiumJS 預設 WMTS 每一級的 TileMatrix 名稱就是簡單的“0、1、2、3、4...”,但是 GeoServer 預設的 900913 和 4326 這兩個
TileMatrixSet
的名稱卻是 “EPSG:4326:0、EPSG:4326:1、EPSG:4326:2...”和“EPSG:900913:0、EPSG:900913:1、EPSG:900913:2...”,面對這種情況也好辦,我們可以用 JavaScript 快速生成這樣一個有規律的
TileMatrixLabels
數組:
const maxLevel = 3 // 别忘了改成你的 WMTS 支援的最大等級,此處示範寫個 3
const tileMatrixID = 'EPSG:900913'
const tileMatrixLabels = Object.keys(new Array(maxLevel).fill(0)).map(v => `${tileMatrixID}:${v}`)
// tileMatrixLabels 即 ['EPSG:900913:0', 'EPSG:900913:1', 'EPSG:900913:2']
現在,你可以用這個
tileMatrixLabels
數組建立
WebMapTileServiceImageryProvider
:
new Cesium.WebMapTileServiceImageryProvider({
url: 'http://localhost:4800/geoserver/gwc/service/wmts/rest/spatial_base:guangxi_cities/{style}/{TileMatrixSet}/{TileMatrix}/{TileRow}/{TileCol}?format=image/png',
style: 'polygon', // 改 'default' 就是預設的樣式
layer: 'spatial_base:guangxi_cities',
tileMatrixLabels: tileMatrixLabels,
tileMatrixSetID: 'EPSG:900913',
rectangle: Cesium.Rectangle.fromDegrees(104.450889587402,20.8992862701416,112.061851501465,26.3855667114258),
})
你甚至可以封裝一個函數擷取這些 TileMatrix 的名稱:
/**
* 建立 TileMatrix 的名稱
* @param {string} tileMatrixID 即 `TileMatrixSet` 的名稱
* @param {number} maxLevel 即 WMTS 的最大等級
* @returns {string[]}
*/
const createTileMatrixLabels = (tileMatrixID, maxLevel) =>
Object.keys(new Array(maxLevel).fill(0)).map(v => `${tileMatrixID}:${v}`)
至于 OpenLayers6 加載 WMTS,也是需要計算分辨率、TileMatrixIDs 的,略嫌麻煩,以
EPSG:4326
為例,你需要計算圖層的分辨率清單、TileMatrix 名稱清單:
// 計算 22 級别,夠用就行
const resolutions = new Array(22)
// EPSG:4326 一級寬度跨 2 個 256 像素的瓦片
const firstLevelPixelWidth = 360 / (256 * 2)
for (let z = 0; z < 22; ++z) {
// 逐級除以 2
resolutions[z] = firstLevelPixelWidth / Math.pow(2, z)
}
const tileMatrixLabels = createTileMatrixLabels('EPSG:4326', 22)
随後,你就可以用
resolutions
和
tileMatrixLabels
建立一個
WMTSTileGrid
,進而建立 WMTS 圖層了:
const wmtsTileGrid = new WMTSTileGrid({
origin: [-180, 90], // origin 即目前坐标系的的左上角
resolutions: resolutions,
matrixIds: tileMatrixLabels,
})
new TileLayer({
extent: [104.4509, 20.8993, 112.0619, 26.3856],
source: new WMTS({
// 和 CesiumJS 不太一樣,這裡不用到模闆那麼細
url: 'http://localhost:4800/geoserver/gwc/service/wmts',
layer: 'spatial_base:guangxi_cities',
matrixSet: 'EPSG:4326', // 與能力文檔中此圖層的 TileMatrixSet 一緻
format: 'image/png',
// 也可以用 `ol/proj` 包導出的 get('EPSG:4326'),傳回 Projection 執行個體即可
projection: 'EPSG:4326',
tileGrid: wmtsTileGrid,
style: 'polygon',
wrapX: true,
}),
})
而如果是
EPSG:3857
,也即
EPSG:900913
,那麼你的
origin
、
extent
、
firstLevelPixelWidth
就要随之改變了:
const origin = [-20037508.34, 2003708.34]
const extent = [11627419.84177403,2379873.5953122815,12474668.246494522,3046913.9333698303]
const firstLevelPixelWidth = 40075016.68557849 / 256
至于為什麼是這幾個數字,請檢視 GeoServer 中相關 Gridset 的數值吧,需要有 Web 墨卡托坐标系相關的基礎。
3. TMS 速查
TMS 是一種非常接近靜态資源的地圖瓦片資料集,常見的瓦片格式有
jpeg
、
png
、
pbf
等。這個标準比較舊了,但是勝在簡單。
3.1. 軸向
TMS 軸朝向如下圖所示。
3.2. 中繼資料 XML 文檔
一般來說,TMS 的位址會指向一個名稱是
tilemapresource.xml
的文檔。當然,GeoServer 就比較例外,僅僅是傳回 XML 文檔而位址并不指向 XML 文檔。
這個 XML 文檔是 TMS 最顯著的特征,記錄了這個瓦片地圖集的中繼資料:
<TileMap version="1.0.0" tilemapservice="...">
<!-->...<-->
</TileMap>
3.3. 請求瓦片舉例
請求位址:
http://localhost:4800/geoserver/gwc/service/tms/1.0.0
/spatial_base:guangxi_cities@EPSG:900913@png
/7/103/72.png
如下圖所示:
3.3. 在 QGIS 中加載 GeoServer 的 TMS
添加一個 XYZ 圖層即可,但是在模闆連結中要填寫的是
{z}/{x}/{-y}.imageExt
,而不是
{z}/{x}/{y}.imageExt
。
3.4. 在 CesiumJS 和 OpenLayers6 中使用 GeoServer 的 TMS
CesiumJS 在測試中發現對非全範圍的 EPSG4326 或 3857 坐标系的 TMS 加載是存在問題的。GeoServer 釋出的圖層一般沒有這個問題。
舉例:
new Cesium.TileMapServiceImageryProvider({
url: "http://localhost:4800/geoserver/gwc/service/tms/1.0.0/spatial_base%3Aguangxi_cities@EPSG%3A900913@png",
minimumLevel: 0,
maximumLevel: 15,
rectangle: Cesium.Rectangle.fromDegrees(104.450889587402,20.8992862701416,112.061851501465,26.3855667114258)
})
如果使用的是
TileMapServiceImageryProvider
這個類,那麼它是遵循正确的 z、x、y 順序的。如果使用的是
UrlTemplateImageryProvider
,那麼你需要把模闆中的
{y}
改成
{reverseY}
:
new Cesium.UrlTemplateImageryProvider({
url: "http://localhost:4800/geoserver/gwc/service/tms/1.0.0/spatial_base%3Aguangxi_cities@EPSG%3A900913@png/{z}/{x}/{reverseY}.png",
minimumLevel: 0,
maximumLevel: 15,
rectangle: Cesium.Rectangle.fromDegrees(104.450889587402,20.8992862701416,112.061851501465,26.3855667114258)
})
CesiumJS 會判斷預設的 TMS 描述檔案“tilemapresource.xml”,請求失敗則降級成
{z}/{x}/{reverseY}.imageExt
而在 OpenLayers6 中,使用 TMS 則是通過
XYZ
實作的:
new TileLayer({
source: new XYZ({
url: 'http://localhost:4800/geoserver/gwc/service/tms/1.0.0/spatial_base%3Aguangxi_cities@EPSG%3A900913@png/{z}/{x}/{y}.png'
}),
})
這隻是最簡單的用法,即預設是
EPSG:3857
或
EPSG:900913
切片方案的 TMS,否則要指定其它的參數,例如
projection
、
tileGrid
、
tileSize
等,具體參考官方文檔。如果不想控制台報沒瓦片的地方找不到瓦片的錯誤,則還要加上
extent
參數給
ol/layer/Tile
類:
import TileLayer from 'ol/layer/Tile'
const tmslayer = new TileLayer({
extent: [11627419.84177403,2379873.5953122815,12474668.246494522,3046913.9333698303],
// ...
})
3.5. GeoServer 是否可以挂接已有的 TMS
暫時不可以。
參考:Can I use external TMS service as a store in Geoserver?
GeoServer 目前隻能挂接其它伺服器的 WMS 和 WMTS,TMS 作為一種比較靜态的瓦片資料服務,建議直接使用 Web 伺服器釋出即可,不需要再經過 GeoServer。
4. WFS 速查
WFS 即使到了 2.0.0 版本,仍然隻能用這兩種方式發起請求:
- 使用鍵值對的簡單類型請求,通常用 Get 請求,也能用 Post 請求
- 使用 XML 體的複雜資料請求,隻能用 Post 請求
這是有問題的,前端的朋友們熟悉什麼?他們要什麼?JSON 啊!
若不加以限制,WFS 傳回的是基于 XML 的 GML 格式。總之,
4.1. 能力
-
:擷取矢量要素資料GetFeature
-
:查詢矢量圖層的中繼資料DescribeFeatureType
-
:擷取能力文檔GetCapabilities
-
:發起矢量圖形互動事務,例如增删改等Transaction
這隻是主要的能力,2.0.0 還新增了其它的能力,有興趣的可以去看規範,也可以直接參考 GeoServer 的幫助手冊,十分詳細:
- GeoServer Docs - Services - WFS - WFS reference#operatioins
我隻是好奇,為什麼 GeoServer 本地不能內建一份幫助文檔呢?
4.2. 擷取要素(GetFeature)及常用參數
這裡以 WFS 2.0.0 為例。
一個最簡單的擷取全部矢量要素的請求如下:
http://localhost:4800/geoserver/spatial_base/ows
?service=WFS
&version=2.0.0
&request=GetFeature
&typeNames=spatial_base:guangxi_cities
&outputFormat=application/json
參數
outputFormat
的指定非常重要,若不指定,預設傳回的是 GML 格式資料。
幾個常用的參數如下
參數名 | 值類型 | 描述 |
---|---|---|
count | int | 限制傳回的個數,取前 個 |
featureid | string | 指定要素的 ID 來查詢,格式是“圖層名.id” |
typeNames | string | 要查詢哪個“圖層”,GeoServer 是“工作空間”:“圖層名” |
propertyName | string | 需要傳回什麼屬性字段,用英文逗号連接配接 |
filter | string | 一個 XML 文本,即查詢資訊 |
outputFormat | string | 要傳回資料的格式類型,能力文檔中有 |
其中,
filter
的 XML 就是 WFS 較為诟病的一點,因為這個 XML 構造起來比較麻煩。
4.3. 擷取要素時使用過濾(Filtering)
以一個簡單的框選查詢為例,你需要構造如下的 XML:
<Filter xmlns:ogc="http://www.opengis.net/ogc" xmlns:gml="http://www.opengis.net/gml">
<Intersects>
<PropertyName>geom</PropertyName>
<gml:Envelope srsName="EPSG:4326">
<gml:lowerCorner>109 20</gml:lowerCorner>
<gml:upperCorner>120 30</gml:upperCorner>
</gml:Envelope>
</Intersects>
</Filter>
對于我這份資料來說,這樣一個框選查詢能傳回 11 個要素。注意,
<Intersects>
下的
<PropertyName>
的值,即 "geom",指的是要素圖層的待相交查詢的幾何字段名稱。如果是 Shapefile,它的幾何字段可能是 "SHAPE" 或其它。
關于這個
filter
能進行什麼空間查詢,請參考:
- GeoServer Docs - Filtering - Supported Filtering Language
- GeoServer Docs - Filtering - Filtering Function References
上述的 XML 過濾參數,是通過
GET
請求,發送 QueryString 的方式傳遞到 WFS 的。如果這個過濾的 XML 體積過大,超出了 GET 請求的最大大小(因浏覽器而異,普遍較小),那麼就需要改成
POST
請求,把這個 XML 作為請求體發送到伺服器。
請求路徑:
POST http://localhost:4800/geoserver/spatial_base/ows
請求體和上面的
filter
略有不同,要把其它的請求參數也帶上:
<?xml version='1.0' encoding='UTF-8'?>
<wfs:GetFeature
service="WFS"
version="2.0.0"
outputFormat="json"
xmlns:wfs="http://www.opengis.net/wfs/2.0"
xmlns:fes="http://www.opengis.net/fes/2.0"
xmlns:gml="http://www.opengis.net/gml/3.2"
xmlns:sf="http://www.openplans.org/spearfish"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.opengis.net/wfs/2.0
http://schemas.opengis.net/wfs/2.0/wfs.xsd
http://www.opengis.net/gml/3.2
http://schemas.opengis.net/gml/3.2.1/gml.xsd"
>
<wfs:Query typeNames='spatial_base:guangxi_cities'>
<wfs:PropertyName>geom</wfs:PropertyName>
<wfs:PropertyName>name</wfs:PropertyName>
<fes:Filter>
<fes:PropertyIsEqualTo matchAction="OR">
<fes:ValueReference>name</fes:ValueReference>
<fes:Literal>梧州市</fes:Literal>
</fes:PropertyIsEqualTo>
</fes:Filter>
</wfs:Query>
</wfs:GetFeature>
WFS 1.0.0 和 1.1.0 的又略有不同,詳見:
- GeoServer Docs - Filtering - Filter functions
- OGC Standard - Filter Encoding
WFS 參考資料之複雜,中文教程、例子之少,其實講究效率的年代不願意用它也是情有可原的。
官方的例子,在标準文檔的
Annex B
章節(附件B)中。
線上的文檔,則可以參考 OGC Standard Examples 頁面,找到 WFS 目錄即可。
4.4. 簡述事務(Transaction)
WFS 的事務允許你向伺服器上的資料進行增删改,能增删改的除了屬性資料,當然還包括圖形資料。
在 WFS 2.0.0 中,事務支援如下幾個動作(Action):
- delete
- insert
- replace
- update
以更新為例,仍然是請求 4.3 小節中的位址,發送的 XML 請求體則是:
<?xml version='1.0' encoding='UTF-8'?>
<wfs:Transaction
version="2.0.0"
service="WFS"
xmlns:fes="http://www.opengis.net/fes/2.0"
xmlns:wfs="http://www.opengis.net/wfs/2.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.opengis.net/wfs/2.0 http://schemas.opengis.net/wfs/2.0.0/wfs.xsd">
<!-->要 Update 的要素是 spatial_base:guangxi_cities<-->
<wfs:Update typeName="spatial_base:guangxi_cities">
<!-->更新名稱屬性為“梧州市_重命名”<-->
<wfs:Property>
<wfs:ValueReference>name</wfs:ValueReference>
<wfs:Value>梧州市_重命名</wfs:Value>
</wfs:Property>
<!-->使用 Filtering 隻修改第4個要素<-->
<fes:Filter>
<fes:ResourceId rid="guangxi_cities.4"/>
</fes:Filter>
</wfs:Update>
</wfs:Transaction>
有時候你無法發送
Transaction
請求,傳回的錯誤是“XXX is readonly”,應該是 GeoServer 對編輯請求作了限制,你可以到管理頁面的“Security - Data”下,将“*.*.w”的規則(也就是寫規則)賦予合适的角色,即可得到編輯寫入的權限。
更多例子請參考文末給的例子連結,或者直接查閱對應 WFS 版本的标準文檔中的 Examples 内容。
4.5. 推薦與不推薦
WFS 的要務并不是拿來顯示大量矢量資料的,大量的矢量圖形資料對網絡傳輸、浏覽器渲染的性能要求非常高,甚至浏覽器超過 1000 個正常的 JavaScript 對象就難以把持 rAF 程式的流暢性(一是周遊性能可能不足,二是浏覽器可用作業系統記憶體可能不夠)。
是以,不推薦 WFS 用來全量顯示矢量圖形資料。
針對“既需要顯示、又需要查詢”的需求,可将任務分解:
- 使用 WMTS/TMS/VectorTiles 顯示圖形;
- 使用 WMS/WMTS 的 GetFeatureInfo 或獨立存儲非空間資料,另寫請求接口進行查詢非空間資料;
- 有空間圖形分析或複雜空間查詢需求的,請使用地理資料庫;
- 有編輯需求的,不太推薦使用 WFS 的 Transaction 操作,建議使用地理資料庫 + 可定制的後端查詢接口
OpenLayers6 有幾個 WFS 的例子,其使用 JavaScript 函數拼接請求參數之複雜令人困擾,實在令人提不起用标準 WFS 的欲望。
而 CesiumJS 則直接不考慮這個 OGC 服務,讓使用者自己選擇矢量圖形資料的加載與否(可請求矢量圖形資料後使用
GeoJsonDataSource
來加載)。
5. 什麼是 TileMatrixSet / TileMatrix
你在 WMTS 能力文檔中,一定能看到這兩個東西。但是我覺得官方文檔廢話太多,索性把自己的了解寫了出來。
TileMatrixSet
筆者譯為“瓦片陣集”,而
TileMatrix
即“瓦片陣”。
很多人也許第一次看到這個詞,一時半會兒想不通為什麼是“Matrix”。直譯來說,“Matrix”即矩陣:
假如這個矩陣的每個元素塊上填充的是地圖瓦片,那就能了解了。
是以,
TileMatrix
指的就是某個層級的所有瓦片;自然而然,
TileMatrixSet
就是所有層級的
TileMatrix
“集”。
舉例,GeoServer 中的内置瓦片陣集有一個是
EPSG:4326
,那麼第 7 級瓦片陣即
EPSG:4326:7
。
在 GeoServer 中還有個類似的詞是 Gridset
,在 TileCaching - Gridsets 下可以找到。
6. 常見地圖服務接口的軸朝向
① 使用 Z-order 降維編碼的微軟必應地圖
Z-order
,有時候又叫
莫頓曲線
,參考 wiki - Z-order 或 wikigis - Z-order。
在微軟 Bing 地圖瓦片的編号中使用了這個曲線。這個曲線通常用于四叉樹的編碼。
② 類似 WMTS 的谷歌和 OSM
瓦片的軸和原點均與 WMTS 一樣,隻不過有一個語義上的等價關系:
- TileCol → x(列 Col 值,即橫方向)
- TileRow → y(行 Row 值,即縱方向)
- TileMatrix = z(目前瓦片陣,即瓦片層級)
如下圖所示:
OSM 和 谷歌地圖 的 Z、X、Y 也與 WMTS 一樣,是從 0 開始算的。
以 WMTS 的
TileMatrix=EPSG:900913:7
、
TileCol=103
、
TileRow=55
瓦片為例,那麼 OSM 的瓦片應為:
https://a.tile.openstreetmap.org/7/103/55.png
得到的瓦片:
而對應的谷歌地圖瓦片連結為:
http://mt2.google.com/vt/lyrs=m@167000000&hl=zh-CN&gl=cn&x=103&y=55&z=7
得到的圖:
再把原來 WMTS的瓦片搬來看看:
可以說位置上是一緻的。
③ 百度地圖
原點在 0 度經度、0 度緯度:
百度的 X 和 Y 值如上圖所示,有正有負。
瓦片層級,從 3 級起算,最大 21 級。
關于百度的 N 種坐标,參考此文 百度地圖API詳解之地圖坐标系統,業務上對高德、百度、騰訊等 LBS 廠商用得不多,故不再列舉,有需要的朋友可自行在網絡上查找。
參考資料
- OGC e-Learning
- OpenStreetMap/Google/百度/Bing瓦片地圖服務(TMS) - 可可西 - 部落格園
- Gist - WFS 2.0 Examples
- OGC Standards' Schemas (Examples)
- GeoServer中WMS、WFS的請求規範 - 李曉晖 - 部落格園