ソースコード付きで緯度・経度を元にした二点間の距離計算方法を解説します。
MapKit等の地図アプリを使用していると、現在位置から目的地までの距離や、
ある場所から、ある場所までの距離を表示したい時があります。
他にも、地図に立てたピンを全て表示させたい場合の縮尺計算も、
全てのピンの中心位置となる緯度経度を計算し、
そこから一番離れているピンまでの距離を計算すれば、
全てのピンを表示出来る縮尺を求める事が出来ます。
そんな、様々なシーンで使う事となる距離の計算方法を
Objective-C流にソースコード付きで解説したいと思います。
緯度・経度を元に二点間の距離(m)を算出する方法
今回はメソッドに纏めましたので、そのままコピペでもご使用頂けます。
まずは下記コードをご覧下さい
//------------------------------------------------------------------------------ // 二点間の距離を計算する(m) //------------------------------------------------------------------------------ -(int)locationDistance:(CLLocationCoordinate2D)loc1 to:(CLLocationCoordinate2D)loc2 { // 2点の緯度の平均 double latAvg = (( loc1.latitude + ((loc2.latitude - loc1.latitude)/2) ) / 180) * M_PI; // 2点の緯度差 double latDifference = (( loc1.latitude - loc2.latitude ) / 180) * M_PI; // 2点の経度差 double lonDifference = (( loc1.longitude - loc2.longitude ) / 180) * M_PI; double curRadiusTemp = 1 - 0.00669438 * pow(sin(latAvg), 2); // 子午線曲率半径 double meridianCurvatureRadius = 6335439.327 / sqrt(pow(curRadiusTemp, 3)); // 卯酉線曲率半径 double primeVerticalCircleCurvatureRadius = 6378137 / sqrt(curRadiusTemp); // 2点間の距離 double distance = pow(meridianCurvatureRadius * latDifference, 2) + pow(primeVerticalCircleCurvatureRadius * cos(latAvg) * lonDifference, 2); distance = sqrt(distance); int distanceInt = (int)round(distance); return distanceInt; }
引数として、緯度・経度情報を保持したCLLocationCoordinate2Dを二つ与えます。
与えられた二点の地点の緯度・経度を元に、距離計算方式を使い距離をm(メートル)として取得し、
返却します。
ヒュベニ距離計算式で求める二点間の距離(m)
また、他にもヒュベニの公式距離計算式を使った距離の求め方は下記をご覧下さい
//------------------------------------------------------------------------------ // 2点の経緯度から距離を求める[m] //------------------------------------------------------------------------------ +(float)calcDistanceWithCoordinate:(CLLocationCoordinate2D)begin end:(CLLocationCoordinate2D)end { /* ヒュベニの距離計算式 D=sqt((M*dP)^2+(N*cos(P)*dR)^2) D: 2点間の距離(弧)(m) P: 2点の平均緯度P[ラジアン]=(P1+P2)/2 dP: 2点の緯度差dP[ラジアン]=P1-P2 dR: 2点の経度差dR[ラジアン]=R1-R2 M: 子午線曲率半径 M=6334834/sqrt((1-0.006674*sin(P)^2)^3) N: 卯酉線曲率半径 N=6377397/sqrt(1-0.006674*sin(P)^2) */ static const float PI = 3.141592653589793; const float P = ( begin.latitude+end.latitude ) / 2 * PI / 180; const float dP = ( begin.latitude-end.latitude ) * PI / 180; const float" dR = ( begin.longitude-end.longitude ) * PI / 180; const float M = 6334834 / sqrt( ( 1-0.006674 * sin( P ) * sin( P ) ) * ( 1-0.006674 * sin( P ) * sin( P ) ) * ( 1-0.006674 * sin( P ) * sin( P ) ) ); const float N = 6377397 / sqrt( 1-0.006674 * sin( P ) * sin( P ) ); float D = sqrt( ( M * dP ) * ( M * dP ) + ( N * cos( P ) * dR ) * ( N * cos( P ) * dR ) ); return D; }
使い方は、先のサンプルコードと同じ様に
引数として、緯度・経度情報を保持したCLLocationCoordinate2Dを二つ与えます。
与えられた二点の地点の緯度・経度を元に、距離計算方式を使い距離をm(メートル)として取得し、
返却します。
そして、全てのピンが収まる様に縮尺を調整するメソッドをMapKitは持っていますので、
中心位置と一番離れた場所までの距離を渡す事で、自動的に縮尺を調整してくれます。
/* center_coordinate:中心地点の緯度・経度 max_distance:一番離れている場所までの距離 */ // 全てのピンが画面に入るように縮尺を設定 MKCoordinateRegion region; region = MKCoordinateRegionMakeWithDistance( center_coordinate, max_distance*2.0, max_distance*2.0 ); [self.mapView setRegion:region animated:NO];
他にも、距離を使った処理は地図アプリや
位置情報を使ったアプリを製作する際には必ずしも通る道です。
こういった距離の計算式はプログラミング技法というよりも数学の要素がとても強いので、
数学が苦手な人は、「こういった計算方法で距離を求める事が出来る」と知っているだけで十分だと思います。
特に三角関数が何だとか、球体を平面で捉えた時の違いや時期によったり、地形によったりする違いを吸収する数式等の
細かい理由は特に考える必要はないのかな~っと感じます。
今回の記事を、地図アプリ作成時のメモ的に思って頂ければ幸いです。
とても魅力的な記事でした!!
返信削除また遊びに来ます!!
ありがとうございます。
銘柄選び様
削除有難う御座います。そういった言葉がブログを運営する上での励みになります。
引き続き有益な記事を公開して参りますので、
今後ともよろしくお願い致します
おお、求めていたものがありました。
返信削除参考にさせていただきます。
ありがとうございます。
この度はコメント頂き、誠に有難う御座います。
削除引き続き有益な情報を公開して参りますので、
今後とも何卒よろしくお願い致します。