まえがき
qiita含めた、技術ブログ的なものは初投稿です。なにか問題点あれば教えてください。よろしく
動機
- 国道を走破するゲームを作りたい
- どうやって作るか
- 位置情報からどの道を走っているかを判定することはできる
- 国道の走破率を計算する必要がある
- 各国道の位置情報(点の集合)を用意しておいて、現在地と照らし合わせることで走破率を計算できそう
- ここで問題になるのが、どうやって国道の位置データを取得するか
- 具体的な実装b(今回の記事には関係なし)
- 準備
- 各国道の位置情報を配列としてサーバーに保存しておく
- 国道1号[始点, ..., 終点]
- 国道2号[始点, ..., 終点]
...
- 各国道の位置情報を配列としてサーバーに保存しておく
- 走破率の判定
- 現在地を定期的に取得する
- 現在地に最も近い国道を求める
- 最も近い国道の位置情報配列の中から、最も近い点を探す
- 最も近い点との距離が一定値以下ならその点をチェックする
- 各国道におけるチェック率を計算する
- 逐一このプロセスを繰り返すのは微妙なので、バッチ処理したほうがいいかも
- 準備
ChatGPTにきいてみた
日本の主要な国道の位置情報を取得するためには、国道ごとの経路を示す緯度・経度データのリストが必要です。以下の手順で進めることができます。
- オープンデータの利用:
国土交通省や地理院地図のウェブサイトでは、国道の位置情報が公開されている可能性があります。オープンデータとして提供されているデータセットをダウンロードし、解析することができます。- Google Maps API などの利用:
Google Maps API を使用して、国道ごとの経路情報を取得できます。国道番号を指定してリクエストを行い、経路を取得し、位置情報を配列として保存することができます。- OpenStreetMap (OSM) データの利用:
>OSM では道路データがオープンな形で提供されています。OSM の API や Overpass API を利用して、特定の国道の経路データをクエリして取得することが可能です。
ちょっと調べた
- オープンデータ
-
国土交通省のデータ
- 平成7年度は古すぎる
- 都道府県別になっていて使いにくい
-
国土交通省のデータ
- Google Maps API
- ちょっと調べた感じ指定した道路を取得するクエリは用意されてなさそう
- 使いすぎるとお金がかかる
- OpenStreetMap(以下OSM)
- 完全無料!
- Overpass APIでOSMの各種データにアクセスできる
- 指定した道路のベクターデータも取得できるらしい!
- これや!
Overpass APIを使ってみる ~失敗~
- Overpass APIのススメ - Qiita
-
overpass turbo
- 好きなOverpass APIクエリを投げて、結果を地図上に表示してくれる優れもの
- 返ってきたjsonデータも見れる
-
Overpass QLというクエリ言語が独特の形式で難しく、ChatGPTにクエリを生成させた
gptが生成した国道1号を取得するクエリ
[out:json]; area["name"="Japan"]->.japan; ( way["highway"="primary"]["ref"="1"](area.japan); ); out body; >; out skel qt;
レスポンス{ "version": 0.6, "generator": "Overpass API 0.7.62.1 084b4234", "osm3s": { "timestamp_osm_base": "2024-08-07T06:52:30Z", "timestamp_areas_base": "2024-08-07T03:37:45Z", "copyright": "The data included in this document is from www.openstreetmap.org. The data is made available under ODbL." }, "elements": [ ] }
- 全然うまくいってない
- 本来は
elements
のところにデータがいろいろ入っているんだろうなあ
ちゃんと調べる
OSMについて
- これだけで別の記事になってしまうのでなるべく簡潔に
- そもそも、OSMとは様々な地理情報を自由に追加できる、その名の通りオープンな地図サービスである
OpenStreetMap は地上の物理的な地物(例えば道路や建物)を、基本的なデータ構造(ノード、ウェイ、リレーション)にタグを付与して表現します。各タグで特定のノード、ウェイ、リレーションで表された地物の地理的な属性を記述します。
OSMにおける地理情報のデータ構造
-
Node
- 地図の基本要素である、緯度経度の座標を持つ単一の点
- 例
- 標識の位置
- 公衆トイレの位置
-
Way
- 複数の
Node
を順に結んだもの - 始点$\neq$終点なら、道路や川のような線状?線形?のデータ
- 始点$=$終点なら、建物の輪郭や、領域を示すポリゴンデータ
- 複数の
-
Relation
- 複数の
Node
やWay
、またRelation
自体も組み合わせて、より複雑な地物データを表す - 例
- バスのルート
- 鉄道路線
- 大学などの建物群
- 複数の
-
Tag
- 前述した基本データに対する地理的な属性をタグとして付与
-
key=value
の形- 例
-
highway=residential
: 住宅街の道路 -
amenity=school
: 学校 -
natural=tree
: 木
-
- 例
- 日本における道路のタグ
-
ここによると、国道を表すタグは、
highway=trunk
で、その中でもref=number
によって任意の番号の国道を指定できる!
-
ここによると、国道を表すタグは、
Overpass APIを使ってみる ~成功?~
国道8号線を取得するクエリ
[out:json];
area["name"="日本"]->.searchArea;
(
way["highway"="trunk"]["ref"="8"](area.searchArea);
);
out body;
>;
out skel qt;
レスポンス
{
"version": 0.6,
"generator": "Overpass API 0.7.62.1 084b4234",
"osm3s": {
"timestamp_osm_base": "2024-08-07T08:25:00Z",
"timestamp_areas_base": "2024-08-07T03:37:45Z",
"copyright": "The data included in this document is from www.openstreetmap.org. The data is made available under ODbL."
},
"elements": [
{
"type": "way",
"id": 23634545,
"nodes": [
256034652,
529442479,
256034651,
529442478,
529442477,
256034648,
529442476,
256034647,
529442475,
529442474,
279674072,
531646732,
256034646,
529442463,
256034645,
529442460,
529442459,
256034644,
529442461,
256034643
],
"tags": {
"highway": "trunk",
"lanes": "2",
"layer": "1",
"name": "国道8号",
"name:en": "National Highway Route 8",
"name:ja": "国道8号",
"ref": "8",
"source": "YahooJapan/ALPSMAP;GSImaps/std",
"surface": "paved"
}
},
//以下"way"が大量に続く
}
-
実際の国道8号
Phiror - 投稿者自身による著作物, CC 表示-継承 4.0, https://commons.wikimedia.org/w/index.php?curid=40131703による
なぜgptの生成したクエリではうまくいかなかったか
-
area
タグで検索範囲を指定する際、"name"="Japan"
のように英語で指定するとうまくいかず、"name"="日本"
や、"name"="石川県"
など日本語を使うとうまくいった
結果と課題
重複していない国道は取得することができたが、重複区間を取得できなかった。そのため該当区間がどのようなタグを持っているか調べてクエリを改良する必要がある。