これは MIERUNE AdventCalendar 20247日目の記事です。
昨日は @KEI_YAMA さんによる QGIS for Facility Management Applications - QGISを用いた施設管理アプリケーションの作成 でした。
はじめに
実は前からgeojsonの重心座標を一発で取れるツールが欲しいなと思っており、今まではQGISを使っていたのですが、自身の技術向上も兼ね、DuckDB-Wasmにて構築を行いました
結論から言いますと、完璧なものが出来たとは言い難いのですが、かなり勉強になりましたので紹介します
DuckDB-Wasmとは
Webブラウザ上で動作するDuckDBのWebAssembly版で、主なポイントとしては
- Webブラウザ上でSQLクエリを実行できる
- サーバー側の処理は不要で、クライアントサイドのみでデータベース操作が可能
- クエリ処理をブラウザのメモリ内で完結し、ローカルデータ分析に最適
- 標準SQLクエリをサポートし、CSVやParquet形式のデータを扱える
- ネットワーク接続がなくても動作するため、オフラインでのデータ分析が可能
というようなものになります
DuckDBにはSpatial Extensionという地理空間データを処理するための拡張機能があり、これがほぼPostGISと同じことが出来る
というのが今回学ぼうと思ったきっかけになります
やったこと
簡単なWEBアプリケーションを作りました
主な利用ライブラリーは以下です
- SvelteKit(TailwindCSS付きでバージョンは2、Svelteのバージョンは5になります)
-
svelte-maplibre-gl(MIERUNE内で@ciscornさんが中心となって構築しているもの、
そのうち記事が出ると思います出ました) - DuckDB-Wasm
主な構成やDuckDB-Wasmへの接続などは以下のサンプルのものをそのまま持ってきたり、改変したりして利用しました
サンプルは2年前のものですので、結構前からあったのだなと気付かされます
エラー内容を見たかったので、importを duckdb-eh.wasm
に変更しています
import * as duckdb from '@duckdb/duckdb-wasm';
import duckdb_wasm from '/node_modules/@duckdb/duckdb-wasm/dist/duckdb-eh.wasm?url';
import duckdb_worker from '/node_modules/@duckdb/duckdb-wasm/dist/duckdb-browser-eh.worker.js?worker';
SvelteKitで構築する上でのポイントはここでしょう
利用するページではSSRしないようにします
export const prerender = true;
export const ssr = false;
DuckDBのSQLは以下のリファレンスを読みながら実装しました
重心を取得するのは ST_Centroid
なのですが、組み立てたMULTIPOINTを送り込むようにしたのと、返り値がPOINT2Dのオブジェクトだったので、Javascriptで文字列として扱うためにGeoJSON形式へ変換していますので、ややこしいSQL文になっています
このあたりは方法を間違っているかもしれないので知見のある方からご指摘があるかもしれません
SELECT ST_AsGeoJSON(ST_Centroid(ST_GeomFromText('${pointsMultiString}'))) as geom;
処理の順番としては
- GeoJSONからDuckDBの一時テーブルを作る
- 読み出してMULTIPOINTの文字列を作る
- ST_Centroidで重心を取得する
という感じです
サラッと書いていますが、結構複雑になっちゃったなあと思っています
メインの実装は以下を御覧ください(雑ですみません)
完成したもの
マルチポイント重心計算くん
※初回表示で地図がちゃんと表示されないバグが発生しております、その場合は何度かリロードしてみてください
ソースコード一式はこちら
改修の予定はあるのですが、マルチポイントのGeoJSONファイルのURLを入れるというところのハードルが高いと思います
G空間情報センターに置いてある国土数値情報あたりが良いかもしれません
ちなみに上記デモは北海道の学校のポイントデータで、 https://www.geospatial.jp/ckan/dataset/8a1f5eb3-dca4-4ba5-8d84-cf6a31a56bff/resource/1a6f4420-2f9a-4f7c-9043-52b7cca64df9/download/p29-13_01.geojson
です
また、以下の記事も参考になるかと思います
感想
なんといっても、WEBでかつクライアント側の実装だけで地理空間分析が出来るのというのが最高です
諸事情でバックエンドが組めない、若しくは組む余裕がない、みたいな場面で生きそうです
ハマりポイントとしては、やりとりしている今データがどんな状況か(テキストなのか、DBのオブジェクトなのか)みたいなところを強く意識しないといけなかったところですね、気をつけましょう
ちなみに、SSRの構成でデプロイしているのに一切SSR使っていないところが微妙だなと思っています、wasmなのでそうなるよなあとは思いつつ
そして、実際計測したわけでは無いのですが、やっぱり速いなと感じました
Turf.jsを使ったほうがもっと便利なものを作れそうだなと思いましたが、大量のポイントの処理はちょっと怖いかも
今後
現状、データをURL指定でしか読み込めないので、手元のGeoJSONを読み込めるように大改修の予定でおります
ここではサラッとしか触れなかったDuckDBの事や、svelte-maplibre-glの事は、他のアドベントカレンダーの記事として出す予定です
特にsvelte-maplibre-glが便利すぎてやばかったですね、おかげでDuckDBとのやりとりの構築に集中できました、神ライブラリーです
構築の上で参考にさせていただいた記事達
これらの記事が無かったら、確実に間に合わなかったでしょう
ありがとうございます
明日は@nkmr_RLさんによる「pyqgisでQGISの標準機能を呼び出す」です!お楽しみにー