現在地から写真の撮影場所までのルートを表示する

<h1>概要

写真のExif情報から位置情報を取得できることを知ったので
その応用ということで、現在地から取得した位置情報へのルートをDirections APIで取得してみようと思いました。
ついでに、Exif情報から逆ジオコーディングを行って地理情報を同時に表示させます。
素人にも扱えるなんて、Googleさんは素晴らしいですなぁ。。

Exif情報については[wiki](https://ja.wikipedia.org/wiki/Exchangeable_image_file_format)を参照してください。
以下、引用文。
>カメラの機種や撮影時の条件情報を画像に埋め込んでいて、ビューワやフォトレタッチソフトなどで参照、応用することができる。

[逆ジオコーディング](https://business.mapfan.com/blog/detail/628)については以下を参照してください。
以下、引用文。
>経度緯度から住所を取得する方法を「リバースジオコーディング」や「逆ジオコーディング」と言います。


<h2>完成系

ただローカルで動かす程度なので、フロントには全くこだわっていません。
簡単に説明しますと、以下の処理を組んでいます。

①ホームディレクトリ``/``から写真を``/upload``にアップロード(POST)
②flaskのルーティングメソッドで写真のオブジェクトを取得
③写真のExif情報からgps情報(緯度・経度)を取得
④取得した緯度・経度から逆ジオコーディングによって地理情報を取得
⑤gps情報・地理情報を地図表示ページに渡す
⑥地図表示ページでgooglemapを展開し、現在地と写真の撮影地とをルートマップとして表示する。またマップの上部に写真の地理情報を箇条書きで表示する。

スクショで表すとこうなります。(位置情報や地図情報は念のため隠しました。(;^ω^))
![home.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558257/da7b36a2-1422-2fe6-8bf1-ff7ddf6a2cd2.png)![upload.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558257/15637449-5240-98a3-280a-44e3f341b885.png)
``A...現在地　B...目的地``です。


<h3>工夫したこと・勉強になったこと

<b>①地図の中心位置は、両者の中間地点にした！

google maps apiに渡すパラメータのうち、center(いわゆる地図の中心位置となるgps情報)を渡す必要があるが、単に現在地と写真の位置を足して2で割った値を中心にすると綺麗に地図が表示されるようになった。

```javascript:Route.js
function successRoute(position) {

    var latitude  = position.coords.latitude;//緯度
    var longitude = position.coords.longitude;//経度
    // 位置情報(現在地)
    var latlng_local = new google.maps.LatLng( latitude , longitude ) ;
    // 位置情報(写真)
    var latlng_photo = new google.maps.LatLng( photo_data[0] , photo_data[1] ) ;

    // mapの中心
    center_lat = (latitude + photo_data[0]) / 2
    center_lng = (longitude + photo_data[1]) / 2
    const center = {lat: center_lat, lng: center_lng };
    const options = {zoom: 7, scaleControl: true, center: center};

```
<br>
<b>②Pyモジュールからjavascriptに変数を渡す工夫

[こちらの記事](https://admin-it.xyz/python/flask/flask-javascript-variable/)を参考にしました。
順序通り説明すると、以下の流れになります。

①app.pyモジュール側にて、渡したい変数(<b>今回はgps情報と地理情報</b>)をリストに格納する。(地理情報はString型で受け取るのでリストに入れ直す必要がある。)

②最終的に変数を渡したいRoute.jsを司っている、map.htmlファイルにリスト化した変数を渡す。

③map.htmlの``<script>``タグ内で、jinja2受け取った変数をjsonにエンコードしたものとして再定義する。

④再定義した``<script>``タグの下に``<script>``タグを用意し、Route.jsをソースとして定義する。

この流れを組むと、無事js内で変数が使えるようになりました。
以下に、コードの一部を掲載しておきます。

```python:app.py
# コードは一部を抜粋
input_data = []
photo_info = []
@app.route('/upload', methods=['POST'])
def upload():
    # Exifからgps情報を取得する(image_pathはアップロードした写真のパス)
    # exif_gps.pyのget_gps関数による処理で緯度経度を取得
    photo_lat, photo_lng = exif_gps.get_gps(image_path)
    # gps情報をリストに格納
    input_data = [photo_lat, photo_lng]
    # 逆ジオコーディング処理で地理情報を取得する
    photo_info_tmp = exif_gps.revgeo(photo_lat, photo_lng)
    # photo_info_tmpはカンマを含む文字列(String)なので
    # photo_info_tmpに含まれた文字数分インクリメントしながら
    # カンマ以外の文字列をリストに格納する(ココ重要)
    num = 0
    note = ""
    for i in photo_info_tmp:
        if i != ',':
            note += i
            continue
        else:
            photo_info.insert(num, note)
            num += 1
            note = ""
    # map.htmlに変数を渡す
    return render_template('map.html', data=input_data, info=photo_info)
```

```html:map.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>位置情報取得サンプル</title>
<script async defer src="https://maps.googleapis.com/maps/api/js?key=XXX:bow:X"></script>
<script type="text/javascript">
// 変数を渡す
var photo_data= {{ data | tojson }}
var map;
</script>
<script src="{{ url_for('static', filename='js/Route.js') }}"></script>
</head>
```


<h2>参考にさせて頂いたサイト:bow:

◆google maps 導入手順
http://toa.in.net/googlemap/

◆参考書籍
https://www.socym.co.jp/book/1251

◆Exifから緯度経度の取得に対するエラー
https://stackoverflow.com/questions/64405326/django-exif-data-ifdrational-object-is-not-subscriptable

◆Directions Service 導入手順
http://www.googleappsscript.info/2018-03-21/map_route_guidance.html

◆Exifの取得
https://geocoder.readthedocs.io/providers/OpenStreetMap.html