国道走破ゲームを作るために、国道の位置データが欲しい

# まえがき
qiita含めた、技術ブログ的なものは初投稿です。なにか問題点あれば教えてください。よろしく
# 動機
- 国道を走破するゲームを作りたい
    - たぶんまだないし、ニッチな需要がありそう(自分も欲しい)
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3855515/cc5def2f-909c-faf2-4de4-0de5f35cca68.png "google検索のサジェストに国道 制覇 アプリ が！")
    - youtubeやブログなどのコンテンツとしては存在し、結構人気ある
    - この世界には、確実に国道マニアが存在している
- どうやって作るか
    - 位置情報からどの道を走っているかを判定することはできる
        - 例：[Roads API](https://developers.google.com/maps/documentation/roads?hl=ja)
    - 国道の走破率を計算する必要がある
    - 各国道の位置情報(点の集合)を用意しておいて、現在地と照らし合わせることで走破率を計算できそう
        - ここで問題になるのが、**どうやって国道の位置データを取得するか**
    - 具体的な実装b(今回の記事には関係なし)
        - 準備
            - 各国道の位置情報を配列としてサーバーに保存しておく
                - 国道１号[始点, ..., 終点]
                - 国道２号[始点, ..., 終点]
                ...
        - 走破率の判定
            1. 現在地を定期的に取得する
            1. 現在地に最も近い国道を求める
            1. 最も近い国道の位置情報配列の中から、最も近い点を探す
            1. 最も近い点との距離が一定値以下ならその点をチェックする
            1. 各国道におけるチェック率を計算する
            - 逐一このプロセスを繰り返すのは微妙なので、バッチ処理したほうがいいかも

# ChatGPTにきいてみた
>日本の主要な国道の位置情報を取得するためには、国道ごとの経路を示す緯度・経度データのリストが必要です。以下の手順で進めることができます。
>
>1. オープンデータの利用:
    国土交通省や地理院地図のウェブサイトでは、国道の位置情報が公開されている可能性があります。オープンデータとして提供されているデータセットをダウンロードし、解析することができます。
>1. Google Maps API などの利用:
    Google Maps API を使用して、国道ごとの経路情報を取得できます。国道番号を指定してリクエストを行い、経路を取得し、位置情報を配列として保存することができます。
>1. OpenStreetMap (OSM) データの利用:
    >OSM では道路データがオープンな形で提供されています。OSM の API や Overpass API を利用して、特定の国道の経路データをクエリして取得することが可能です。

# ちょっと調べた
- オープンデータ
    - [国土交通省のデータ](https://nlftp.mlit.go.jp/ksj/gmlold/datalist/gmlold_KsjTmplt-N01.html)
        - 平成７年度は古すぎる
        - 都道府県別になっていて使いにくい
- Google Maps API
    - ちょっと調べた感じ指定した道路を取得するクエリは用意されてなさそう
    - 使いすぎるとお金がかかる
- OpenStreetMap(以下OSM)
    - 完全無料！
    - Overpass APIでOSMの各種データにアクセスできる
        - 指定した道路のベクターデータも取得できるらしい！
    - これや！

# Overpass APIを使ってみる ~失敗~
- [Overpass APIのススメ - Qiita](https://qiita.com/K-Sakanoshita/items/0c610d76bba2e7245ea5)
- [overpass turbo](https://overpass-turbo.eu/#)
    - 好きなOverpass APIクエリを投げて、結果を地図上に表示してくれる優れもの
    - 返ってきたjsonデータも見れる
- [Overpass QL](https://wiki.openstreetmap.org/wiki/JA:Overpass_API/Overpass_QL)というクエリ言語が独特の形式で難しく、ChatGPTにクエリを生成させた
    ```:gptが生成した国道１号を取得するクエリ
    [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 は地上の物理的な地物（例えば道路や建物）を、基本的なデータ構造（ノード、ウェイ、リレーション）にタグを付与して表現します。各タグで特定のノード、ウェイ、リレーションで表された地物の地理的な属性を記述します。

- [Map Features](https://wiki.openstreetmap.org/wiki/JA:Map_Features)
### OSMにおける地理情報のデータ構造
- `Node`
    - 地図の基本要素である、緯度経度の座標を持つ単一の点
    - 例
        - 標識の位置
        - 公衆トイレの位置
- `Way`
    - 複数の`Node`を順に結んだもの
    - 始点$\neq$終点なら、道路や川のような線状？線形？のデータ
    - 始点$=$終点なら、建物の輪郭や、領域を示すポリゴンデータ
- `Relation`
    - 複数の`Node`や `Way`、また`Relation`自体も組み合わせて、より複雑な地物データを表す
    - 例
        - バスのルート
        - 鉄道路線
        - 大学などの建物群
- `Tag`
    - 前述した基本データに対する地理的な属性をタグとして付与
    - `key=value`の形
        - 例
            - `highway=residential`: 住宅街の道路
            - `amenity=school`: 学校
            - `natural=tree`: 木
    - 日本における道路のタグ
        - [ここ](https://wiki.openstreetmap.org/wiki/Japan_tagging#Highway)によると、**国道を表すタグは、`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"が大量に続く
}
```
- overpass turboによる地図上の表示
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3855515/e854c93a-22f0-2847-6926-db887fa976c0.png "overpass turboによる地図上の表示")
- 実際の国道８号
![Japan_National_Route_8_Map.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3855515/61e56a85-421e-1c98-3fa9-3404dff0cf26.png)
Phiror - 投稿者自身による著作物, CC 表示-継承 4.0, https://commons.wikimedia.org/w/index.php?curid=40131703による

- だいだいうまくいっているが、他の国道との重複区間が取得できていない
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3855515/c398a6ea-b34e-cb72-5d03-149e34e2ada0.png "重複区間")

### なぜgptの生成したクエリではうまくいかなかったか
- `area`タグで検索範囲を指定する際、`"name"="Japan"`のように英語で指定するとうまくいかず、`"name"="日本"`や、`"name"="石川県"`など日本語を使うとうまくいった
    - 参考：[バスマップ用のデータをopenstreetmapから取り込む手順メモ - Qiita](https://qiita.com/kotodu/items/9d5e1c473bab2cf4bbd9)
# 結果と課題
重複していない国道は取得することができたが、重複区間を取得できなかった。そのため該当区間がどのようなタグを持っているか調べてクエリを改良する必要がある。