2014年12月13日土曜日

PostgreSQL(PostGIS) でベクトルタイルを作る決意を固めたものの挫折しそう

この記事は FOSS4G Advent Calendar 2014 の 12/13 (土) の記事です。

さて、ここ1年色々環境が変化したわけで、あまり FOSS4G 関連の場に出ていけてないそんな私ですが、今年は久しぶりに書きたいと思います。
ブログもうやってなかったんですが、このために作りました。来年また使うと思います。

ベクトルタイルです。ベクトルタイルですってよ。
新卒で某オレンジ色のWebで地図な会社に入って、退職するまでずっと地図画像作ったり、配信していたわけですが、ベクトルタイルに関してはちょっと距離を置いていたわけです。
数学的な素養がないとか、クライアントサイドでの描画を行なうための某フリーダムな言語およびデザイン等にあまり明るくないなど色々理由はあるわけですが。

普段タイルタイル言ってるだけではだめだなーって。そう思ったのでベクトルタイルを作ろうと思ったんです。SQLで(オカシイ)。

趣味でいじっている地理空間データはすべて PostgreSQL (PostGIS) に格納しているんですが、RDBMS 内でデータ管理からタイル生成、隙をみてタイル配信までできやしないかとふと思ったのでやってみたら挫折した記録をお届けしたいと思います。
特に PostgreSQL の JSON 関連機能が最近がんがん実装されてきたりしているので、色々夢が広がったんでしょうね、数時間前の私は。

ちなみに RDBMS は前職でも触ってたし、現職では RDBMS 担当なわけですが、どちらかというと DBA 的な部分の仕事が多くて実は SQL 力が低いです。

すごい頑張ったんですが、結果的にはタイルの境界線を発生させる関数しか現状できていません。以下です。


引数に zoom レベルをとります。RECORD 型で zoom レベルと LineString を返します。使い方はこんな感じ。

insert into tileline (zoom, geom) select zoom, geom from create_tileline(16) as (zoom integer, geom geometry);

QGIS で表示するとこんな感じ。

zoom レベルにはそのラインが存在する最大レベルが入ります。この値によって以下のような条件を与えれば、zoom レベルでの使い分けが可能になります。
select * from tileline where zoom <= 10
上の画像は zoom レベル16のラインですが、QGISで zoom <= 13 のフィルタをかけると↓になります。

後は、対象のフィーチャと重なるタイルのラインを Geometry Collection か MultiLineString かなんかにして ST_Split でタイル化完了!とか思ってたんですが、ST_Split が LineString しか取れないらしいです...orz
なんで MultiLine とかじゃないとダメかというと、切断に使うタイルのラインが複数ある場合一回で切らないと処理が超面倒くさそうというかこの短時間では実装できなさそうだったというだけなんですが...orz
MultiLineString を ST_Union する手もあるんですが、処理時間やTempな領域とはいえ一時的にかなりリソースを食いそうだったんでやめました。
やりたかったイメージ↓
ここで Split!!!
というわけでかなり道半ばですが、SQL力向上のためにも継続してやっていきたいと思います。
来年は OPEN KWASAKI で地元貢献目標で頑張ります。