地球上の2地点間の距離を取得するアルゴリズム(ヒュベニ or 球面三角法)比較【JavaScript】

2018-05-06
html5javascript%E3%82%A2%E3%83%AB%E3%82%B4%E3%83%AA%E3%82%BA%E3%83%A0GeoLocationAPI
    

目次

概要

以前、地球上の2地点間の距離を計算する実装を行なった際に「ヒュベニの公式」と「球面三角法」を比較したことがあります。 ここでは改めて2つのアルゴリズムを実装して比較してみようと思います。

ヒュベニの公式

http://hp.vector.co.jp/authors/VA002244/yacht/geo.htm

ヒュベニの式を用いた、緯度・経度と距離・方位の相互変換の解説

球面三角法

https://ja.wikipedia.org/wiki/%E7%90%83%E9%9D%A2%E4%B8%89%E8%A7%92%E6%B3%95

球面三角法 基本的な三角関数を組み合わせたものです。 球面三角法はヒュベニと比べ計算結果は荒くなります。

ソース

下記のソースでは「ヒュベニの公式」 と 「球面三角法」 を比較しています。

//
// ヒュベニの公式
//
function hubeny(lat1, lng1, lat2, lng2) {
    function rad(deg) {
        return deg * Math.PI / 180;
    }
    //degree to radian
    lat1 = rad(lat1);
    lng1 = rad(lng1);
    lat2 = rad(lat2);
    lng2 = rad(lng2);

    // 緯度差
    var latDiff = lat1 - lat2;
    // 経度差算
    var lngDiff = lng1 - lng2;
    // 平均緯度
    var latAvg = (lat1 + lat2) / 2.0;
    // 赤道半径
    var a = 6378137.0;
    // 極半径
    var b = 6356752.314140356;
    // 第一離心率^2
    var e2 = 0.00669438002301188;
    // 赤道上の子午線曲率半径
    var a1e2 = 6335439.32708317;

    var sinLat = Math.sin(latAvg);
    var W2 = 1.0 - e2 * (sinLat * sinLat);

    // 子午線曲率半径M
    var M = a1e2 / (Math.sqrt(W2) * W2);
    // 卯酉線曲率半径
    var N = a / Math.sqrt(W2);

    t1 = M * latDiff;
    t2 = N * Math.cos(latAvg) * lngDiff;
    return Math.sqrt((t1 * t1) + (t2 * t2));
}

//
// 球面三角法
//
function sphericalTrigonometry(lat1, lng1, lat2, lng2) {
    // 赤道半径
    var R = 6378137.0;

    function rad(deg) {
        return deg * Math.PI / 180;
    }

    return R *
        Math.acos(
            Math.cos(rad(lat1)) *
            Math.cos(rad(lat2)) *
            Math.cos(rad(lng2) - rad(lng1)) +
            Math.sin(rad(lat1)) *
            Math.sin(rad(lat2))
        );
}

GeoLocationAPIとの組み合わせ

https://developer.mozilla.org/ja/docs/Web/API/Geolocation/Using_geolocation

GeoLocationAPIと組み合わせて現在地と任意の地点間の距離を計測します。

var getSuccess = function(pos) {

    //現在地の緯度経度
    var lat1 = pos.coords.latitude;
    var lng1 = pos.coords.longitude;

    //新宿都庁の座標
    var lat2 = 35.689487;
    var lng2 = 139.691706;

    //距離の計算//
    var ans1, ans2;
    try {
        ans1 = hubeny(lat1, lng1, lat2, lng2);
        ans2 = sphericalTrigonometry(lat1, lng1, lat2, lng2);
    } catch (e) {
        alert(e);
    }

    //結果
    document.getElementById("result1").innerHTML = ans1 + " m";
    document.getElementById("result2").innerHTML = ans2 + " m";
};

var geoError = function() {
    var pos = {
        'coords': {
            'latitude': 35.5562073,
            'longitude': 139.5723855
        }
    };
    getSuccess(pos);
    alert('Getting location failed.');
};

// GeoLocationAPIで現在地の座標を取得する
document.getElementById("start").onclick = function() {
    navigator.geolocation.getCurrentPosition(getSuccess, geoError, {
        enableHighAccuracy: true
    });
};

デモ(外部リンク)

結果

https://vldb.gsi.go.jp/sokuchi/surveycalc/main.html

国土地理院のサイトの計算結果と一緒に2つの実装を比較してみました。

※単位 : m

東京-川崎

東京(35.689487, 139.691706) 〜 川崎(35.5562073, 139.5723855)

球面三角法 : 18317.126210821592
ヒュベニ    : 18349.45459166647
地理院    : 18317.122

数メートルの誤差が生じる。

東京-名古屋

東京 〜 名古屋(35.2, 136.9)

球面三角法 : 259215.96201641572
ヒュベニ    : 258964.81739383226
地理院    : 259205.815

1km未満ではあるが誤差が生じた。

東京-ギニア湾

東京 〜 ギニア湾(0.0, 0.0)

球面三角法 : 15324766.692400709
ヒュベニ    : 14278853.174450254
地理院    : 14274245.589

まとめ

数キロ程度の距離の計算では、ヒュベニと球面三角法の差は小さいものとなりましたが、 実用するのであれば様々なソフトウェアで採用実績のあるヒュベニの公式を使うのが無難かもしれません。

また、今回のソースでは測地系の差を考慮していないので、用いる測地系によって計算結果が少し変わってくると思います。

参考

https://keisan.casio.jp/exec/system/1257670779

https://qiita.com/chiyoyo/items/b10bd3864f3ce5c56291

https://qiita.com/port-development/items/eea3a0a225be47db0fd4

    
s-yoshiki
s-yoshiki
githubtwitterqiita
Web作ってますが、インタラクティブなプログラミングも好きです。
JavaScript / Vue / node.js / PHP / AWS / OpenCV

関連記事

10進数から2進数 2進数から10進数への変換 JavaScript
10進数から2進数 2進数から10進数 テスト 10進数から2進数、2進数から10進数への変換を行うJavaScriptのコードの紹介。 JSの場合、10進数から2進数への変換はメソッド。2進数から1…

JavaScriptの配列ショートハンド (AtCoder用)

JavaScriptでワーシャルフロイド法を実装
AtCoder ABC012 D問題 D - バスと避けられない運命 解説 実装 AtCoder ABC012 の D問題でワーシャルフロイド法が利用できる問題が出てきたので、 JavaScriptで実装しました。 AtCoder ABC012 D問題 D…

JavaScriptによる2分探索(バイナリサーチ) のサンプルコード
2分探索について ソース 参考 JavaScriptで2分探索(バイナリサーチ)を実装してみました。…

Firebase + Nuxt で認証付きページを作るときに参考にしたいところ
Webアプリケーションのセッション管理にJWT導入を検討する際の考え方 Service Worker によるセッション管理 ユーザー セッションの管理 Nuxt.jsとFirebaseでSPA×SSR×PWA×サーバーレスを実現する CookieとセッションとJWT SSR…

JavaScriptで幅優先探索 (bfs) を実装する
bfsソースコード 前提 bfs関数 テストコード JavaScriptで幅優先探索 (bfs) を実装し簡単な最短経路の探索問題を解いてみました。 AtCoderの問題を参考にしています bfsソースコード 前提 bfs 関数の定義について 引数 table…

JavaScriptでbig-integerでできること
定数 メソッド abs add, plus and bitLength compare compareTo compareAmb divide, over divmod equals, eq greater, gt greaterOrEquals, geq…

ソースコードレビューのポイントをまとめる
ソースコードレビュー時のポイントを各所のブログから集めてまとめました。以下 https://gist.github.com/s-yoshiki/9e446d69cf388703a4711f7e69cba173

0埋め・ゼロ埋め処理 のコードJavaScript
サンプル コード 呼び出す 説明 参考 追記 JavaScriptで 0埋め / ゼロ埋め / zero埋め 処理を行うサンプルコード サンプル コード 呼び出す 説明 記事タイトルが…

順列・組み合わせ のサンプルコード JS [permutation] [combination]
順列 - permutation サンプルコード Usage 組み合わせ - combination サンプルコード Usage 順列(permutation) と 組み合わせ(combination) のサンプルコードをJavaScript…

最新の投稿

SQL整形ツールを作成した
特徴 使い方 FW/ライブラリ等 nuxt sql-formatter-plus Monaco Editor おまけ ソース SQL整形ツールを作成しました。 URLはこちらです。 SQL…

ファイルの1行目を表示 Linuxコマンド head
head コマンド例 headコマンドでファイルの 1行目もしくは指定した行数だけ表示する方法。 head 利用できるオプション コマンド例 の 1行目だけを表示 の 5行目までを表示 カレントディレクトリ以下の全てのtxtファイルの1行目を表示

Amazon S3 と ローカルファイルのチェックサムの比較
s3apiでEtagを取得 検証 マルチアップロード時の注意点 Amazon S3 の Etagを使ってファイルの整合性チェックをする。 s3apiでEtagを取得 S3 APIを利用するとEtagを取得します。この値はmd5のハッシュ値になります。 検証 MD…

github.io / gitlab.ioで公開されている質の高い技術ドキュメント
AWSによるクラウド入門 Pythonプログラミング入門 普通の人が資産運用で99点をとる方法とその考え方 2018年の段階で私が知らないこと github.io / gitlab.io で無料で公開されている興味深いドキュメントのmemo AWS…

10進数から2進数 2進数から10進数への変換 JavaScript
10進数から2進数 2進数から10進数 テスト 10進数から2進数、2進数から10進数への変換を行うJavaScriptのコードの紹介。 JSの場合、10進数から2進数への変換はメソッド。2進数から1…

JavaScriptの配列ショートハンド (AtCoder用)

JavaScriptでワーシャルフロイド法を実装
AtCoder ABC012 D問題 D - バスと避けられない運命 解説 実装 AtCoder ABC012 の D問題でワーシャルフロイド法が利用できる問題が出てきたので、 JavaScriptで実装しました。 AtCoder ABC012 D問題 D…

GitHub Actions で Gatsby をビルドし Amazon S3 にデプロイする
GitHub Actions について あらかじめ準備しておくもの AWS IAM ユーザを環境変数にセットする workflowの記述 ビルド バッジを利用する 終わりに 参考にしたところ Gatsbyで作った静的サイトを、GitHub Actions…

cloudinaryによる画像ファイルの管理 はじめてみる
目的 cloudinary について 他のサービスとの比較 料金プラン アカウントの登録 利用してみる ダッシュボード 画像の編集 APIベースでのアクセス 感想 参考 画像の管理や配信、さらには加工といった事ができるsaas型のcloud…

JavaScriptによる2分探索(バイナリサーチ) のサンプルコード
2分探索について ソース 参考 JavaScriptで2分探索(バイナリサーチ)を実装してみました。…

Tags

Dates

© 2020   404 motivation not found