シェープファイルからベクタータイルを作成して地図表示する

シェープファイルからベクタータイルを作成しTileServer GLで地図表示します。また、Maputnikでスタイルファイルを作成して地図にスタイルを適用します。

シェープファイルを用意

シェープファイルとして今回は以下のデータを利用します。

  • 国土数値情報ダウンロードサイト(国土交通省) / 行政区域 / 北海道(平成31年)N03-190101_01_GML.zip(2020/6/4取得)
$ ls -l
合計 41428
-rw-rw-r-- 1 ubu ubu 42415745  6月  4 19:34 N03-190101_01_GML.zip
$ unzip N03-190101_01_GML.zip 
Archive:  N03-190101_01_GML.zip
  inflating: KS-META-N03-19_01_190101.xml  
  inflating: N03-19_01_190101.dbf    
  inflating: N03-19_01_190101.geojson  
  inflating: N03-19_01_190101.prj    
  inflating: N03-19_01_190101.shp    
  inflating: N03-19_01_190101.shx    
  inflating: N03-19_01_190101.xml    

GeoJSON に変換

シェープファイルをGeoJSONファイルに変換します。同時に、空間参照をEPSG:4326(WGS84)に変換します。

$ ogr2ogr -f GeoJSON Hokkaido.json -t_srs EPSG:4326 N03-19_01_190101.shp

mbtiles に変換

GeoJSONファイルをmbtilesファイルに変換します。

$ tippecanoe -o Hokkaido.mbtiles Hokkaido.json
For layer 0, using name "Hokkaido"
9587 features, 4796684 bytes of geometry, 3454 bytes of separate metadata, 4722 bytes of string pool
  99.9%  14/14849/5929  

TileServer GL で地図表示

TileServer GLを起動してmbtilesを地図表示します。上記で作成したmbtilesファイルを--mbtilesオプションで指定します。ちなみにオプションは他にも色々あります

$ docker run -it -v $(pwd):/data -p 8080:80 klokantech/tileserver-gl --mbtiles Hokkaido.mbtiles
Starting Xvfb on display 99
xdpyinfo:  unable to open display ":99".

Starting tileserver-gl v2.6.0
Automatically creating config file for Hokkaido.mbtiles
WARN: MBTiles not in "openmaptiles" format. Serving raw data only...
Run with --verbose to see the config file here.
Starting server
Listening at http://[::]:80/
Startup complete

http://localhost:8080にアクセスするとトップページが表示されます。

トップページの「Inspect」ボタンを押すと地図表示されます。

トップページの「TileJSON」リンクを押すとJSONファイルの内容が表示されます。このTileJSONのURL(TileJSONの中に書かれているURLではなくTileJSON自体のURL、ここではhttp://localhost:8080/data/Hokkaido.json)は後でスタイルを設定する際に使用します。

ここまでで、mbtilesへの変換までうまくいったことが確認できました。

Maputnik でスタイルファイルを作成

Maputnikを起動します。

$ docker run -it --rm -p 8888:8888 maputnik/editor
Serving HTTP on 0.0.0.0 port 8888 (http://0.0.0.0:8888/) ...

http://localhost:8888にアクセスするとスタイルエディタが表示されます。

デフォルトで色々とスタイルが設定されていますが、「Open」ー「Empty Style」を選択して一旦クリアします。

まっさらな状態になります。

「Data Sources」でデータソースを選択します。「TileJSON URL」には、前述のTileServer GLのトップページにあったTileJSONのURLを設定します。

まだスタイルを設定していないため、「View」がMapのままだと地図が見えません。「View」をInspectにすると地図が見えるようになります。

「Add Layer」からレイヤーを追加します。

レイヤーが追加され、スタイルを設定できるようになります。

レイヤーのスタイルを設定していきます。スタイルの反映結果が見えるようにするため「View」をMapに変更します。今回は「Color」と「Outline color」を設定してみます。スタイルをいじるとリアルタイムに地図に反映されます。うまく反映されない場合はレイヤー名の横の目の形のアイコンをクリックして表示・非表示を一度切り替えると表示されます。

スタイルの設定が完了したら「Export」でスタイルをJSONファイルとしてダウンロードします。

ダウンロードしたJSONを適当な名前に変更します。今回はHokkaido_style.jsonとします。

{
  "version": 8,
  "name": "Empty Style",
  "metadata": {"maputnik:renderer": "mbgljs"},
  "sources": {
    "Hokkaido": {
      "type": "vector",
      "url": "http://localhost:8080/data/Hokkaido.json"
    }
  },
  "sprite": "",
  "glyphs": "https://orangemug.github.io/font-glyphs/glyphs/{fontstack}/{range}.pbf",
  "layers": [
    {
      "id": "layer1",
      "type": "fill",
      "source": "Hokkaido",
      "source-layer": "Hokkaido",
      "layout": {"visibility": "visible"},
      "paint": {
        "fill-color": "rgba(168, 255, 187, 1)",
        "fill-outline-color": "rgba(255, 0, 0, 1)"
      }
    }
  ],
  "id": "meppdf0vz"
}

スタイルを指定して TileServer GL を起動

TileServer GLにスタイルJSONの場所を指定するためにconfig.jsonを作成します。config.jsonでは様々な設定ができますが、今回は以下のように最低限の設定を行います。スタイルのJSONファイルと地図のmbtilesファイルを指定しています。

{
  "options": {
    "paths": {
      "styles": "./",
      "mbtiles": ""
    }
  },
  "styles": {
    "mydesign": {
      "style": "Hokkaido_style.json"
    }
  },
  "data": {
    "Hokkaido": {
      "mbtiles": "Hokkaido.mbtiles"
    }
  }
}

TileServer GLを起動します。引数なしで起動するとデフォルトでカレントディレクトリのconfig.jsonが読み込まれて起動します。

$ docker run -it -v $(pwd):/data -p 8080:80 klokantech/tileserver-gl 
Starting Xvfb on display 99
xdpyinfo:  unable to open display ":99".

Starting tileserver-gl v2.6.0
Using specified config file from config.json
Starting server
Listening at http://[::]:80/
Startup complete
GET /data/Hokkaido.json 200 4312 - 11.537 ms
GET /data/Hokkaido.json 200 4312 - 12.097 ms
GET /data/Hokkaido.json 200 4312 - 13.054 ms
GET /data/Hokkaido.json 200 4312 - 20.552 ms
GET /data/Hokkaido.json 200 4312 - 21.183 ms
GET /data/Hokkaido.json 200 4312 - 21.755 ms
GET /data/Hokkaido.json 200 4312 - 22.335 ms
GET /data/Hokkaido.json 200 4312 - 22.827 ms
GET /data/Hokkaido.json 200 4312 - 23.661 ms
GET /data/Hokkaido.json 200 4312 - 24.502 ms
GET /data/Hokkaido.json 200 4312 - 25.161 ms
GET /data/Hokkaido.json 200 4312 - 25.832 ms
GET /data/Hokkaido.json 200 4312 - 26.627 ms
GET /data/Hokkaido.json 200 4312 - 1.207 ms

http://localhost:8080にアクセスすると、先程は無かった「STYLES」という表示が追加されています。

「Viewer」を開くと、設定したスタイルどおりに地図が表示されます。初期表示位置や縮尺がいいかげんなので画面上のどこに地図が表示されているのか分かりにくいことがありますが、拡大・縮小(マウスホイール、+-アイコン)やスライド(マウスドラッグ、矢印キー)で調節できます。

「View」または「Vector」ではベクタータイルが、「Raster」ではラスタータイルが表示されます。ウェブブラウザの開発者ツールで見てみると、ベクタータイルの方はcanvas要素で描画されており、ラスタータイルの方はタイル画像で描画されているのが分かります。
また、ベクタータイルの方のみ、回転と視点移動(マウス右ボタンを押したままドラッグ)ができます。

Mapbox GL JS で表示

参考:OpenMapTilesのチュートリアル(Mapbox GL JS)

TestMapboxGLJS.html

<!DOCTYPE html>
<html>

<head>
    <link rel='stylesheet' href='https://api.tiles.mapbox.com/mapbox-gl-js/v1.10.1/mapbox-gl.css'>
    <script src='https://api.tiles.mapbox.com/mapbox-gl-js/v1.10.1/mapbox-gl.js'></script>
    <script defer src="TestMapboxGLJS.js"></script>
    <style>
        html, body, #map { width: 100%; height: 100%; }
    </style>
</head>

<body>
    <div id='map'></div>
</body>

</html>

TestMapboxGLJS.js

var map = new mapboxgl.Map({
    container: 'map',
    style: 'http://localhost:8080/styles/mydesign/style.json',
    center: [143, 43],
    zoom: 6
});

OpenLayers で表示

OpenLayersライブラリでOpenMapTilesを表示するには、ラスタータイルまたはベクタータイルを使用する2つの方法があります。

サーバーからのラスタータイル

OpenLayersは、デフォルトではベクタータイルをサポートしていません。ラスタータイルは、TileServer GLと呼ばれるオープンソースのサーバーソフトウェアを使用して、必要に応じて任意のGLスタイルで生成できます。このようなラスタータイルは、ol.source.XYZソースを使用して表示できます。

プラグイン付きのベクタータイル

ベクタータイルは、OpenMapTilesと共にol-mapboxスタイルのプラグインを使用してOpenLayersで表示できます。

https://translate.google.com/translate?sl=en&hl=ja&u=https%3A%2F%2Fopenmaptiles.org%2Fdocs%2Fwebsite%2Fopenlayers%2F

プラグインを使わない場合(ラスタータイルを使うことになる)

参考:OpenLayersのサンプル(XYZ)

TestOpenLayersRaster.html

<!DOCTYPE html>
<html>

<head>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.3.1/css/ol.css">
    <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.3.1/build/ol.js"></script>
    <script defer src="TestOpenLayersRaster.js"></script>
    <style>
        html, body, #map { width: 100%; height: 100%; }
    </style>
</head>

<body>
    <div id="map"></div>
</body>

</html>

TestOpenLayersRaster.js

var map = new ol.Map({
    target: 'map',
    layers: [
        new ol.layer.Tile({
            source: new ol.source.XYZ({
                url: 'http://localhost:8080/styles/mydesign/{z}/{x}/{y}.png'
            })
        })
    ],
    view: new ol.View({
        center: ol.proj.fromLonLat([143, 43]),
        zoom: 6
    })
});

ol-mapbox-style プラグインを使う場合

参考:OpenMapTilesのチュートリアル(OpenLayers)OpenLayersのサンプル(Vector tiles created from a Mapbox Style object)

TestOpenLayersVector.js

<!DOCTYPE html>
<html>

<head>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.3.1/css/ol.css">
    <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.3.1/build/ol.js"></script>
    <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans">
    <script src="https://unpkg.com/ol-mapbox-style@5.0.2/dist/olms.js"></script>
    <script defer src="TestOpenLayersVector.js"></script>
    <style>
        html, body, #map { width: 100%; height: 100%; }
    </style>
</head>

<body>
    <div id="map"></div>
</body>

TestOpenLayersVector.js

olms('map', 'http://localhost:8080/styles/mydesign/style.json').then(function (map) {
    map.setView(new ol.View({
        center: ol.proj.fromLonLat([143, 43]),
        zoom: 6
    }))
});

Leaflet で表示

OpenMapTilesをマップレイヤーとして使用する方法は3つあります。

・サーバーからのラスタータイル

mapbox-gl-leafletプラグインを備えたベクタータイル

VectorGridプラグインを使用したベクタータイル

サーバーからのラスタータイル

リーフレットは、デフォルトではベクタータイルをサポートしていません。ベースマップの場合は、従来のラスタータイル(メルカトルXYZ)で使用することをお勧めします。このようなタイルは、TileServer GLと呼ばれるオープンソースのサーバーソフトウェアを使用して、必要に応じて任意のGLスタイルで生成できます。

https://translate.google.com/translate?sl=en&hl=ja&u=https%3A%2F%2Fopenmaptiles.org%2Fdocs%2Fwebsite%2Fopenlayers%2F

プラグインを使わない場合(ラスタータイルを使うことになる)

TestLeafletRaster.html

<!DOCTYPE html>
<html>

<head>
    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.6.0/dist/leaflet.css" />
    <script src="https://unpkg.com/leaflet@1.6.0/dist/leaflet.js"></script>
    <script defer src="TestLeafletRaster.js"></script>
    <style>
        html, body, #map { width: 100%; height: 100%; }
    </style>
</head>

<body>
    <div id="map"></div>
</body>

</html>

TestLeafletRaster.js

let mymap = L.map('map').setView([43, 143], 6);
L.tileLayer('http://localhost:8080/styles/mydesign/{z}/{x}/{y}.png').addTo(mymap);

mapbox-gl-leaflet プラグインを使う場合

参考:OpenMapTIlesのチュートリアル(Leaflet)

TestLeafletVector1.html

<!DOCTYPE html>
<html>

<head>
    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.6.0/dist/leaflet.css">
    <script src="https://unpkg.com/leaflet@1.6.0/dist/leaflet.js"></script>
    <link rel='stylesheet' href="https://api.tiles.mapbox.com/mapbox-gl-js/v1.10.1/mapbox-gl.css">
    <script src="https://api.tiles.mapbox.com/mapbox-gl-js/v1.10.1/mapbox-gl.js"></script>
    <script src="https://unpkg.com/mapbox-gl-leaflet/leaflet-mapbox-gl.js"></script>
    <script defer src="TestLeafletVector1.js"></script>
    <style>
        html, body, #map { width: 100%; height: 100%; }
    </style>
</head>

<body>
    <div id="map"></div>
</body>

</html>

TestLeafletVector1.js

var map = L.map('map').setView([43, 143], 6);
var gl = L.mapboxGL({
    style: 'http://localhost:8080/styles/mydesign/style.json'
}).addTo(map);

VectorGrid プラグインを使う場合

参考:OpenMapTIlesのチュートリアル(Leaflet)

TestLeafletVector2.html

<!DOCTYPE html>
<html>

<head>
    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.6.0/dist/leaflet.css">
    <script src="https://unpkg.com/leaflet@1.6.0/dist/leaflet.js"></script>
    <script src="https://unpkg.com/leaflet.vectorgrid@1.3.0"></script>
    <script defer src="TestLeafletVector2.js"></script>
    <style>
        html, body, #map { width: 100%; height: 100%; }
    </style>
</head>

<body>
    <div id="map"></div>
</body>

</html>

TestLeafletVector2.js

var map = L.map('map').setView([43, 143], 6);
var openMapTilesLayer = L.vectorGrid.protobuf("http://localhost:8080/data/Hokkaido/{z}/{x}/{y}.pbf", {
    vectorTileLayerStyles: {
        Hokkaido: {
            fill: true,
            fillColor: 'rgba(168, 255, 187, 1)',
            color: 'rgba(255, 0, 0, 1)'
        }
    }
}).addTo(map);

参考

コメントを残す