Swift MkMapViewで地図アプリ作成してみた（12）- ロングタップした位置と現在位置の標高差をピンに表示する

#記事一覧
[Swift MkMapViewで地図アプリ作成してみた（記事一覧）](https://qiita.com/rain_00_00_09/items/3151b3faf2303fe78312)

#国土地理院から現在位置の標高を取得する

国土地理院のWebAPIから標高を取得する方法の詳細は、「[ロングタップした位置の標高を国土地理院から取得する](https://qiita.com/rain_00_00_09/items/df32926d6755972cb421)」を参照してください。

1. URLを生成する

    国土地理院から現在位置の標高をJSONで取得するためのURLを作成する。

    ```swift:ViewController.swift：URLを生成する
    // 国土地理院のURL
    let baseUrl = "https://cyberjapandata2.gsi.go.jp/general/dem/scripts/getelevation.php?"
    // 現在位置でクエリを設定する
    let lonUrl = "&lon=" + mapView.userLocation.coordinate.longitude.description
    let latUrl = "&lat=" + mapView.userLocation.coordinate.latitude.description
    // アウトプット形式をJSONに設定する
    let outtypeUrl = "&outtype=JSON"
    // URLとクエリを連結
    let listUrl = baseUrl + lonUrl + latUrl + outtypeUrl        
    // URLを生成する
    guard let url = URL(string: listUrl) else { return }
    ```

    [現在位置を取得する](https://qiita.com/rain_00_00_09/items/18496f0f9aa1e89350e0)で現在位置受信を有効にしていれば、mapView.userLocationに現在位置が自動で設定されている。

2. 標高を取得する

    URLSessionで生成したURLにアクセスして標高を取得する。

    ```swift:ViewController.swift：標高を取得する
   
    // URLを生成する
    guard let url = URL(string: listUrl) else { return }
    URLSession.shared.dataTask(with: url) { (data, response, error) in
        if error != nil {
            print(error!.localizedDescription)
        }
        guard let data = data else { return }
        // JSONを取得する
        let json = try? JSONDecoder().decode(JsonElevation.self, from: data)
        if nil != json {
            // mainスレッドで処理する
            DispatchQueue.main.async {
                // JSONから標高を取得する
                self.currentElevation = (json?.elevation)!
            }
        }.resume()
    }
    ```

    サブスレッドからメインスレッドに切り替えるためには、DispatchQueue.main.asyncを使用する。


#ロングタップした位置と現在位置の標高差をピンに表示する

1. 標高差を計算する

    [ロングタップした位置の標高を国土地理院から取得する](https://qiita.com/rain_00_00_09/items/df32926d6755972cb421)で取得した標高との差を


    ```swift:ViewController.swift：標高差を計算する
    self.lblDiffElevation = "高低差：" + (round(((self.longTapElevation - self.currentElevation)*10))/10).description + " m"
    // ロングタップしたアノテーション情報を更新する
    updateLongTapPointAno()
    ```

    少数第1桁となる様に、"*10))/10"としている。


2. 標高差をピンに表示する

    [ロングタップした位置にピンを立て距離を表示する](https://qiita.com/rain_00_00_09/items/d426a32ab8356a97fc78)で設定したピンのタイトルに連結する。

    ```swift:ViewController.swift：標高差をピンに表示する
    // ロングタップしたアノテーション情報を更新する
    func updateLongTapPointAno() {
        // 現在位置とタッウプした位置の距離(m)を算出する
        let distance = calcDistance(mapView.userLocation.coordinate, pointAno.coordinate)
            
        // ピンに設定する文字列を生成する
        var str:String = Int(distance).description
        str = str + " m"
            
        // yard
        let yardStr = Int(distance * 1.09361)
        str = str + " / " + yardStr.description + " y"
            
        // 標高差を連結する
        str = str + "\n" + lblDiffElevation.description
            
        if pointAno.title != str {
            // ピンまでの距離に変化があればtitleを更新する
            pointAno.title = str
            mapView.addAnnotation(pointAno)
        }
    }
    ```

    シミュレータの実行結果は以下の様になる。

<img width="802" alt="Qiita(12)-01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/362635/62da16eb-7a89-4872-eba0-b2df20c5047f.png">


#参考文書
[国土地理院　ヘルプ](http://maps.gsi.go.jp/help/index.html)