LeafletでCSISのジオコーダを使う

この記事は1年以上前に書かれました。
内容が古くなっている可能性がありますのでご注意下さい。


Leafletライブラリを使って開発したWeb地図に住所検索の機能を追加するために、ジオコーディングのプラグインが各種用意されています。これらのプラグインは、ユーザーが入力した住所をジオコーダと呼ばれるサーバーに渡して緯度経度を受け取ります。
プラグインによって対応するジオコーダが異なります。また、ジオコーダによって性能が異なり、高性能なジオコーダは利用登録が必要だったり費用がかかったりします。
比較的高性能でありながら無料で使えるジオコーダのひとつに、東京大学空間情報科学研究センターの「CSISシンプルジオコーディング実験」がありますが、残念なことに、対応しているLeafletプラグインがありませんでした。
そこで、 OpenStreetMapNominatim ジオコーダに対応した Leaflet Control Geocoder プラグインとCSISのジオコーダを橋渡しするプロキシサーバを作成しました。

動作原理を図で表すと以下のようになります。

Nominatim の形式で渡されたパラメータをCSISのジオコーダ用に変換して渡し、返された XML を JSON に変換して呼び出し元に返すというだけの簡単なものです。

ソースコードはGitHubで公開しているので、そちらを参照して下さい。ここにPHPのコードを記述すると、WAFにブロックされて投稿できなくなってしまうのです。

プログラムの前半では、パラメータが 35.658099, 139.741357 という形式の緯度経度だった場合の処理をしています。この場合はジオコーダの呼び出しをせず、この緯度経度を含む連想配列を作成します。後半ではCSISのジオコーダを呼び出し、返されたXMLを解析して連想配列を組み立てます。

  // $item['address']['country'] = '日本';
  $item['address']['country'] = str_replace('/', ' ', $cand->address );

となっている箇所では、本来ならば国名をセットするべき所に、〇〇県 □□市 △△町のようなデータをセットしています。Leaflet Control Geocoderプラグインでは、ジオコーダから複数の住所が返された場合に、こうした方がリストの表示が分かりやすくなるためです。別のプラグインを使用する場合は、本来の値をセットした方が良いかもしれません。
最後に、連想配列をJSONに変換して返します。

このプログラムはPHPで書かれているので、通常なら

https://server/search.php?q=住所

という形式で呼び出すことになります。しかし、Leaflet Control Geocoderプラグインでは、server の部分はオプションで指定できますが、プログラム名は拡張子の付かない search で変えることができません。そこで、.htaccessに以下の記述をし、拡張子なしでPHPプログラムを呼び出せるようにします。

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.*)$ $1.php

Web地図のプログラムでLeaflet Control Geocoderプラグインを初期化する際は、geocoder オプションで L.Control.Geocoder.Nominatim を指定し、その serviceUrl オプションで GeocoderProxy を設置したサーバーを指定します。

L.Control.geocoder({
    geocoder: new L.Control.Geocoder.Nominatim({
      serviceUrl: /* URL of the service */
    }),

月待ビンゴ攻略マップでは、Leaflet Control Geocoderプラグインと GeocoderProxy を実際に使用しており、動作を確認することができます。