天天看點

OGC WebGIS 常用服務标準(WMS/WMTS/TMS/WFS)速查

本文隻介紹實際工作中常用的 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 參數,是“工作空間名:圖層名”這樣的組合。

那麼,它傳回的就是一張圖:

OGC WebGIS 常用服務标準(WMS/WMTS/TMS/WFS)速查

這是最正常的使用“鍵值對”,也就是 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 a 

LAYERS

 param is required. 

STYLES

 is 

''

 by default. 

VERSION

 is 

1.3.0

 by default. 

WIDTH

HEIGHT

BBOX

 and 

CRS

 (

SRS

 for WMS version < 1.3.0) will be set dynamically.

也就是至少要設定

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 的軸朝向如下圖所示。

OGC WebGIS 常用服務标準(WMS/WMTS/TMS/WFS)速查

2.2. 能力

  • GetCapabilities

    (擷取WMTS中繼資料文檔,也叫擷取能力文檔)
  • GetTile

    (擷取一張瓦片)
  • GetFeatureInfo

    (可選能力)

2.3. 示意圖

OGC WebGIS 常用服務标準(WMS/WMTS/TMS/WFS)速查

WMTS 的行列号、瓦片陣(TileMatrix,類似層級的概念,參考第 5 節)是從 0 開始算的,例如

TileMatrix=EPSG:4326:0&TileCol=0&TileRow=0

2.4. 請求瓦片舉例(GetTile)

以 2.3 小節中的“TileRow=55 & TileCol=103”這張瓦片為例:

OGC WebGIS 常用服務标準(WMS/WMTS/TMS/WFS)速查

它的請求位址是:

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 的能力文檔,搜尋

    ResourceURL

    标簽,此處的位址是 REST 風格的。

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 軸朝向如下圖所示。

OGC WebGIS 常用服務标準(WMS/WMTS/TMS/WFS)速查

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
           

如下圖所示:

OGC WebGIS 常用服務标準(WMS/WMTS/TMS/WFS)速查

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 限制傳回的個數,取前

count

 個
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”即矩陣:

OGC WebGIS 常用服務标準(WMS/WMTS/TMS/WFS)速查

假如這個矩陣的每個元素塊上填充的是地圖瓦片,那就能了解了。

是以,

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(目前瓦片陣,即瓦片層級)

如下圖所示:

OGC WebGIS 常用服務标準(WMS/WMTS/TMS/WFS)速查

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
           

得到的瓦片:

OGC WebGIS 常用服務标準(WMS/WMTS/TMS/WFS)速查

而對應的谷歌地圖瓦片連結為:

http://mt2.google.com/vt/lyrs=m@167000000&hl=zh-CN&gl=cn&x=103&y=55&z=7
           

得到的圖:

OGC WebGIS 常用服務标準(WMS/WMTS/TMS/WFS)速查

再把原來 WMTS的瓦片搬來看看:

OGC WebGIS 常用服務标準(WMS/WMTS/TMS/WFS)速查

可以說位置上是一緻的。

③ 百度地圖

原點在 0 度經度、0 度緯度:

OGC WebGIS 常用服務标準(WMS/WMTS/TMS/WFS)速查

百度的 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的請求規範 - 李曉晖 - 部落格園

繼續閱讀