2地点の緯度経度から距離を求める(概念編の詳細)

前回の記事(my-hobby : 2地点の緯度経度から距離を求める(Google MAPS APIとの比較~結果報告編~))でgoogleMAPS APIの計算式の検証を行ないました。
その際に検証用として使用した図に対して、メンバーのもじゃもじゃさんから「なぜこの様な図が出来上がるのか?詳しく教えて欲しい」という話があったので、今回はmy-hobby : 2地点の緯度経度から距離を求める(Google MAPS APIとの比較~概念編~)で提案した図についてもう少し詳しく説明したいと思います。
またこの図を使って、ちょっとした実験もしてみたいと思います。

この記事を見て、図に興味を持った方は是非見ていってください。
図のサンプル

図1
図1

●初めに、この図で検証しようと思ったきっかけ
2地点の緯度経度の距離を数字で比較するよりかは、ビジュアル的な図で比較した方がぱっと見た感じ解りやすくて良いと思ったからです。

●この図を一言で言うと
A地点からB地点までの距離を点の集合体で表現した図です。
A、B地点の意味は、my-hobby : 2地点の緯度経度から距離を求める(Google MAPS APIとの比較~概念編~)を参考にしてください。

●詳細な説明
先ずこの図は、A地点を中心に上下左右が対称である事が分かります。
つまり、縦2等分、横2等分に4分割したいづれの部分も、同じ理論で描画されている事になるので、どこか1箇所を説明すれば、それが他の3箇所にも当てはまる事になります。
そこで、今回は右上のエリアに絞って説明を行ないます。
右上のみに絞った図を以下に示します。

図2
図2

この点について全てを説明するのは大変なので、更にいくつかポイントを絞って説明していきます。
1.B地点が東経0~180度、北緯90度(北極点)の場合の距離(図3参照)
この図は、地球という球面を平面に見立てて距離を求めようとしているのですが、平面の場合、単純に3平方の定理を使用して、2地点の長さを求めると、その距離は2点(A地点、B地点)を対角線で結んだ長さとなります。※青色の線
しかし(2地点の緯度経度)で紹介した計算式(ここでは「ろっきー方式」とさせて頂きます)を使用して解くと、必ずしも2点を対角線で結んだ長さにはなりません。※赤色の線
この1の例で言うと、ろっきー方式を使用して2地点の距離を求めると、B地点の経度は異なるのですが、実は北極点の1点をさしているので、全て同じ計算結果になります。

図3
図3

実際の計算結果は以下の通りです。

A地点 B地点
緯度 経度 緯度 経度 距離(Km)
0 0 90 0 9990
0 0 90 10 9990
0 0 90 20 9990
0 0 90 30 9990
0 0 90 40 9990
0 0 90 50 9990
0 0 90 60 9990
0 0 90 70 9990
0 0 90 80 9990
0 0 90 90 9990
0 0 90 100 9990
0 0 90 110 9990
0 0 90 120 9990
0 0 90 130 9990
0 0 90 140 9990
0 0 90 150 9990
0 0 90 160 9990
0 0 90 170 9990
0 0 90 180 9990

この計算結果を図に反映させると、A地点を中心とした半径(距離Km)の円を描く様な図が出来上がります。

2.B地点が東経180度、北緯0~90度の場合の距離(図4参照)
距離の長さを赤線で示していますが、1の円形と違って、楕円を描くような感じの図になっています。
北緯90度から0度に移動するにつ入れて、距離が長くなっている事になります。
1の場合はB地点がいづれも北極点を指していた為、距離が同じでしたが、今度は北極点から赤道に向かってB地点が配置されている為、距離が伸びていく結果になります。

図4
図4

実際の計算結果は以下の通りです。

A地点 B地点
緯度 経度 緯度 経度 距離(Km)
0 0 90 180 9990
0 0 80 180 9534
0 0 70 180 10347
0 0 60 180 12006
0 0 50 180 13991
0 0 40 180 15937
0 0 30 180 17621
0 0 20 180 18906
0 0 10 180 19708
0 0 0 180 19980

これでもいまいちイメージが付きづらいと思うので、ちょっと視点を変えて、地球を球体として見るとどの様になるか図にしてみました。(図5)

図5
図5

図4の青枠の線と、図5の青枠の線は同じ場所を指しています。
図4では分かりませんでしたが、図5の様に視点を変えてみると、A地点からの距離が伸びているのが分かると思います。

この様な計算結果を今回提案したような図に描くと、図1の様な図形が出来上がります。
これを踏まえると、基準となるA地点と、計測対象となるB地点の緯度経度が分かれば、地球上のどこの場所の地図でも描く事が出来るという事です。

では冒頭にも書きましたが、試しにこの図の概念を使って面白い実験をしてみたいと思います。
JR東京駅をA地点、東京都内の各地域をB地点として、それぞれの2地点の距離を使用して東京都の形を描いてみたいと思います。
B地点となる緯度経度情報については位置参照情報ダウンロードサービスより取得しました。

約5200箇所のB地点の緯度経度情報を元に、それぞれの距離計算して作成した図は以下の通りです。
ちなみに、ろっきー方式は精度が悪いので、より精度の良いGoogleMAPS APIと近い計算結果になった計算式で描画してみました。

図6
図6

うーん・・・何となく東京都っぽい形が浮かび上がりました。
※言われてみないと分かりませんが・・・
B地点の緯度経度情報が均等で無い為、山岳部などは点の数が少なくなっています。
逆に都心部はそれなりの形を成しています。
ちなみに、各市区町村別のB地点の数は以下の通りです。

都道府県名 市区町村名 緯度経度(B地点の数)
東京都< 神津島村 1
東京都 小笠原村 2
東京都 西多摩郡日の出町 2
東京都 新島村 2
東京都 八丈町 5
東京都 三宅村 6
東京都 福生市 20
東京都 西多摩郡瑞穂町 22
東京都 稲城市 23
東京都 国立市 27
東京都 狛江市 41
東京都 清瀬市 43
東京都 小金井市 45
東京都 武蔵野市 51
東京都 羽村市 51
東京都 荒川区 52
東京都 東村山市 53
東京都 あきる野市 53
東京都 三鷹市 62
東京都 武蔵村山市 63
東京都 小平市 65
東京都 大島町 68
東京都 文京区 68
東京都 国分寺市 70
東京都 東大和市 72
東京都 昭島市 75
東京都 立川市 79
東京都 東久留米市 80
東京都 渋谷区 80
東京都 豊島区 83
東京都 中野区 85
東京都 多摩市 87
東京都 目黒区 88
東京都 中央区 98
東京都 調布市 102
東京都 墨田区 104
東京都 台東区 108
東京都 日野市 109
東京都 北区 113
東京都 西東京市 114
東京都 千代田区 115
東京都 港区 117
東京都 品川区 130
東京都 板橋区 134
東京都 町田市 137
東京都 杉並区 139
東京都 青梅市 144
東京都 府中市 147
東京都 江東区 149
東京都 新宿区 152
東京都 葛飾区 155
東京都 江戸川区 196
東京都 八王子市 199
東京都 練馬区 202
東京都 大田区 216
東京都 足立区 267
東京都 世田谷区 277

何かこの図の考え方は他にも応用が利きそうですが、またアイデアが浮かんだら記事にしたいと思います。
いきなりこの記事を読んだ方!意味不明かと思いますので、興味があればバックナンバーを参考にして下さい。

2地点の緯度経度から距離を求める(Goole MAPS API ~距離の計算式編~)

my-hobby : 2地点の緯度経度から距離を求める(Google MAPS APIとの比較~結果報告編~)の結果で、Google Maps API リファレンス – Google Maps API – Google Code(google方式)の精度が、3平方の定理を使用した方式(ろっきー方式)よりも精度が良い事が分かりました。
そこでgoogle方式の計算式を調べていたところ、偶然、javascriptのコードを緯度経度から2点の距離を求める – masakiplusの日記で見つけました。

今回は、これをVB.netに変換し、2点間の距離を算出しました。
以下のプログラムです。
[vbnet]
Imports System.Math
Public Function Getdistance(ByVal longitudeFrom As Double, ByVal latitudeFrom As Double, ByVal longitudeTo As Double, ByVal latitudeTo As Double)As Double
Dim from_x As Double ‘A地点の経度(ラジアン)
Dim from_y As Double ‘A地点の緯度(ラジアン)
Dim to_x As Double ‘B地点の経度(ラジアン)
Dim to_y As Double ‘B地点の緯度(ラジアン)
Dim deg As Double
Dim distance As Double ‘2地点の距離

from_x = longitudeFrom* Math.PI / 180
from_y = latitudeFrom * Math.PI / 180
to_x = longitudeTo * Math.PI / 180
to_y = latitudeTo * Math.PI / 180

deg = Sin(from_y) * Sin(to_y) + Cos(from_y) * Cos(to_y) * Cos(to_x – from_x)
distance = 6378140 * (Atan(-deg / Sqrt(-deg * deg + 1)) + Math.PI / 2) / 1000 ‘2地点の距離(Km)
Return distance

End Function
[/vbnet]

このプログラムを使用して、計算を行った結果と、google方式の結果を比較したところ、以下の様な結果となりました。

図1-計算結果
図1-計算結果

※赤がgoogle方式、黒がインターネット上で見つけた計算式です。
google方式、インターネット上で見つけた方式の順に上書き描画しています。

なんと黒色の点しか存在しません。

詳細に調べる為、結果を数値レベルで比較したところ、最も誤差の大きいところでも0.013Km程度でした。(0.00008%の誤差)
また、上記のケースは東経0~180度、北緯0~90度の範囲ですが、念の為に世界全体で比較した場合も同様の結果となりました。(図2を参照)

図2-計算結果(世界全体)
図2-計算結果(世界全体)

プログラムで小数点以下を扱う以上、この程度の誤差は出てしまうので、ほぼこの計算式で間違いないと言えます。

なおGoogle MAPS APIの公式な情報として、この計算式が発表されているわけでは無いので、本当の計算式は不明ですが、非常によく似た結果になった事は事実です。
今回は計5回に分けて記事を書きましたが、その結果以下の結論を得る事が出来ました。

・三平方の定理を使用した2地点の距離の計算式(ろっきー方式)よりは、Google MAPS APIが提供している機能(google方式)の方が精度が良い。
・図1、図2の様なテストケースにおいて、Google MAPS APIが提供している2地点の距離を求める計算結果は、上記の計算式を使用して計算した結果と非常によく似ている。

前者は悔しいですが、ある意味予想通りの結果でした。
ただ後者の事実が得られた事は予想外の収穫でした。

この計算式があれば、インターネットが利用できない環境(Google MAPS APIが利用できない環境)でも、Google MAPS APIを利用した場合と同等の結果(2地点の距離)を求めることが出来るようになります。

ちなみに余談ですが、計算式のヒントとして紹介したサイトから、更にそのサイトが参考にしたサイト(Seis Pesos)は、googleマップを使った技術がすごいです。
上記の計算式も、元々はこのサイトで掲載されていた様です。(今は無かったです)
今後googleマップを使ったアプリを作る機会があったら参考にしたいと思います。(今回のもう一つの収穫でした)

2地点の緯度経度から距離を求める(Google MAPS APIとの比較~結果報告編~)

my-hobby : 2地点の緯度経度から距離を求める(Google MAPS APIとの比較~テスト結果GoogleAPI編~)で、3平方の定理を使用した方式(ここでは「ろっきー方式」とさせていただいてます)と、Google MAPS APIが提供している距離の算出(google方式)の結果の差を報告しました。
※ろっきー方式の計算式はバックナンバーを参照して下さい。

今回はいよいよどちらの精度がよいのかを検証してみたいと思います。
測量計算(距離と方位角の計算)より取得した結果を「正しい結果」として、それを画面上に描画した結果は以下の通りとなりました。

図1-3者の結果比較-
図1-3者の結果比較-

※青がろっきー方式、赤がgoogle方式、緑が正しい結果です。
※なお、上記のサイトで計算すると、緯度、もしくは経度0の時、正しい結果が得られなかったので、0度を0度0分0.001秒として計算しています。(多分バグだと思います)
※計算上、0度から0度0分0.001秒までの長さはわずか3cmである為、今回の計算結果には影響を与えない範囲と考えられます。

なお描画は、ろっきー方式、google方式、正しい結果の順に上書き描画しています。
「ろっきー方式」、「google方式」それぞれの計算結果が正しい場合は、緑の点に上書きされるので、上書きされなかった(残ってしまった)点が多いほど、精度が悪いという事になります。

上記の図1を見ると、赤の点(Google方式)がほとんど無く、青の点(ろっきー方式)が多い事が分かります。
その結果、ろっきー方式よりもgoogle方式の方が精度が高い事が判明しました。

ではgoogle方式はどの様な計算式で、距離を割り出しているのか?エンジニアの自分としては気になって仕方がありません。
やはり、3平方の定理を使用したろっきー方式より精度が良いという事であれば、地球を球体とみなして計算をしているに違いありません。
しかし、自分だけの力でこの計算式を割り出すのは到底無理なので、ダメもとでいろいろ検索してたら、ろっきー方式と違う計算式を見つけ出しました。

この計算式を使って、再度my-hobby : 2地点の緯度経度から距離を求める(Google MAPS APIとの比較~概念編~)で紹介した方法で描画して、google方式との差を比較したいと思います。
今回の目的は達成しましたが、番外編として比較結果を次回報告したいと思います。

2地点の緯度経度から距離を求める(Google MAPS APIとの比較~テスト結果GoogleAPI編~)

flashcast:フリーで働くITエンジニア集団のブログ: 2地点の緯度経度から距離を求める(Google MAPS APIとの比較~テスト結果自作計算編~)の続編です。
Google Maps API リファレンス – Google Maps API – Google Codeで紹介されている2地点の距離の結果を、flashcast:フリーで働くITエンジニア集団のブログ: 2地点の緯度経度から距離を求める(Google MAPS APIとの比較~概念編~)で紹介した方法で図形化すると、以下の様な図が出来上がりました。

図1-google方式の結果-
図1-google方式の結果-

・・・なんか、前回紹介した「ろっきー」方式と似ているような、でもちょっと違うような・・・
改めてろっきー方式と、google方式の違いを一つの図で表示させて、両者を見比べてみたいと思います。

図2-両者の比較結果-
図2-両者の比較結果-

青がろっきー方式、赤がgoogle方式で描画しています。
ろっきー方式、google方式の順に上書き描画していますので、赤い点しかない部分はろっきー方式とgoogle方式の計算結果が同じという事になります。

図2を見ると、緑で囲った部分の差が大きいようです。
そこで、緑で囲った部分を含む東経0~180度、北緯0~90度の範囲(図2のオレンジで囲った部分)だけをクローズアップして見てみたいと思います。
ただ、10度刻みだと間隔が大きすぎるので、5度刻みにして描画してみました。
クローズアップして描画した結果は以下の通りになりました。

図3-クローズアップ-
図3-クローズアップ-

図3を見ると、青で囲った箇所は結果がほぼ一致していますが、赤で囲った箇所はかなりの差が出ているようです。
とりあえず現時点で分かった事としては、以下の通りです。
・ろっきー方式とgoogle方式は計算結果に違いがある。
・計算結果の違いは、B地点の緯度経度によって、大きかったり小さかったりする。
※B地点とは、背景の黄色い罫線が交差している点を指しています。
この事から、ろっきー方式と、google方式とでは、計算式が異なると言う事が確実となりました。

では今回のシリーズの本題である「ろっきー方式とgoogle方式とではどちらが精度が良いのか?」を検証してみたいと思います。
そこで、正しい結果を取得するべく、過去にも何度かお世話になっている測量計算(距離と方位角の計算)よりクローズアップ部分のみの結果を取得して、この図に描画してみる事にしました。
※このサイトで得られた結果を正解として、ろっきー方式と、google方式を比較してみたいと思います。

描画してみた結果は、次回報告したいと思います。

●バックナンバー
第1回:flashcast:フリーで働くITエンジニア集団のブログ: 2地点の緯度経度から距離を求める(Google MAPS APIとの比較~概念編~)
第2回:flashcast:フリーで働くITエンジニア集団のブログ: 2地点の緯度経度から距離を求める(Google MAPS APIとの比較~テスト結果自作計算編~)

2地点の緯度経度から距離を求める(Google MAPS APIとの比較~テスト結果自作計算編~)

my-hobby : 2地点の緯度経度から距離を求める(Google MAPS APIとの比較~概念編~)の続編です。
googleAPIが提供している距離計算「google方式」と、3平方の定理を使用した距離計算(ここでは「ろっきー方式」とさせていただきます)の精度の差を比較すべく、先ずはろっきー方式のテスト結果を報告します。

早速計算結果を描画してみたところ、以下の様な図が出来上がりました。

図1-ろっきー方式の結果-
図1-ろっきー方式の結果-

・・・う~ん。。。一見おかしな図形ですが、とりあえずこれはこれで良しとします。
ちなみにこの図形は、google方式との比較をする為のもので、この図形自体には何の意味もありませんのでご注意下さい。。。

では次にいよいよ「google方式」の検証です。
同じ3平方の定理(ろっきー方式)を使用していれば、同じ様な図形を描くはずですが、この方式は誤差が大きい為、別の方法を採用している可能性があります。

「google方式」はどの様な図形を描くのでしょうか?
ちなみに、googleの2地点の距離を求める方法については、もじゃもじゃさんの記事flashcast:フリーで働くITエンジニア集団のブログ: iPhone OS 3.0のSafariでGPS機能を使ったWeb Applicationを作る!(iPhoneでテスト編)を参考にしました。

結果は次回報告したいと思います。

2地点の緯度経度から距離を求める(Google MAPS APIとの比較~概念編~)

my-hobby : 2地点の緯度経度から距離を求める(global化 2/2)でglobal化が完了して一段落しましたが、メンバーのもじゃもじゃさんから、以下の様な話が出ました。
「GoogleMAPS APIにも、2地点の緯度経度から距離を求めるAPIがあるんだけど、ろっきーが紹介している方法とどちらの方が精度がいいのか知りたい」

googleの精度(以降「google方式」とします)に勝つつもりは無いですけど、ろっきーが紹介した方法(以降「ろっきー方式」とします)とどれだけ精度に差があるのか気になるところなので、せっかくだからこの疑問に対して自分なりの答えを出してみたいと思います。
ではどの様にして両者を比較すればよいのか?

比較と言うからには、やっぱり2地点のそれぞれの緯度経度から、「ろっきー方式」と、「google方式」を使用して、どの様な距離が算出されるかを比較すればよいという事になります。
ではテスト対象となる、2地点の緯度経度はどの様に決めるべきか?
ただ、単に1ケースだけでは、全体的な計算結果の差を把握する事は出来ません。
やはり全世界を網羅し、かつ簡単な(解り易い)テストケースであるのが、現時点では望ましいと言えます。

とりあえず最も単純な方法として、以下の様な方法を考えました。(1~4を順番に行なう)
1.東経0度、北緯0度の位置にポイントを打ち、これをA地点とします。
2.東経0~180度、西経0~180度、北緯0~90度、南緯0~90度の範囲(地球全体)で、それぞれ10度毎に線を引き、線が交差した部分にポイントを打ち、これをB地点とします。

図1-A地点とB地点の配置イメージ-
図1-A地点とB地点の配置イメージ-

※世界中にB地点として、703個のポイントが打たれます。
703=横(経度10度間隔)×縦(緯度10度間隔)=37×19=(360÷10+1)+(180÷10+1)=(360÷10+1(経度0度上のポイント))+(180÷10+1(緯度0度上のポイント))

3.A地点と、703箇所のB地点それぞれに対して、「ろっきー方式」「google方式」で距離を求める。
4.両者で算出された距離を比較する。

この結果をそれぞれ比較すれば、両者の計算結果にどれだけの違いが出てくるかが解ります。
ただ、それぞれの計算結果(数値)を比較しても個々の差がどれくらいあるかは解りますが、全体的な差のイメージが湧きません。

そこで、計算結果の距離をビジュアル的に表現してみたいと思います。
では、距離をどの様にして表現するのか?
とりあえず今回は以下の様な方法を考えてみました。

A、Bの2地点に対して距離を求めた場合、通常の2次元の世界であれば、A地点からB地点までを直線で引いた長さが距離となります。

しかし、3次元である円い地球を、図1の様に2次元上で表現している為、A地点とB地点を直線で結んだ長さが実際の距離にはなりません。
例えば単純に2次元上でA地点(0,0)、B地点(150,30)の2点に対して3平方の定理を使用して、斜辺の長さを求めると、152.97となります。
これに1度あたりの距離111Kmを掛けると、16979.73Kmとなります。
これを実際の地球に想定して、東経0度、北緯0度と、東経150度、北緯30度としての2地点の距離を「ろっきー」方式で求めると、15427.82Kmとなります。
上記の計算方法についてはmy-hobby : GoogleAPI~2つの住所から距離を求める~を参照して下さい。

図2-2地点の実際の距離-
図2-2地点の実際の距離-

上記の計算結果で得られたこの結果(図2)の距離を点として画面上に描画して、これを703のポイントに対して全て行ないます。
そうすると、A地点(東経0度、北緯0度)からB地点(703個のポイント)のそれぞれに対しての距離が点として描画される為、距離を基準とした「703個の点の集合からなる図形」が出来上がります。
これを「Google方式」、「ろっきー」方式のそれぞれに対して行い、先ずはビジュアル的に両者の計算結果を確認してみようという作戦です!

結果がどうなるか分かりませんが、興味がある方はこの「研究」にお付き合い下さい。
※研究なので失敗する事もあります。。。
なおこのテストの為に、専用のアプリをVB.netで開発してしまいました!

では先ず手始めに、「ろっきー」方式から試してみたいと思います。
さてどの様な図形が浮かび上がるのか?
結果は次回報告したいと思います。

zipnavi機能拡張 ~住所の構造化~

郵便番号検索 -zipnavi-が完成し、住所から郵便番号が検索できるようになりました。
ただ、郵便番号だけ検索できても面白くありません。

そこでzipnaviでは、サイト(Webサービス)の汎用性を広げるべく、住所の構造化に取り組みたいと思います。
ではここで言う「住所の構造化」とは何か?
簡単に言うと、検索条件として入力された住所情報を、「都道府県」、「市区町村」、「町域」、「その他」の4つの情報に分割する事を意味します。
具体的には以下の様な例です。

東京都港区芝公園4丁目2-8

東京都、港区、芝公園、4丁目2-8

一見これで何が出来るの?と思いますが、この機能は住所情報単体で使ってもあまり意味がありません。
複数の住所を併せて使用する事で、色々なメリットが出てきます。
例えば以下の様な例です。

1.住所情報の地域別の分布が採れる。
例えば以下の様な住所一覧(例えば温泉施設)が存在した場合、住所をそれぞれ構造化する事で、
東京都には3件、神奈川県には1件、更に東京都の中で港区芝公園には2件、港区高輪には1件、といった感じで、分布を採る事が出来ます。
これを応用すれば、この地域は温泉が多い、少ないといった情報を把握する事が出来ます。
a.東京都港区芝公園4丁目あいう⇒【東京都、港区、芝公園、4丁目あいう】
b.東京都港区芝公園3丁目かきく⇒【東京都、港区、芝公園、3丁目かきく】
c.東京都港区高輪3丁目さしす⇒【東京都、港区、高輪、3丁目さしす】
d.神奈川県横須賀市金谷たちつ⇒【神奈川県、横須賀市、金谷、たちつ】

2.施設検索等で現在地から近い施設を検索できる。
例えばGPS付きの携帯電話等で、現在地の住所を取得する事が出来れば、現在地点から近い温泉施設を検索する事や、現在地から近い順に温泉施設を一覧表示するといったレコメンドも出来るようになります。
【具体例】
GPSで取得した住所:東京都港区高輪1丁目999番地⇒【東京都、港区、高輪、1丁目999番地】
町域レベルで一致するのが上記の4施設ではcとなり、あとは市区町村、都道府県でそれぞれ合致するものを一覧に表示していけばよい事になります。
なお、それぞれの住所に対して事前に緯度経度を取得し、2地点の距離を計算して距離の短い順に並べるという方法もありますが、仮に検索対象の施設が1000件あった場合に、1000施設全てに対してそれぞれの距離を計算する必要がある為、1回の検索でPCの負荷が掛かり過ぎるといった問題があります。
それに比べて、住所の構造化を利用した方法では、単純に文字列の一致で検索するだけなので、非常に実用的な方法と言えます。
※施設の件数が増加しても、レスポンスの低下を最小限に出来ます。

3.住所情報を分けて入力する必要が無くなる
これは住所情報単体でも使えます。
よくECサイトなどで買い物をした際に、配送先の住所を入力しますが、入力欄がいくつかに分かれてて、都道府県はプルダウンになってたり、と入力が面倒くさい場合があります。
プルダウンは入力ミスを防ぐという目的があるのかもしれませんが、利用者側からしてみれば一気に住所情報を入力したいです。
そこで住所の構造化が利用されれば、住所の入力欄は1つにする事ができ、1つの入力情報から自動的に住所を構造化出来るので、紛らわしい入力の手間が省けます。
しかも郵便番号は入力する必要が無い(郵便番号検索で自動的に検索される)ので、まさに一石二鳥です。

ざっと上げただけでも上記の様な事が可能になります。
今までは「住所」という情報だけで終わってしまっていたものが、今後は「住所の構造化」によって、さまざまな利用方法が生まれてくる可能性があります。
今後「住所の構造化」機能を実現する事で、今後新しいサービスを提案していければと思っています。
その為には更なる住所解析の精度向上も今後必要となってくる課題です。
ホントにこんな機能が出来るの?という意見もありますが、初期の開発時に将来的にこの様な機能の実現を考慮しながら開発していた為、そんな大げさな開発では無いと言うのが本音です。
大きな落とし穴(バグ)が無ければ、実現できると思います。

ちなみに「住所の構造化」は、実はサービス – Google Maps API – Google Codeで既に実現されていました。
※既に先を越されてました。。。

ただ、自分で実装すれば、サービスの内容によって自由にカスタマイズ出来るというメリットがあります。
その点では今後他サイトには無いオリジナルに富んだサービスを提供できる事に繋がるので、無駄ではないと思っています。

現在のzipnaviですぐにこの機能を活用する予定はありませんが、検索エンジンの汎用性が広がれば、今後新たなサービスが閃くきっかけになるかもしれませんので、とりあえず作ってみたいと思います。
住所構造化を使った具体的なサービスが閃いたら、いずれ本ブログで報告したいと思います。

2地点の緯度経度から距離を求める(global化 2/2)

前回(my-hobby : 2地点の緯度経度から距離を求める(global化 1/2))の続きです。
前回の内容を踏まえて、問題点を解決する方法を考えました。
具体的に言うと以下の様な方法です。
1.A地点の座標がx軸の中心となるように、地図を移動させる。y軸は任意。
2.B地点についてはA地点の緯度経度から相対的な位置関係を計算して、B地点とのx軸、y軸の経差、緯差を求める。
3.x軸、y軸の距離差を使用して、2地点の距離を計算する。

この方法だとA地点を経度の基点として、地図を左右に移動できるので、前回の様な問題を解決する事が出来ます。

上記の方法で計算式を書くと以下の様な感じです。(vb.netで記述しています)
[vbnet]
Dim longitude1 As Double ‘A地点の経度
Dim latitude1 As Double ‘B地点の緯度
Dim longitude2 As Double ‘A地点の経度
Dim latitude2 As Double ‘B地点の緯度

Dim latitude1Abs As Double ‘A地点の緯度の絶対値
Dim latitude2Abs As Double ‘B地点の緯度の絶対値
Dim CosIdoWK As Double ‘基準となる緯度(角度)

Dim xWK As Double ‘経度差
Dim yWK As Double ‘緯度差
Dim distance As Double ‘2地点の距離

distance = 0

‘基準となる緯度(角度)を取得
latitude1Abs = Abs(latitude1)
latitude2Abs = Abs(latitude2)
If latitude1Abs &lt;= latitude2Abs Then
If latitude1Abs = 0 Then
CosIdoWK = latitude2Abs
Else
CosIdoWK = latitude1Abs
End If
Else
CosIdoWK = latitude2Abs
End If

‘A地点、B地点の経差、緯差を求める。
‘差の絶対値を取る事で、緯度経度に-(マイナス)が入っても、それぞれの差を求める事が出来る
x = Abs(longitude2 – longitude1)
y = Abs(latitude2 – latitude1)

‘経差を補正
‘※原点に対して180度を超過している(地球を半周以上している)場合は、反対周りの距離に変換する
If x &gt; 180 Then
x = 360 – Abs(x)
End If

‘座標上から2地点の距離を求める
If CosIdoWK = 0 Then ‘赤道上の距離の場合
distance = x * 111
Else
xKm = x * Cos(Math.PI / 180 * CosIdoWK) * 111
yKm = y * 111
distance = (xKm ^ 2 + yKm ^ 2) ^ (1 / 2)
End If
[/vbnet]
※上記計算式は、2地点の距離が2極点を通過する場合は、超レアケースでかつ計算式が複雑になる為考慮していません。

上記計算式の場合、過去の記事(my-hobby : GoogleAPI~2つの住所から距離を求める~)でも紹介していますが、この計算式には根本的な欠陥があって、そもそも地球の円い表面を、平らな表面と仮定して計算している為、2地点の緯度差、経度差が大きくなればなるほど、その誤差は大きくなる可能性があります。
具体的には、以下の様な例と考えられます。

上記の様な例を元に、今回採用した方法で距離を計算するとA地点とB地点の距離は約17303Kmとなります。
しかし、A地点からB地点の移動は単純に地球を半周している為、40000Km÷2=20000Kmとなるのが正しい答えのはずです。
※計算結果と実際の距離には、約2700Kmもの誤差が発生しています。

要は、国を跨るような距離の計算は誤差が出過ぎるという事です。
正確に測ろうとすると、非常に難しい計算式になります。
今回の計算式は、国をまたぐような2点間の距離の計算は考慮しませんが、同じ国の中で2地点の距離の計算には最適だと思います。
(参考にしてみてください!)

2地点の緯度経度から距離を求める(global化 1/2)

以前の記事でmy-hobby : GoogleAPI~2つの住所から距離を求める~を紹介しましたが、
こちらの内容はあくまで日本国内に限った場合の方法でした。
先日メンバーのもじゃもじゃさんから、iPhoneのGPS機能を使ったアプリを作っているので、記事で掲載した内容を使いたいという話がありました。
自分の記事の内容を実際に使ってもらえるのはうれしい事なのですが、今の機能(日本国内限定)で使ってもらうのはちょっと失礼なので、思い切って全世界どこででも使えるようにしようと思います!

そもそも、なぜ日本国内限定にしているかと言うと、以前の記事で紹介した計算式は東経0~180度、北緯0~90度までの範囲でしか計算できない為、日本国内限定としていました。
※GoogleMAPS APIが返す座標(緯度経度)は以下の様な値となっています。
東経0~180度:0~180
西経0~180度:0~-180
北緯0~90度:0~90
南緯0~90度:0~-90
世界地図で表すと、以下の様な感じです。
【図1】

地図から緯度経度を調べるにて、各地点のGoogleMAPS APIが返す座標(緯度経度)の結果を確認できます

東経0~180度、北緯0~90度以外は座標が-(マイナス)を返すので、差を使った計算が出来ないという理由がありました。
緯度・経度の差より距離を求めているので、マイナスを返す場合、単純に差を求めると、結果が意図したものと異なる場合があります。
※前回までの計算式

IdoWK = Abs(txt_Ido.Text – txt_Ido2.Text) * 111
KeidoWK = Abs(txt_Keido.Text – txt_Keido2.Text) * Cos(Math.PI / 180 * CosIdoWK) * 111
KyoriWK = (IdoWK ^ 2 + KeidoWK ^ 2) ^ (1 / 2)

今回は上記内容を考慮してどの経度、緯度でも計算可能な式に変更したいと思います。
GoogleMAPS APIが返す座標の場合、緯度差、経度差を計算する際に-(マイナス)が邪魔になるので、これをどの位置でも0以上になるように原点(0,0)の位置を移動させます。
移動させた結果は以下の様な感じです。
【図2】

※x(経度)を180、y(緯度)を90足した(補正した)状態としました。

これでヨシ!と思いきや、この方法には大きな落とし穴がありました。

以下の図3の左のケースの様な場合に、上記の方法で2地点の距離を求めようとすると、最適な結果が得られなくなります。
【図3】

図2で示した座標で計算を行なうと、図3の左側の図の様な結果が2地点の距離になりますが、実は右側の図の方が距離が近いのです。
2地点の距離を求めると言っても、遠い距離を返してしまっては意味がありません。
地球の様に円い3次元の物体の表面を移動する場合には、単純に2地点を直線で結んだだけでは、最短距離を求める事が出来ないと言う事です。

かといって、3次元の世界で新たに計算式を作るのも面倒なので、2次元の世界で前回作った計算式を応用して最短距離を求める方法を考えたいと思います。
この問題の解決する為、少ない知恵を絞って考えた方法を次回紹介します。

経度から緯度の距離を求める方法

前回のブログでは、2点間の距離を求める方法を紹介しました。
前回のブログはmy-hobby : GoogleAPI~2つの住所から距離を求める~で確認できます。

今回はITとはかなりかけ離れていますが、番外編として前回のブログで紹介した計算方法の詳しい内容を紹介します。
まず前回の内容より1度あたりの2点間の緯度差から距離を求めるには
1.0061504(緯度差)×111Km
で計算する事が出来ますが、
なぜ経度差から距離を求めるのは、
4.2389033(経度差)×111Km×cos34.6524841(緯度)
となるのでしょうか?
※なぜ「cos34.6524841(緯度)」が必要なのか?

※前回までのおさらい

上記内容は1度あたりの距離ですが、説明を解りやすくする為に
まず地球の緯線と経線の外周の距離を見てみたいと思います。
【経線】
必ず極点(北極点、南極点)を通過する為、どの経度でも必ず同じ長さとなります。
※前回のブログより、
実際の値(赤道半径):6,378.137km
実際の値(極半径):6,356.752km
と説明しているので、実際には地球は楕円形をしていますが、今回は真円とみなし、かつ外周を4万Kmと仮定しています。

【緯線】
赤道上(北緯・南緯0度)では4万Kmですが、それぞれ極点に近づくにつれ、その距離は小さくなり、
極点(北緯・南緯90度)では、経線の外周は0Kmとなります。

●図1

つまり緯線の外周の距離は、緯度によって異なるのです。
北緯・南緯0度では4万Km、北緯・南緯90度では0Km。
では北緯30度では何kmになるのか?

それは以下の様な方法で求める事が出来ます。
まず北緯0度と北緯30度の地点に対し、地球の中心から線を引きます。
そうすると、角Aは30度になり、線1は北緯0度の外周の半径になります。
また線2も地球の中心から引いた線になるので線1と同じ長さになります。
●図2

・角A:30度
・線1=線2

次に北緯30度の地点から、地球の地軸に対して線を引きます。
そうすると、線3は北緯30度の外周の半径になります。
更に線1と線3は平行なので、角Bも30度となります。
●図3

・線1と線3は平行
・角B:30度

ここで話は変わって、cosは三角形の斜辺を1とした場合の、角Cに対する底辺の長さを示したものになるので、
cos30とした場合は、底辺の長さは0.866となります。
●図4

・斜辺の長さ:1
・底辺の長さ:0.866

図4で得た考え方を図3に当てはめると、
線1に対する線3の長さの比率が解ります。
●図5

・線1:1
・線3:0.866
・線1と線3の比率は1:0.866

線1、線3共に、北緯0度、北緯30度の外周の半径になるので、
線1、線3の比率が解れば、北緯0度の外周から、北緯30度の外周の距離も求まります。
これと同じ考えで、1度あたりの距離も同じ比率を使って求めることが出来ます。
これにより、北緯30度の1度あたりの距離は111Km×0.866=96.13Kmとなります。
●図6

・北緯30度の1度あたりの距離:96.13Km

これを先ほどの式に当てはめると
4.2389033(経度差)×111Km×cos34.6524841(緯度)
といった計算式になります。

なんか数学の授業をやっている様な気がするのは自分だけでしょうか?
最後まで読んで理解してくださった方、ありがとうございます。そしてご苦労様でした。。。
次回はまたITネタに戻します。