以前に少し試した OverpassAPI ですが、ちょっとやってみたいことができたので、改めて OpenStreetMap からのデータの取り出し方を復習してみました。
とその前に。
Overpass API のチュートリアルを見つけたので、まずは下記を試してみるのもおすすめです。
このチュートリアルも含めて、いろいろとやってみて、気になった点をまとめておきます。
クエリと結果セット
Overpass API のクエリって、結果をある集合に書き込みます。
[bbox: 34.46326, 136.66065, 34.56397, 136.80004]; node["name"]; out;
この場合は、デフォルトの結果集合に書き込んでいます。結果集合に名前を付けて、明示的に操作することもできます。
[bbox: 34.46326, 136.66065, 34.56397, 136.80004]; node["name"] -> .ise; .ise out;
デフォルトの結果集合を明示的に操作したい場合は、アンダースコア(_)で表現します。
[bbox: 34.46326, 136.66065, 34.56397, 136.80004]; node["name"] -> ._; ._ out;
最初の例と同じことになります。
複数のクエリ
Overpass API では複数のクエリを書くこともできます。 で、クエリ毎に結果集合を切り替えることができるので、あとから、個別に処理することもできます。
[bbox: 34.46326, 136.66065, 34.56397, 136.80004]; node["name" = "伊勢市役所"] -> .ise; node["name" ~ "伊勢支店"] -> .s; ( .ise; .s; ); out;
丸かっこは、前の Overpass API の記事でやった、和集合をつくるやつです。 伊勢市役所が1点と金融機関の支店が2点見つかっています。
出力先が、同じ結果セットであれば、2つ目のクエリが入力集合を取らない場合は、前の結果が上書きされます。
[bbox: 34.46326, 136.66065, 34.56397, 136.80004]; node["name" ~ "伊勢支店"] -> .s; node["natural"] -> .s; .s out;
こんな感じで、 natural タグが定義されている結果に上書きされています。ということは、これをデフォルトの結果セットで試すと、2つ目のクエリの結果だけが得られることになります。
以前の記事で、絞り込みを試したときに、ちょっと感じた違和感がこれで明らかになりました。つまり、2つ目のクエリが、結果集合を上書きしていたため、絞り込みになっていなかったということですね。
複数の out ステートメント
上記では、複数のクエリを書くことができるとしましたが、もっというと、クエリだけではなく複数のステートメントを書くことができます。
ということで、 out ステートメントを複数を複数使うこともできます。
[bbox: 34.46326, 136.66065, 34.56397, 136.80004]; node["name" = "伊勢市役所"]; out; node["name" ~ "伊勢支店"]; out;
画面上で『データ』を選択すると、一つの XML にまとまっているので、結果を一つにまとめるのは、 Overpass API でよしなにやってくれてるんでしょうね(apiを直接呼び出しても同じく1つのXMLが返ってきてました)。
way について
Overpass turbo でwayだけを表示するには
way({{bbox}})["highway"]; out geom;
または
way({{bbox}})["highway"]; (._;>;); out skel;
のようにします。さきほどまでの伊勢市全体だとデータ量が多すぎるため、表示していた画面の範囲に限定しました(緯度経度の範囲だと、南、西、北、東の並びで 34.48677, 136.7046, 34.49306, 136.71331 でした)。
両者の違いは、戻ってきたデータの形式の違いです。 前者は、
<?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-19T07:32:05Z"/> <way id="23429311"> <bounds minlat="34.4904910" minlon="136.7079073" maxlat="34.4914138" maxlon="136.7087511"/> <nd ref="1303266857" lat="34.4904910" lon="136.7079073"/> (中略) <way id="50049599"> <bounds minlat="34.4660951" minlon="136.7062005" maxlat="34.4880673" maxlon="136.7215013"/> <nd ref="253746243" lat="34.4660951" lon="136.7215013"/> <nd ref="1815327956" lat="34.4661111" lon="136.7212954"/> (中略) <tag k="source" v="Bing 2007;GSImaps/std"/> <tag k="surface" v="paved"/> </way> (後略)
のように、wayの要素内にnd要素があり、これに緯度経度の情報が付加されています。
一方、後者の場合は、
<?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-19T07:27:07Z"/> <node id="253746243" lat="34.4660951" lon="136.7215013"/> <node id="253746281" lat="34.4771808" lon="136.7095462"/> (中略) <way id="50049599"> <nd ref="253746243"/> <nd ref="1815327956"/> (中略) </way> (後略)
のように、 way 要素内にある nd 要素には node 要素のIDのみが記されており、対応するid属性を持つnode要素に緯度経度が記されています。
node もまとめて表示されるケース
ちなみに、
way({{bbox}})["highway"]; out;
とすると、
のような警告が表示されます。これは、通常 out (out body) だと、way を構成する node の情報として id は含まれますが、その node の緯度経度がないため、描画できないためです。
なので、『クエリの修復』を行うと
way({{bbox}})["highway"]; /*added by auto repair*/ (._;>;); /*end of auto repair*/ out;
のようになります。もちろん、これでもよいのですが、この場合、node によっては交差点や信号なども表示されることがあります。
再帰
さきほどの例は、こうも書けます。
way({{bbox}})["highway"]; //(._;>;); (._;node(w);); out;
node(w) は入力集合の way に対する node を返すというフィルタ)だそうです。
さきほどの > (再帰下降クエリ))との違いは、再帰下降クエリの場合は、入力集合にリレーションがある場合、そのリレーションのメンバーである way や node も出力する、ということのようです。
なので、上記の例では同じ結果になりましたが、入力集合によっては異なる結果になりそうです。
ちなみに、再帰下降クエリと >> (再帰下降リレーションクエリ))の違いは、リレーションのメンバーにリレーションが含まれた場合に、さらにそのリレーションのメンバーも含めるかどうか、ということのようです。
再帰フィルタや再帰クエリはいろいろなバリエーションがあるようなので、詳しくはマニュアルをご覧ください。
まとめ
いろいろと試していくと、だんだんとやり方が見えてきました。
ですが、上記の基本的な部分のほかに、頭を悩ませたものに、 area があります。長くなるので、そちらはまた別の記事にまとめたいと思います。