8
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

MIERUNEAdvent Calendar 2024

Day 7

DuckDB-Wasmで簡単な地理空間情報分析アプリを作る

Last updated at Posted at 2024-12-07

はじめに

実は前からgeojsonの重心座標を一発で取れるツールが欲しいなと思っており、今まではQGISを使っていたのですが、自身の技術向上も兼ね、DuckDB-Wasmにて構築を行いました

結論から言いますと、完璧なものが出来たとは言い難いのですが、かなり勉強になりましたので紹介します

DuckDB-Wasmとは

Webブラウザ上で動作するDuckDBのWebAssembly版で、主なポイントとしては

  1. Webブラウザ上でSQLクエリを実行できる
  2. サーバー側の処理は不要で、クライアントサイドのみでデータベース操作が可能
  3. クエリ処理をブラウザのメモリ内で完結し、ローカルデータ分析に最適
  4. 標準SQLクエリをサポートし、CSVやParquet形式のデータを扱える
  5. ネットワーク接続がなくても動作するため、オフラインでのデータ分析が可能

というようなものになります

DuckDBにはSpatial Extensionという地理空間データを処理するための拡張機能があり、これがほぼPostGISと同じことが出来る
というのが今回学ぼうと思ったきっかけになります

やったこと

簡単なWEBアプリケーションを作りました
主な利用ライブラリーは以下です

  • SvelteKit(TailwindCSS付きでバージョンは2、Svelteのバージョンは5になります)
  • svelte-maplibre-gl(MIERUNE内で@ciscornさんが中心となって構築しているもの、そのうち記事出ると思います出ました)
  • DuckDB-Wasm

主な構成やDuckDB-Wasmへの接続などは以下のサンプルのものをそのまま持ってきたり、改変したりして利用しました
サンプルは2年前のものですので、結構前からあったのだなと気付かされます

エラー内容を見たかったので、importを duckdb-eh.wasm に変更しています

lib/duckdb.ts
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しないようにします

routes/page.ts
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;

処理の順番としては

  1. GeoJSONからDuckDBの一時テーブルを作る
  2. 読み出してMULTIPOINTの文字列を作る
  3. ST_Centroidで重心を取得する

という感じです
サラッと書いていますが、結構複雑になっちゃったなあと思っています

メインの実装は以下を御覧ください(雑ですみません)

完成したもの

マルチポイント重心計算くん
※初回表示で地図がちゃんと表示されないバグが発生しております、その場合は何度かリロードしてみてください

Kapture 2024-12-07 at 08.48.11.gif

ソースコード一式はこちら

改修の予定はあるのですが、マルチポイントの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の標準機能を呼び出す」です!お楽しみにー

8
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?