Help us understand the problem. What is going on with this article?

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

記事一覧

Swift MkMapViewで地図アプリ作成してみた(記事一覧)

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

国土地理院のWebAPIから標高を取得する方法の詳細は、「ロングタップした位置の標高を国土地理院から取得する」を参照してください。

  1. URLを生成する

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

    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 }
    

    現在位置を取得するで現在位置受信を有効にしていれば、mapView.userLocationに現在位置が自動で設定されている。

  2. 標高を取得する

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

    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. 標高差を計算する

    ロングタップした位置の標高を国土地理院から取得するで取得した標高との差を

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

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

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

    ロングタップした位置にピンを立て距離を表示するで設定したピンのタイトルに連結する。

    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)
        }
    }
    

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

Qiita(12)-01.png

参考文書

国土地理院 ヘルプ

yuta-sasaki
車載ソフトウェア開発者です。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした