プログラマーのメモ書き

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

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

以前に少し試した OverpassAPI ですが、ちょっとやってみたいことができたので、改めて OpenStreetMap からのデータの取り出し方を復習してみました。

とその前に。

Overpass API のチュートリアルを見つけたので、まずは下記を試してみるのもおすすめです。

Overpass Tutorial

このチュートリアルも含めて、いろいろとやってみて、気になった点をまとめておきます。

クエリと結果セット

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 があります。長くなるので、そちらはまた別の記事にまとめたいと思います。