tmap.mapglパッケージで建物ポリゴン入り地図を描画してみた

R
作者

伊東宏樹

公開

2025年10月14日

更新日

2025年10月14日

FOSS4G Hokkaido 2025での湯谷さんの発表「mapglパッケージの紹介」で紹介されていたtmap.mapglパッケージを使ってみました。mapglパッケージの機能をより手軽に使えるようにできるようです。せっかくなので3D polygon layerを使って、建物の高さを反映させたポリゴン入りの地図を描いてみました。とはいえ、やっていることは、tmap.mapglの3D polygon layerの例題コードほぼそのままです。

準備

必要なパッケージを読み込みます。osmdataパッケージは、OpenStreetMapからデータを取得するのにつかいます。

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

各種設定です。

tmap_mode関数で、maplibreを使うように設定します。

描画範囲は、金沢駅を中心にだいたい2km四方の範囲とします。

tmap_mode("maplibre")
## ℹ tmap modes "plot" -> "view" -> "mapbox" -> "maplibre"
## ℹ rotate with `tmap::rtm()`switch to "plot" with `tmap::ttm()`

# 金沢駅の位置
lat <- 36.578044
lon <- 136.648175

# 3Dポリゴンデータの取得範囲
# 経度は±40秒、緯度は±30秒の範囲(おおよそ±1kmに対応)
xmin <- lon - 0.0125
ymin <- lat - 0.00833
xmax <- lon + 0.0125
ymax <- lat + 0.00833

データ

建物データのデータを取得します。

buildings <- opq(bbox = c(xmin, ymin, xmax, ymax)) |>
  add_osm_feature(key = "building") |>
  osmdata_sf()

ポリゴンをとりだして、levels(建物の階数)とheight(高さ)を設定します。

buildings_poly <- buildings$osm_polygons |>
# 高さと建物の階数を文字列から数値に変換する
  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))

# 最大の高さ
mx <- max(buildings_poly$height)

描画

描画します。

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)

建物入りの地図を描くだけなら、これでもいいかもしれません。