在第二天的資料格式介紹中,曾提到的 WMTS 線上圖磚服務,今天我們將實際的串接服務並將圖層呈現在地圖上。
複習一下
WMTS 全稱是 Web Map Tile Service,是一種將高品質地圖依據網格系統切割成小圖磚發布的網路服務。
Google Maps API (SDK) 將地圖依不同層級,切割成數個正方形的網格,當地圖移動至新的位置或縮放層級時,會根據當下的層級位置,給出 z, x, y 這三個數值,並根據這三個數值取得它對應的圖片。
這次練習所要使用的圖磚資源,是由國土測繪中心所提供的國土測繪服務雲的資源。
目前國土測繪服務雲所提供的資料,大多數需要以機關單位的身份提出申請,但今天我們要使用的 WMTS 服務,是屬於不用申請的免申請服務 API。
連線國土測繪的 EPSG:3857 版本的介接網址 https://wmts.nlsc.gov.tw/wmts ,會發現拿到的是一個 XML 格式的檔案,內容長得像下面這個截圖。
這個 XML 檔案其實是由 OGC (開放地理空間協會) 所提出的網路地圖介接規格,內容會描述這個 WMTS 服務所能提供的圖層與詳細規格。
而在 SDK 中介接圖磚,我們要看的是這個區塊的 ResourceURL tag 中的 template。
<Layer>
<ows:Title>臺灣通用電子地圖</ows:Title>
<ows:Identifier>EMAP</ows:Identifier>
<ows:BoundingBox crs="urn:ogc:def:crs:EPSG::3857">
<ows:LowerCorner>-2.0037507842788246E7 -3.0240971958386146E7</ows:LowerCorner>
<ows:UpperCorner>2.0037507842788246E7 3.024097145838615E7</ows:UpperCorner>
</ows:BoundingBox>
<Style isDefault="true">
<ows:Title>Default Style</ows:Title>
<ows:Identifier>default</ows:Identifier>
</Style>
<Format>image/jpeg</Format>
<TileMatrixSetLink>
<TileMatrixSet>GoogleMapsCompatible</TileMatrixSet>
</TileMatrixSetLink>
<ResourceURL format="image/jpeg" resourceType="tile" template="https://wmts.nlsc.gov.tw/wmts/EMAP/{Style}/{TileMatrixSet}/{TileMatrix}/{TileRow}/{TileCol}"/>
</Layer>
比對 tags 所提供的各欄位資訊,我們可以串出以下的 URL。
https://wmts.nlsc.gov.tw/wmts/EMAP/default/GoogleMapsCompatible/{TileMatrix}/{TileRow}/{TileCol}
參照國土測繪雲上所提供的連線範例,確認無誤。
連線範例:https://wmts.nlsc.gov.tw/wmts/EMAP/default/GoogleMapsCompatible/15/14127/27366
在 Google Maps SDK 上要加入 WMTS 圖層,使用的是 TileOverlay
這個類別,並實作 TileProvider
這個介面 (圖磚的來源)。
UrlTileProvider
UrlTileProvider 是實作 TileProvider
的類別,專門用來讀取 Url 來源的圖磚,而我們需要 override
的方法是 getUrl()
。
完整實作會如以下:
class WMTSTileProvider(tileWidth: Int, tileHeight: Int):
UrlTileProvider(tileWidth, tileHeight) {
override fun getTileUrl(x: Int, y: Int, zoom: Int): URL? {
val url = "https://wmts.nlsc.gov.tw/wmts/EMAP/default/GoogleMapsCompatible/$zoom/$y/$x"
return try {
URL(url)
} catch (e: MalformedURLException) {
null
}
}
}
Google Maps SDK 的 x
, y
, zoom
分別是對照 Url 上的 TileCol
, TileRow
, TileMatrix
,在寫的時候要特別注意,不然讀取出來的圖磚會對不上圖面的位置。
TileOverlay
至 GoogleMap
class WMTSMapActivity : AppCompatActivity() {
private val binding: ActivityWmtsMapBinding by lazy {
ActivityWmtsMapBinding.inflate(layoutInflater)
}
private var googleMap: GoogleMap? = null
private var wmtsTileOverlay: TileOverlay? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
binding.mapView.onCreate(savedInstanceState)
binding.mapView.getMapAsync {
googleMap = it
wmtsTileOverlay = setWmtsTileOverlay(it)
}
}
/**
* 設定 WMTS 圖層並取得 TileOverlay 物件
*/
private fun setWmtsTileOverlay(map: GoogleMap): TileOverlay? {
// 建立 WMTS 圖磚服務來源 並填入圖磚的長寬
val provider = WMTSTileProvider(256, 256)
// 建立 WMTS 圖層設定
val tileOverlayOptions =
TileOverlayOptions().tileProvider(provider)
// 將圖層加入到圖台上
return map.addTileOverlay(tileOverlayOptions)
}
// 以下省略...
}
Google Maps 使用的圖磚預設是 256 x 256 的大小,但官方建議高解析度裝置,可使用 512 x 512 的大小,效果會更好。
而國土測繪所提供的圖磚是 256 的大小,因此在程式碼中設定的是 256 x 256。
另外,如果是要加入 TileOverlay
作為整個圖台的底圖,可以將原本的地圖類型設定為 GoogleMap.MAP_TYPE_NONE
,才不會像上方的範例程式,在縮放的時候會看得到預設的 Google 電子地圖。
AndroidManifest.xml
設定網路權限因為圖磚是透過網路服務存取,記得網路權限也要設定。
<manifest>
<!-- 略... -->
<uses-permission android:name="android.permission.INTERNET"/>
<!-- 略... -->
</manifest>
TileOverlay
假設圖層是可以讓使用者切換的,這時候就會需要清除功能。
清除的方式也很簡單,只要對我們剛才建立的 TileOverlay
呼叫 remove()
即可。
wmtsTileOverlay?.remove()
TileOverlay
細部調整TileOverlayOptions
除了 tileProvider
用來設定圖磚來源外,還有幾個方法參數能夠調整圖面的樣式。
fadeIn
: 圖層的淡入動畫,預設為開啟。transparency
: 圖層的透明度,範圍值從完全不透明 0.0f 到完全透明 1.0f。適合用在不同資訊圖層的套疊上。visible
: 預設為 true
。當設定為 false
時,圖層為不顯示,但設定的屬性等仍存在。zIndex
: 圖層在圖台上疊加的位置,預設為 0 。數字越高的疊在上面,相同數值時則隨機。clearTileCache()
當圖磚來源有更新時,clearTileCache()
可以強制圖磚重新整理。
以上,就是今天的 WMTS 圖層套疊功能的介紹。
有興趣的朋友,可以再另外套疊看看國土測繪的其他圖磚服務,或是 中央研究院臺灣百年歷史地圖 WMTS 服務來玩玩。
發文數來到第十篇,也代表挑戰已進行了三分之一,繼續努力!
明天見啦~