Vincenty's Formulae

modified on Aug 4th, 2023


はじめに

過去に仕事で必要になったので、大圏航路(大圏コース)にかかる計算法などを調べ、ソフトウェアとして実装した。
それまでは、理論すら知らなかった。

ここでは自身の経験に基づき、計算法の紹介と、コンピュータプログラムとして実装する際に、 どういったことに気をつけるべきかの私見を残したいと思う。
ネットの時代なので、もっとより良い知見は他にもあるはずなので、ここに書かれたことを鵜呑みにしないでもらいたい。

当然、ここに書かれたことに基づき読者に何らかの損害が発生したとしても、一切の責は負わない。

なお、出てくる Vincety's Formulae とは何かや使われる用語などは、必要に応じてウィキペディア などでより詳しい情報を得られたし。 ただし、2014年9月時点では、Vincenty's Formulaeは日本語版のウィキペディアには存在していない。英語版の Wikipediaを参照されたし。
(2023年6月時点では、日本語版のウィキペディアにも載っていますね。)

大圏航路とは

地球表面上の2地点を結ぶ地球表面をなぞる最短コースのことである。
地球表面をなぞる3次元的には曲線(実は円弧に近い)もので、地中に潜り込んで2地点を結ぶ直線ではないことに注意されたし。

地球のモデル

地球は、半径約6370キロメートル、外周(大円)約40,000キロメートルのほぼ球体をしているが、真球(perfect sphere)ではない。
赤道付近が膨らみ、北極と南極を上下からちょっと押し潰したような形をしている。 (楕円形を短径を軸に三次元空間で回転させたときに描かれる形、即ち回転楕円体(spheroid)に近い。) 特に、「地球楕円体(Earth ellipsoid)」という用語が存在する。

実際の地球には、山あり谷あり、重力場の揺らぎあり、などなどの要因からもろもろの凹凸があるわけであるが、 ここで紹介している大圏航路の計算ではそれらは無視しており、完全なる回転楕円体にモデル化した上での話である。

以下、地球のモデルをいくつか挙げておく。

モデル名 長半径(a)
メートル
扁平率(f)
(長半径-短半径)/長半径
概要
(近似球) 6,366,707.019 0 1国際海里(正確に1852メートル)を緯度1分(min.)分としたときの球体である。
半径≒1国際海里×60分×360度÷(2×円周率)
航路計算は球面三角法を使用して単純になるが、誤差が大きいという欠点がある。
ベッセル 6,377,397.155 1 / 299.152813 2002年3月まで日本の測地系として使用されていた。
GRS80 6,378,137 1 / 298.257222101 2002年4月から日本の測地系として使用されている。
WGS84 6,378,137 1 / 298.257223563 GPSで採用されている。海洋での測量に使用する。
GRS80との差は実用上ほとんどない。

Vincenty's Formulae

何を解くのか? というと次の2つの問題を解くものである。

地球が完全な球体であれば、球面三角法という解法が存在するのであるが、あいにく地球は完全な球体ではなく回転楕円体(地球楕円体)である。
回転楕円体においては、球面三角法と計算量が同等の解法は存在しない。

Vincentyの計算法の特徴は次にあげられる。

ただし、inverse問題の計算において、地球のほぼ裏側同士に位置する2地点を与えたときには、反復を繰り返しても解が収束しないという欠点がある。

計算には計算誤差対策を打とう

(計算機は無限の桁の数値を扱うことはできない。そのため、計算機とプログラムでの実装では必ず計算誤差が生じる。
どのような計算誤差を考察し、プログラミングではどういった工夫をすべきか、について語りたい。)

double型変数の特徴を理解しておこう

(コンピュータのプログラミングで、実数を扱うときに整数型変数ではなくて、float型(単精度浮動小数点数)やdouble型(倍精度浮動小数点数)を使う。
この型はどのようにコンピュータの中で表現されているのか、それ故にどのような特徴を持つのか、さらにその特徴を理解すると、 プログラミング上で考慮すべき点は何なのかについて語りたい。
だって、「実数を入れる器は、floatかdoubleなんだよ。以上。」では、なんだか寂しいじゃん。それに、思ったようにプログラムは動いてくれないかもよ。)

コンピュータの中では、二進数が使われる。これは、ディジタル回路の究極の最小単位は、二値(電圧がかかっている状態とかかっていない状態)であることに基づく。
二値の一桁で表すことのできる情報の区別は、当然二個であり、この単位をビット(bit)という。
2ビット使うと4個の状態を区別でき、3ビット使うと8個の状態、...8ビット使うと156個の状態を区別して扱うことができる。

正の整数は、必要なビット数の領域に二進数で格納する。1ビットは、0か1の値しか持てず、それを1桁として上位の桁に繰り上げていく。だから二進数なのだ。

同様に、小数も二進数での表現になる。(1/2)の桁、(1/4)の桁、(1/8)の桁、・・・の値を持つかどうかで表現することになる。
例えば、十進小数で 0.1 や 0.9 という値は、(十進で)
0.1(10) = (1/2) x 0 + (1/4) x 0 + (1/8) x 0 + (1/16) x 1 + (1/32) x 1 + (1/64) x 0 + ・・・
0.9(10) = (1/2) x 1 + (1/4) x 1 + (1/8) x 1 + (1/16) x 0 + (1/32) x 0 + (1/64) x1 + ・・・
となるので、二進小数では、
0.1(10) = 0.000110・・・(2)
0.9(10) = 0.111001・・・(2)
といった感じで、有限桁では正確には保持することはできず、近似値を持つことになる。
より詳しくは、「IEEE754-2008」などを参照されたし。

さらに徐々につづく。。。

三角関数 atan2() とは

(現代のコンピュータの世界では、三角関数(sin, cos, tan...)は、ライブラリとして用意されている。
同様に逆関数(逆三角関数)も用意されているのだが、asin(アークサイン)、acos(アークコサイン)、atan(アークタンジェント)の他に、 atan2というアークタンジェントなんだけどatanとはちょっと違うモノもある。
atan2()がどういった局面で有効な関数であるのかを考察してみたい。)

C++/Javaによるサンプルプログラム

(プログラミング言語C++を使って、かつC++風(オブジェクト指向風)に、サンプルプログラムを書いてみたい。
過去に書いたのは会社の資産であり、おいらの資産ではないので、ここに載せることは出来ない。それ以前に会社から持ち出すことも出来ない。 自身のプログラミング技術を錆びつかせないためにも、一から書いてみようと思う。)

2023/6/12 C++言語ではなくて、Java言語での実装例を公開する。
ちなみに、計算ロジックのサンプルコードは2023年時点でネット上のいたるところに存在している。また、はやりのchatGPTだって、コードを書き出してくれる。 計算結果を取得するだけのサイトもたくさんある。国土地理院のサイトでも計算させることができる。
それなのに、ここで公開しようと思うに至った、としあきが重点を置いたものとは・・・

ファイルたちはパックしたファイルにて提供するので、ダウンロードして解凍してご利用ください。 なお、JavaですのでJavaの実行環境のインストールは別途必要だ。
ご自身で一部書き替えてお試しするためには実行環境だけではなく開発環境(JDK)のインストールが必要だ。(どちらもOracleのページから無料で入手できる) パックされているファイルの概要は以下となっている。 (ソースコードの解読やクラス構成を決めるときに考察したことなどを含めて、解読の一助に。)

一部中途半端と思える箇所もあるだろう。それらを含めて、「僕(私)だったら、ここはこう書くかな」「こういった拡張性を考えたら、この部分はこうしておくほうが良いかな」 などを考えるきっかけになり、そして、そう考えることが読者の技術向上になることは間違いないことと思う。

🔝