0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

オフライン用の行政区/統計区の逆ジオコーディング用SDK

0
Posted at

{FDE247BC-178B-4685-92EA-D66EFB9636CC}.png

緯度経度から、その地点が属する市区町村や統計小地域などを取得する「Galuchat GIS SDK」を作成しました。

外部APIを使わず、手元のデータセットで逆ジオコーディングを行います。JavaScript、Java、Python、C++に対応し、ブラウザやローカルアプリケーション、組み込み機器で利用できます。

この記事では、開発の背景とデモ・SDKの使い方を紹介します。方式やファイル形式の詳細は、プロジェクトの概略ページとSDKのドキュメントを参照してください。

既存の方法と、ローカルで使う際の課題

日本の行政区域レベルの逆ジオコーディングをローカルで行う場合、国土地理院が公開する位置参照情報や、国土数値情報(行政区域データ)、逆ジオコーディングAPIを使用する方法がありますが、これらをそのままローカル環境で使う場合、いくつかの技術的な課題があります。

通信環境と外部サービスへの依存

外部APIは通信環境やサービスの利用条件に依存するため、オフラインでは使用できない。またはキャッシュデータ量の予測ができない。

ポリゴンの計算量とデータサイズ

区域ポリゴンを使えばその座標が属する区域を判定可能だが、広範囲の詳細なポリゴンを低計算資源の機器で扱うには、データサイズと検索負荷もあり、データサイズも大きい。

代表点と実際の区域の不一致

区域を代表点で表せばデータを削減可能であるが、最も近い代表点の区域と座標が実際に属する区域は一致しない。特に入り組んだ境界や細長い区域では、形状を十分に反映できない。

Galuchatの提案する解決方法

Galuchatでは、区域ポリゴンを高解像度のラスタに変換し、部分参照できる形で圧縮します。グリッド単位で区域形状を保持しながら、データサイズと検索時のメモリ使用量を抑えます。

ポリゴン判定を領域IDの読出しに置き換える

各画素に領域IDを記録し、検索時には次の処理を行います。

  1. 緯度経度からグリッド位置を求める
  2. 圧縮データから領域IDを読み出す
  3. 辞書から対応する地名を取得する

代表点までの距離ではなく面情報を使うため、解像度の範囲で複雑な区域形状を反映できます。

領域のまとまりを利用して圧縮する

ラスタを再帰構造に分割しつつ、分割区域内の画像の規則性を利用して面積に比例しない方式でデータを圧縮します。例として、日本全国の行政区域の地図データは、0.001度間隔(約110m間隔)で478.8 KiB、0.0001度間隔(約11m間隔)で4.47 MiBです。

圧縮は領域IDを保持しますが、ラスタ化で境界がグリッド単位に丸められます。境界付近やグリッドより小さな区域では、ポリゴンによる判定と異なる場合があります。

※領域IDと地名の変換辞書は別途使用します。

地図全体を展開せずに読み出す

圧縮データを順に走査し、不要な部分を読み飛ばしながら対象位置の領域IDを復元します。地図全体を展開せず、ファイルやROMから小さな作業メモリで検索します。

応用例

Galuchatの機能を体験できる2つのウェブアプリケーションと一つの組込例を公開しています。どちらも、ダウンロードしたデータを使い、逆ジオコーディングや地図の再構成をブラウザ内で実行します。

逆ジオコーディング

image.png

データセットを選び、緯度経度を入力すると、その地点が属する区域の地名を取得できます。複数地点の検索や、結果のJSON・CSV出力にも対応しています。

逆ジオコーディングを試す

地図表示

image.png
領域IDのラスタデータから地図を再構成し、区域の形状を表示します。地図の移動・拡大縮小に加え、クリックした地点の地名を確認できます。このウェブページはWebMCPからも使用可能です。

地図表示を試す

どちらもGaluchatのランディングページから利用できます。

SDKとして使う

コードとデータセットは、以下のリポジトリで公開しています。

SDKは主に、領域IDの地図データである WGSMapSet、地名辞書である GisWordBook、それらを読み出すライブラリで構成しています。同じデータセットをJavaScript、Java、Python、C++で利用できます。

パッケージマネージャによるインストールを前提とせず、必要な読出しコードとデータファイルを配置して使う形です。

Pythonで動かす例

Python 3.11以降で、SDKに同梱した日本の行政区域データを検索できます。

git clone https://github.com/nyatla/galuchat-gis-sdk.git
cd galuchat-gis-sdk

PYTHONPATH=python/src python3 \
  python/getstarted/reverse_geocode_imperial_palace.py \
  datasets/jp-admin-n03-2026/N03-20260101-grid-4096-1000.wgsmapset.glc \
  datasets/jp-admin-n03-2026/N03-20260101.giswordbook

サンプルは皇居、東京駅、新宿駅付近を検索します。出力の一部は次のようになります。

Tokyo Station: lon=139.7671, lat=35.6812
  code: 672
  path: 東京都 / 千代田区

Shinjuku Station: lon=139.7006, lat=35.6896
  code: 688
  path: 東京都 / 新宿区

ここで表示される code はデータセット内部の領域IDです。自治体コードなどの原典の識別子と同じものとは限りません。

各言語の導入手順と最小コードは、リポジトリのGet Startedにまとめています。

日本以外の区域データへの展開

当初は日本の行政区域のみを対象としていましたが、読出し方式を共通化し、各国の行政区や統計区のデータにも展開しました。

公開しているデータセットは38か国・地域、計45件です。地図データと地名辞書を対応するものに変更することで、同じ読出しコードを利用できます。

ただし、収録している区域の単位はデータセットごとに異なります。市区町村相当のものもあれば、統計小地域などを収録したものもあります。細かいグリッドのデータを選んでも、収録している区域の単位自体が細かくなるわけではありません。

各データセットの収録内容、解像度、ファイルサイズ、描画例、ダウンロード先は、SDKのデータセットガイドにまとめています。

ソフトウェアと文書は、特に記載がない限りApache License 2.0です。データセットにはそれぞれの原典に基づく利用条件が適用されるため、利用するデータのガイドと、配布ZIP内の NOTICE.md を確認してください。

AIに実装を依頼する場合

コーディングAIに組み込みを依頼する場合は、リポジトリと対象言語のGet Startedを参照させると、使用するコードとデータファイルを指定できます。

例えば、Pythonなら次のような依頼です。

https://github.com/nyatla/galuchat-gis-sdk を使用して、
経度・緯度から、その地点が属する日本の行政区域名を取得する
Pythonプログラムを作成してください。

README.ja.md と python/getstarted/README.md を参照し、
同梱の jp-admin-n03-2026 データセットを使用してください。

検索は外部APIを使わず、ローカルのデータを参照して行ってください。
座標の引数順は経度、緯度です。
未設定領域では、地名が得られなかったことを返してください。

まず同梱サンプルを実行し、東京駅付近の座標
(経度139.7671、緯度35.6812)から
「東京都 / 千代田区」が得られることを確認してください。

データセットのNOTICE.mdも確認し、必要な出典表示を残してください。

AIに実装を任せた場合も、使用したデータセット、座標の順序、未設定領域での結果は確認してください。

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?