library(tmap)
library(tmap.mapgl)
library(osmdata)
## Data (c) OpenStreetMap contributors, ODbL 1.0. https://www.openstreetmap.org/copyright
library(dplyr)
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
FOSS4G Hokkaido 2025での湯谷さんの発表「mapglパッケージの紹介」で紹介されていたtmap.mapglパッケージを使ってみました。mapglパッケージの機能をより手軽に使えるようにできるようです。せっかくなので3D polygon layerを使って、建物の高さを反映させたポリゴン入りの地図を描いてみました。とはいえ、やっていることは、tmap.mapglの3D polygon layerの例題コードほぼそのままです。
準備
必要なパッケージを読み込みます。osmdataパッケージは、OpenStreetMapからデータを取得するのにつかいます。
各種設定です。
tmap_mode
関数で、maplibreを使うように設定します。
描画範囲は、金沢駅を中心にだいたい2km四方の範囲とします。
tmap_mode("maplibre")
## ℹ tmap modes "plot" -> "view" -> "mapbox" -> "maplibre"
## ℹ rotate with `tmap::rtm()`switch to "plot" with `tmap::ttm()`
# 金沢駅の位置
<- 36.578044
lat <- 136.648175
lon
# 3Dポリゴンデータの取得範囲
# 経度は±40秒、緯度は±30秒の範囲(おおよそ±1kmに対応)
<- lon - 0.0125
xmin <- lat - 0.00833
ymin <- lon + 0.0125
xmax <- lat + 0.00833 ymax
データ
建物データのデータを取得します。
<- opq(bbox = c(xmin, ymin, xmax, ymax)) |>
buildings add_osm_feature(key = "building") |>
osmdata_sf()
ポリゴンをとりだして、levels
(建物の階数)とheight
(高さ)を設定します。
<- buildings$osm_polygons |>
buildings_poly # 高さと建物の階数を文字列から数値に変換する
mutate(levels = as.numeric(`building:levels`),
height = as.numeric(height)) |>
# 階数がないときは2階建てとする
mutate(levels = if_else(is.na(levels), 2, levels),
# 高さがないときは階数×3mとする
height = if_else(is.na(height), levels * 3, height))
# 最大の高さ
<- max(buildings_poly$height) mx
描画
描画します。
tm_shape(buildings_poly) +
tm_polygons_3d(height = "height",
options = opt_tm_polygons_3d(height.max = mx)) +
tm_maplibre(pitch = 60)
以下のような地図が描画できました。実際の出力は、インタラクティブに拡大縮小などできます。
建物ポリゴンなしで描画
と、ここまで来たところで、領域外でも建物が描画されていることに気がつきました。ということで、建物ポリゴンなしで描画してみます。
tm_shape
関数で、建物ポリゴンではなく、バウンディングボックスとCRSを指定します。
tm_shape(bbox = c(xmin, ymin, xmax, ymax),
crs = 4326) + # WGS84
tm_maplibre(pitch = 60)
建物入りの地図を描くだけなら、これでもいいかもしれません。