Node.js
ベクタータイル

ST_AsMVTを使ってベクタータイルが作れるか?

本記事については問題があり、原因については下記にて説明しています。
https://qiita.com/R_28/items/49826f822121cb15e11c

前提

結論としてST_AsMVTでベクタータイルは作れます。(そういう関数なので)
下記に詳細は記載されていますので、ST_AsMVTを試してみたい方はこちらを参考にされるほうが良いです。
http://waigani.hatenablog.jp/entry/2017/12/22/060000

自分はベクタータイルの作り方は下記の「simple-vectorizer」を参考にしています。
https://qiita.com/honjo/items/8ea61f5a9c1bbaa669c0
https://github.com/mapion/simple-vectorizer

ここでの本題は
ST_AsMVTで「simple-vectorizer」と同じベクタータイルが生成できるか?
になります。

simple-vectorizerは次のような手順でベクタータイルを作成しています。

  1. タイル状にクリッピングしたジオメトリとパラメータを作成
  2. ジオメトリの結合、単純化を適用
  3. 生成したジオメトリをGeoJSONに変換して出力
  4. JSONをmapnik.VectorTileを使ってバイナリ化

http://mapnik.org/documentation/node-mapnik/3.6/#VectorTile.getData

1から3まではSQLで処理し、JSONからバイナリ化はNode.js側で処理している設計ですね。

この際、

  • ジオメトリからJSONに変換している
  • JSONをバイナリにNode.jsで変換している

といったところオーバヘッドになっているわけですが、
PostGIS2.4から「ST_AsMVT」が使えるようになったことから
「SQLでバイナリ化まで可能」になったようです。

で、ST_AsMVTで同様のベクタータイルが生成できるのかを検証。

環境

OS:
Windows10

PostgreSQL:
'PostgreSQL 10.1, compiled by Visual C++ build 1800, 64-bit'

PostGIS:
'2.4 USE_GEOS=1 USE_PROJ=1 USE_STATS=1'

タイル:
16/58306/25693

レイヤー:
rdcl

SQL

ST_AsMVTを使用したSQL部分については下記の通り

sample.sql
SELECT ST_AsMVT(q, 'rdcl', 4096, 'geom') 
FROM (
    SELECT
        rdctg AS c1,
        ST_AsMVTGeom(
            ST_Simplify(ST_LineMerge(ST_Collect(geom)),map.pixel_at_zoom(16)), --- 1
            map.tile_to_box(58306,25693,16,2),
            4096,
            0,
            true) --- 2
            AS geom
    FROM (
        SELECT 
                rdctg,
                (ST_Dump(geom)).geom --- 3
        FROM rdcl 
        WHERE geom && map.tile_to_box(58306,25693,16,2)
    ) a GROUP BY a.rdctg
) as q

  1. ST_Transformは実施していません。(ST_AsMVTGeomがやっている?)
  2. タイルのクリッピング処理をST_AsMVTGeomで実施
  3. そのため、map.safe_intersectionは省略

描画

SQLを一度テキストで吐き出してバイナリ化、vt2gejsonでJSON化し、表示。

やり方は下記参照
http://waigani.hatenablog.jp/entry/2017/12/22/060000

GEOJSONの表示は下記のサイトを使用
http://geojson.io/

image.png

比較

赤:simple-vectorizerで作成したジオメトリ
黒:ST_AsMVTで作成したジオメトリ

※simple-vectorizerで生成したベクタータイルのバイナリをvt2gejsonでJSONに変換して使用

image.png

なんかずれるんだよなぁ

考察

なぜずれるか

  1. ST_TransformとST_AsMVTGeomの座標変換での差?
  2. map.safe_intersectionの差?

ずれ方を見る限り、中心付近ではマッチしていることから、測地系のずれではなさそう。
投影法かなぁ