プログラマーのメモ書き

伊勢在住のプログラマーが気になることを気ままにメモったブログです

OverpassAPI の QL でいろいろと試してみました (2/2)

Overpass API でいろいろ試した続きです(基本的な部分は前の記事をご参考にしてください)。

OpenStreeMap の要素としては node, way, relation の3つらしいんですが、 OverpassAPI では area という要素があります。個人的には、この area というものの実態がつかめず、苦労しました。

ということで、この記事では area について思ったことをまとめておきます。

area について

まず、 area というのは、 OpenStreetmap の要素では『ない』というのが大前提としてあります。じゃあ、areaってどうやって決めてるの?

となりますが、こちらの説明にあるように、一定の条件を満たす範囲をエリアとして定義しているとのことです。で、これは、 Overpass API サーバー上でバッチジョブのように動作して、 area を生成しているとのことです。

誤解をおそれずにまとめると、 area というのは、下記のような条件のどれかを満たす way または relation に対して作成される、というもののようです。

  • relation : タグ admin_level の指定あり かつ タグ name の指定あり
  • relation : タグ type が multipolygon かつ タグ name の指定あり
  • relation : タグ postal_code の指定あり
  • relation : タグ addr:postcode の指定あり
  • way : タグ area が yes かつ タグ name の指定あり

それぞれのタグの意味を調べるとこんな感じかと思います。

  • admin_level というタグは自治体などの境界を表現する際に使われているようです。国や県、市町村などで異なるレベルを表現しているようです。
  • multipolygon はそのまま理解すると多角形なんですが、ここでは、内部に穴が開いているような領域を表現する際に使うもののようです。単なる多角形なら閉じた way (始点と終点が同じ node である way )でも表現できますからね。
  • postal_code と addr:postcode は同じ郵便番号を持つ地域を意味しているんだろうと思います。
  • タグ area は何らかの領域を表しているようです。

area 要素を導入した目的は、ある一定の領域を簡便に取り扱うために導入されたんですよね、きっと。自治体の境界とか、複雑な領域を扱うには、こういうものがあるほうが便利ですよね、そりゃ。チュートリアルの area のページに詳しく書かれていますので一読するといいかと思います。

また、こちらの説明だと area 要素のタグは、元になった relation や way のタグをそのまま使っているとあります。

概要がわかったところで、 area をあれこれ触ってみます。

参考

area についてはなかなか理解できなくて、下記などの説明も参考にしました。

個人的には map_to_area の説明を読んだときに、 way または relation に対応して area 要素が作られている、というのをはっきりと認識できて、理解が進みました。

area クエリ

area がどんなものかつかめたら、早速 Overpass API で扱ってみます。まずは、 area を指定して、それを対象にデータを取得してみます。

エリア『伊勢市』に含まれる node を返します(データ量が多いので、実行時にはご注意ください)。

area["name" = "伊勢市"];
node(area);
out;

area クエリは area["name" = "伊勢市"] の部分になります。条件に該当する area を返してきます。

でも、実は、上記の結果は area クエリだけではなく、 area フィルタも通した両方の結果になっています。なので、 area フィルタについてもいろいろと試します。

area フィルタについて

上記の例で node(area) の部分が、 area フィルタで、 area クエリで取得した area を対象に、その area に含まれる node を返すというものになります。

node(area) だけだと、デフォルトの入力集合(デフォルトセット)に含まれる area が対象になるとのことです。 node(area.a) のような表記だと、 a という入力集合に含まれる area が対象になるようです。

他の例も見てみます。

エリア『伊勢市』に含まれる、 way を返します(データ量が多いので、実行時にはご注意ください)。 なお、出力形式として out だけだと、 way を構成する node の緯度経度情報が出力されず描画できないので、 geom を付けています。

area["name" = "伊勢市"];
way(area);
out geom;

Wiki のエリアによるフィルターの説明では

ノードの場合は、エリアの内部または境界線上にあるものが検索されます。ウェイの場合は、少なくとも 1 点 (線分上の点も可) がエリアの内部 (境界線を含まない) にあるものが検索されます。エリア境界線上に終端があるだけで、エリアと交わらないようなウェイは、検索されません。リレーションの場合は、そのメンバーのいずれかがエリア内部 (境界線上を含まない) にあるものが検索されます。

とあります。上記の例を見ても、このとおりに area 内に node を持つ way を選択している様子(伊勢市外に道路が伸びている様子)が見てとれますね。

ついでに rel でも試してみます。

area["name" = "伊勢市"];
rel(area);
out geom;

伊勢市にメンバーがあるものが選択されているっぽいですね。

ちなみに、 area クエリが無い状態で、 area フィルタを使うと

node(area);
out;

下記のように、取得したデータがない応答がかえってきてました。

<?xml version="1.0" encoding="UTF-8"?>
<osm version="0.6" generator="Overpass API 0.7.59 e21c39fe">
<note>The data included in this document is from www.openstreetmap.org. The data is made available under ODbL.</note>
<meta osm_base="2022-12-14T10:04:24Z" areas="2022-12-14T07:49:33Z"/>


</osm>

pivot フィルタ

area クエリで取得した area の輪郭が欲しいときは pivot フィルタというのを使うといいみたいです。

area["name" = "伊勢市"];
rel(pivot);
out geom;

area の元になったリレーションの情報を得ることができるようです。

ちなみに、

area["name" = "伊勢市"];
node(pivot);
out geom;

でも同じ結果を得ることができました。

Wiki の説明だと pivot は way と rel に使うとあるんですが、 node に使ってもエラーにはならずにうまいことやってくれてるようです(が、予期せぬ結果になるかもしれないので避けたほうがいいんでしょうね)。

area クエリで何が返ってくるのか?

最初に示した例は、 area クエリで選択した結果が、デフォルトセットに含まれて、その area に対して、 area フィルタを適用して、 node を表示させたものでした。

じゃあ、 area クエリだけなら、何が返ってくるのかが気になります。

area["name" = "伊勢市"];
out;

とすると、Overpass turbo では表示されない(表示できない)ので、画面上部の選択ボタンで『データ』を選び、データとして表示させて、area クエリで返ってくるものを確認します。

上記の場合は、

<?xml version="1.0" encoding="UTF-8"?>
<osm version="0.6" generator="Overpass API 0.7.59 e21c39fe">
<note>The data included in this document is from www.openstreetmap.org. The data is made available under ODbL.</note>
<meta osm_base="2022-12-14T10:18:22Z" areas="2022-12-14T07:49:33Z"/>

  <area id="3604538518">
    <tag k="addr:country" v="JP"/>
    <tag k="admin_level" v="7"/>
    <tag k="boundary" v="administrative"/>
    <tag k="is_in:continent" v="Asia"/>
    <tag k="is_in:country" v="Japan"/>
    <tag k="is_in:country_code" v="JP"/>
    <tag k="is_in:iso_3166_2" v="JP-24"/>
    <tag k="is_in:prefecture" v="三重県"/>
    <tag k="is_in:province" v="Mie Prefecture"/>
    <tag k="name" v="伊勢市"/>
    <tag k="name:ar" v="إيسه"/>
    <tag k="name:en" v="Ise"/>
    <tag k="name:fa" v="ایسه، میه"/>
    <tag k="name:ja" v="伊勢市"/>
    <tag k="name:ja_kana" v="いせし"/>
    <tag k="name:ja_rm" v="Ise-Shi"/>
    <tag k="name:ko" v="이세시"/>
    <tag k="name:ru" v="Исе"/>
    <tag k="name:tg" v="Исе"/>
    <tag k="name:uk" v="Ісе"/>
    <tag k="name:zh" v="伊勢市"/>
    <tag k="name:zh-Hans" v="伊势市"/>
    <tag k="name:zh-Hant" v="伊勢市"/>
    <tag k="population" v="127071"/>
    <tag k="postal_code" v="516-0037"/>
    <tag k="source" v="KSJ2/N03"/>
    <tag k="source:population" v="http://www.pref.mie.lg.jp/DATABOX/23355003425.htm"/>
    <tag k="type" v="boundary"/>
    <tag k="website" v="https://www.city.ise.mie.jp/"/>
    <tag k="wikidata" v="Q328067"/>
    <tag k="wikipedia:ja" v="伊勢市"/>
  </area>

</osm>

のような、 area タグとそれに関する情報が返ってきました。これだけだと、緯度経度の情報を含んでいないので、表示できないのもその通りですね。

area の ID について

上記の area ID を確認すると 36xxxxxxxx と 36 で始まっています。こちらの説明によると、これは area の元になったリレーションのIDに対して、 3600000000 を付加したものとのことです。なので、

rel(id:0004538518);
out geom;

とすると、先ほどと同じ境界線を表示することができます。

area クエリ(つづき)

クエリは、完全一致だけでなく正規表現も使えます。そこで、 area クエリで正規表現を使ってみます。

area["name" ~ "伊勢市"];
out;

結果は

<?xml version="1.0" encoding="UTF-8"?>
<osm version="0.6" generator="Overpass API 0.7.59 e21c39fe">
<note>The data included in this document is from www.openstreetmap.org. The data is made available under ODbL.</note>
<meta osm_base="2022-12-14T10:30:39Z" areas="2022-12-14T07:49:33Z"/>

  <way id="182504191">
    <nd ref="1928645808"/>
    <nd ref="1928645781"/>
    <nd ref="1928645782"/>
    <nd ref="1928645778"/>
    <nd ref="1928645779"/>
    <nd ref="1928645809"/>
    <nd ref="1928645808"/>
    <tag k="building" v="train_station"/>
    <tag k="name" v="伊勢市駅"/>
(中略)
  </way>
  <area id="3604538518">
    <tag k="addr:country" v="JP"/>
    <tag k="admin_level" v="7"/>
(中略)
  </area>

</osm>

のようになってました。今度は、 area タグのほかに way も出力されています。

どうも、Wiki の説明などでは、 area クエリは area を返すとありますが、条件に一致した閉じた way も返しているようです。

is_in クエリ

指定された緯度経度を含むエリアおよび閉じた way を返すとのことです(リンク先の日本語ページには『閉じた way』の表記がありませんが、英語版のページを見ると書かれてます)。

引数として、伊勢市駅付近の緯度経度を指定してみます。

is_in(34.4909706, 136.7097211);
out meta geom;

駅近辺の way が表示されています。

でも、『データ表示』で確認すると、 area として

  • 日本
  • 本州
  • 近畿地方
  • 三重県
  • 伊勢市
  • 東海道
  • 伊勢国

という名前を持つ area が返ってきているのがわかります。

is_in は入力集合を指定することもでき、その場合は入力集合のノードを含むエリアおよび閉じた way を返すようです。

まとめ

Overpass API の機能のうち、 area をいろいろと触ってみました。

最初は area がどんなものかつかめずに戸惑いましたが、 OpenStreetMap では、 way や relation を使って一定の領域(エリア)を工夫して表現しているものを、 area タグという表現を導入することで、便利に扱おうとしていることがよくわかりました。地域を絞り込んで検討したい時などには便利に使えそうです。

にしても、日本語の情報がもっと欲しいものです。