緯度と経度の2点間の距離を計算しますか?(ハバシン式)


907

緯度と経度で指定された2点間の距離を計算するにはどうすればよいですか?

明確にするために、距離をキロメートル単位で教えてください。ポイントはWGS84システムを使用しており、利用可能なアプローチの相対的な精度を理解したいと思います。



3
WGS 84のような回転楕円体にHaversine式を適用できないことに注意してください。このメソッドは、半径のある球にのみ適用できます。
マイクT

3
ここでの回答のほとんどは単純な球面三角法を使用しているため、GPSシステムで使用されるWGS84楕円体距離と比較すると、結果はかなり粗雑です。いくつかの回答は、Vincentyの楕円体の公式を参照していますが、そのアルゴリズムは1960年代の卓上計算機で使用するために設計されており、安定性と精度の問題があります。ハードウェアとソフトウェアが改善されました。さまざまな言語で実装された高品質のライブラリについては、GeographicLibを参照してください。
PM 2Ring

@MikeT-ここでの回答の多くは短い距離で役立つように見えますが、true :緯度/経度 WGS 84から取得し、 Haversine 球面上の点であるかのように適用すると、エラーが原因であるだけの回答が得られません。地球の平坦化係数なので、より正確な式の1%以内でしょうか?これらは短い距離である、という警告があります。たとえば、単一の町の中で。
ToolmakerSteve 2018年

1
これらplateformsの場合:モノラル/ .NET 4.5 / .NETのコア/ Windowsの携帯電話は、/ユニバーサルのWindowsプラットフォーム/ XamarinのiOS / AndroidのXamarinは見8.xのstackoverflow.com/a/54296314/2736742
A.モレル

回答:


1148

このリンクは、Haversine式を使用して距離を計算する方法の詳細を示しているので、役立つ場合があります。

抜粋:

このスクリプト[Javascript]は、「Haversine」式を使用して、2点間の大圏距離、つまり地表上の最短距離を計算します。

function getDistanceFromLatLonInKm(lat1,lon1,lat2,lon2) {
  var R = 6371; // Radius of the earth in km
  var dLat = deg2rad(lat2-lat1);  // deg2rad below
  var dLon = deg2rad(lon2-lon1); 
  var a = 
    Math.sin(dLat/2) * Math.sin(dLat/2) +
    Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * 
    Math.sin(dLon/2) * Math.sin(dLon/2)
    ; 
  var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 
  var d = R * c; // Distance in km
  return d;
}

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

51
この計算/方法は、地球が回転楕円体(完全な球体ではない)であることを説明していますか?元の質問では、WGS84地球上のポイント間の距離を求めていました。完全な球を使用することでどのくらいのエラーが発生するかはわかりませんが、地球上の点の位置によってはかなり多くなる可能性があるので、この違いは覚えておく価値があります。
redcalx

15
Haversineの公式は地球が回転楕円体であることを考慮していないため、その事実のためにいくつかのエラーが発生します。0.5%以上の正確性は保証できません。ただし、これは許容できるレベルのエラーかもしれません。
ブランドン、

24
Math.atan2(Math.sqrt(a), Math.sqrt(1-a))代わりにを使用する理由はありMath.asin(Math.sqrt(h))ますか?これは、Wikipediaの記事で使用されている式を直接実装したものですか?より効率的または数値的に安定していますか?
musiphil 2012

16
@UsmanMutawakilええと、あなたが得る38マイルは道路上の距離です。このアルゴリズムは、地表上の直線距離を計算します。Googleマップには、同じことをする距離ツール(左下、「Labs」)があり、それを使用して比較します。
Pascal

4
Forte_201092 @:それは必要ありませんので-と(sin(x))²イコール(sin(-x))²
ジャンHominal

360

プロジェクトのポイント間の多くの距離を計算する必要があったので、先に進んでコードを最適化しようとしましたが、ここで見つかりました。さまざまなブラウザーで平均して、私の新しい実装は最も支持されている回答より2倍速く実行されます。

function distance(lat1, lon1, lat2, lon2) {
  var p = 0.017453292519943295;    // Math.PI / 180
  var c = Math.cos;
  var a = 0.5 - c((lat2 - lat1) * p)/2 + 
          c(lat1 * p) * c(lat2 * p) * 
          (1 - c((lon2 - lon1) * p))/2;

  return 12742 * Math.asin(Math.sqrt(a)); // 2 * R; R = 6371 km
}

私のjsPerfで遊んで、結果をここで確認できます

最近私は同じことをpythonで行う必要があったので、ここにpython実装があります

from math import cos, asin, sqrt, pi

def distance(lat1, lon1, lat2, lon2):
    p = pi/180
    a = 0.5 - cos((lat2-lat1)*p)/2 + cos(lat1*p) * cos(lat2*p) * (1-cos((lon2-lon1)*p))/2
    return 12742 * asin(sqrt(a)) #2*R*asin...

そして、完全を期すために、WikiのHaversine


13
@AngularMであり、直線ではなく道路を走行する場合、Googleが距離を計算する可能性が非常に高くなります。
サルバドールダリ

3
グーグルは走行距離を計算し、これは「カラスが飛ぶように」を計算します
ホビーイスト

4
@Ouadie、それは速度を向上させますか?おそらくそうではないかもしれませんが、古いブラウザにコピーペーストする人にとっては、多くの「あなたのものは機能しない」ことになります
Salvador Dali

4
ええ、でも何の// 2 * R; R = 6371 km略ですか?現在の方法はkmまたはマイルで回答を提供しますか?より良いドキュメントが必要です。ありがとう
Khalil Khalaf

20
@KhalilKhalaf冗談やここでトロールしようとしているの?kmはキロメートルを表します。Rは何を表していると思いますか(特に私たちがshpereについて話す場合)?すでにkmが表示されている場合、答えはどの単位であるかを推測してください。ここでどのような種類のドキュメントを探していますか?文字通り4行あります。
サルバドールダリ

69

C#の実装は次のとおりです。

static class DistanceAlgorithm
{
    const double PIx = 3.141592653589793;
    const double RADIUS = 6378.16;

    /// <summary>
    /// Convert degrees to Radians
    /// </summary>
    /// <param name="x">Degrees</param>
    /// <returns>The equivalent in radians</returns>
    public static double Radians(double x)
    {
        return x * PIx / 180;
    }

    /// <summary>
    /// Calculate the distance between two places.
    /// </summary>
    /// <param name="lon1"></param>
    /// <param name="lat1"></param>
    /// <param name="lon2"></param>
    /// <param name="lat2"></param>
    /// <returns></returns>
    public static double DistanceBetweenPlaces(
        double lon1,
        double lat1,
        double lon2,
        double lat2)
    {
        double dlon = Radians(lon2 - lon1);
        double dlat = Radians(lat2 - lat1);

        double a = (Math.Sin(dlat / 2) * Math.Sin(dlat / 2)) + Math.Cos(Radians(lat1)) * Math.Cos(Radians(lat2)) * (Math.Sin(dlon / 2) * Math.Sin(dlon / 2));
        double angle = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));
        return angle * RADIUS;
    }

}

14
赤道半径を使用していますが、平均半径6371 kmを使用する必要があります
フィリップレイバート09

7
これはすべきではないdouble dlon = Radians(lon2 - lon1);double dlat = Radians(lat2 - lat1);
クリスMarisic

私はクリス・マリシックに同意します。元のコードを使用しましたが、計算が間違っていました。デルタをラジアンに変換する呼び出しを追加しましたが、正しく動作します。私は編集を提出し、それがピアレビューされるのを待っています。
Bryan Bedard、2011

lat1とlat2もラジアンに変換する必要があるため、別の編集を送信しました。私はまた、式に一致するように割り当てるための式を改訂し、コードはここで見つける:movable-type.co.uk/scripts/latlong.html
ブライアンBedard

RADIUS他の回答と同様に、値は6371である必要がありますか?
クリスヘイズ

66

これは、Haversine式のJava実装です。

public final static double AVERAGE_RADIUS_OF_EARTH_KM = 6371;
public int calculateDistanceInKilometer(double userLat, double userLng,
  double venueLat, double venueLng) {

    double latDistance = Math.toRadians(userLat - venueLat);
    double lngDistance = Math.toRadians(userLng - venueLng);

    double a = Math.sin(latDistance / 2) * Math.sin(latDistance / 2)
      + Math.cos(Math.toRadians(userLat)) * Math.cos(Math.toRadians(venueLat))
      * Math.sin(lngDistance / 2) * Math.sin(lngDistance / 2);

    double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));

    return (int) (Math.round(AVERAGE_RADIUS_OF_EARTH_KM * c));
}

ここでは、最も近いkmへの回答を丸めていることに注意してください。


2
2点間の距離をメートルで計算したい場合、より正確な方法は何でしょうか?6371000地球の半径として使うには?(平均地球半径は6371000メートル)または関数からキロメートルをメートルに変換しますか?
2016

マイルが必要な場合は、結果の倍数0.621371
lasec0203

42

本当にありがとうございました。Objective-C iPhoneアプリで次のコードを使用しました。

const double PIx = 3.141592653589793;
const double RADIO = 6371; // Mean radius of Earth in Km

double convertToRadians(double val) {

   return val * PIx / 180;
}

-(double)kilometresBetweenPlace1:(CLLocationCoordinate2D) place1 andPlace2:(CLLocationCoordinate2D) place2 {

        double dlon = convertToRadians(place2.longitude - place1.longitude);
        double dlat = convertToRadians(place2.latitude - place1.latitude);

        double a = ( pow(sin(dlat / 2), 2) + cos(convertToRadians(place1.latitude))) * cos(convertToRadians(place2.latitude)) * pow(sin(dlon / 2), 2);
        double angle = 2 * asin(sqrt(a));

        return angle * RADIO;
}

緯度と経度は10進数です。私が使用している距離が非常に小さいため、asin()呼び出しにmin()を使用しなかったため、必要としません。

私がラジアンで値を渡すまで、それは間違った答えを出しました-今ではそれはアップルのマップアプリから得られた値とほとんど同じです:-)

追加アップデート:

iOS4以降を使用している場合、Appleはこれを実行するいくつかの方法を提供しているため、同じ機能が次のように実現されます。

-(double)kilometresBetweenPlace1:(CLLocationCoordinate2D) place1 andPlace2:(CLLocationCoordinate2D) place2 {

    MKMapPoint  start, finish;


    start = MKMapPointForCoordinate(place1);
    finish = MKMapPointForCoordinate(place2);

    return MKMetersBetweenMapPoints(start, finish) / 1000;
}

1
iOS SDKには独自の実装があります:developer.apple.com/library/ios/documentation/CoreLocation/…
tuler

かっこpow(sin(dlat / 2), 2) + cos(convertToRadians(place1.latitude))が間違っていると思います。それらを削除すると、このページで他の実装を使用したとき、またはウィキペディアのHaversine式を最初から実装したときに得られる結果と一致します。
zanedp

NYCの座標(40.7127837、-74.0059413)とLAの座標(34.052234、-118.243685)を使用すると、()その合計で3869.75になります。それらがなければ、私は3935.75を取得します。これは、Web検索で得られるものとほぼ同じです。
zanedp

40

これは非常に合理的な概算を与える単純なPHP関数です(エラーマージンは+/- 1%未満)。

<?php
function distance($lat1, $lon1, $lat2, $lon2) {

    $pi80 = M_PI / 180;
    $lat1 *= $pi80;
    $lon1 *= $pi80;
    $lat2 *= $pi80;
    $lon2 *= $pi80;

    $r = 6372.797; // mean radius of Earth in km
    $dlat = $lat2 - $lat1;
    $dlon = $lon2 - $lon1;
    $a = sin($dlat / 2) * sin($dlat / 2) + cos($lat1) * cos($lat2) * sin($dlon / 2) * sin($dlon / 2);
    $c = 2 * atan2(sqrt($a), sqrt(1 - $a));
    $km = $r * $c;

    //echo '<br/>'.$km;
    return $km;
}
?>

前に言ったように; 地球は球ではありません。それはマーク・マクワイヤーが一緒に練習しようと決めた古い、古い野球のようなものです-それはへこみと隆起でいっぱいです。単純な計算(このような)は、球のように扱います。

さまざまな方法は、この不規則な卵形のどこにいて、ポイントがどれだけ離れているか(距離が近いほど絶対誤差範囲が小さくなる)によって、多少正確になる場合があります。期待が正確であればあるほど、数学は複雑になります。

詳細:ウィキペディアの地理的距離


4
これは完璧に動作します!$ distance_miles = $ km * 0.621371を追加しました。おおよその距離(マイル)に必要なのはそれだけです。トニー、ありがとう。

31

ここに私の実例を掲載します。

MySQLで、指定されたポイント間の距離を持つすべてのポイントをリストします(ランダムなポイント-lat:45.20327、long:23.7806を使用)、緯度と経度、50 KM未満(テーブルフィールドはcoord_latおよびcoord_longです):

DISTANCE <50のすべてをキロメートル単位でリストします(地球半径6371 KMと見なされます)。

SELECT denumire, (6371 * acos( cos( radians(45.20327) ) * cos( radians( coord_lat ) ) * cos( radians( 23.7806 ) - radians(coord_long) ) + sin( radians(45.20327) ) * sin( radians(coord_lat) ) )) AS distanta 
FROM obiective 
WHERE coord_lat<>'' 
    AND coord_long<>'' 
HAVING distanta<50 
ORDER BY distanta desc

上記の例は、MySQL 5.0.95および5.5.16(Linux)でテストされています。


適切なアプローチは、近似を使用して結果を事前にフィルタリングすることかもしれないと思うので、重い式はいくつかの場合にのみ適用されます。他の条件がある場合に特に役立ちます。:私は最初のおよそ10mlの液体フッ化水素を圧入のためにこれを使用していstackoverflow.com/questions/1253499/...
パト

28

他の答えでの実装 不足している。

2点間の距離の計算はdistmgeosphereパッケージの関数を使用すると非常に簡単です。

distm(p1, p2, fun = distHaversine)

どこ:

p1 = longitude/latitude for point(s)
p2 = longitude/latitude for point(s)
# type of distance calculation
fun = distCosine / distHaversine / distVincentySphere / distVincentyEllipsoid 

地球は完全に球形ではないので、楕円体Vincenty式は距離を計算するためのおそらく最良の方法です。したがって、geosphere次に使用するパッケージでは:

distm(p1, p2, fun = distVincentyEllipsoid)

もちろん、必ずしもgeosphereパッケージを使用する必要はありません。R関数を使用して、ベースの距離を計算することもできます。

hav.dist <- function(long1, lat1, long2, lat2) {
  R <- 6371
  diff.long <- (long2 - long1)
  diff.lat <- (lat2 - lat1)
  a <- sin(diff.lat/2)^2 + cos(lat1) * cos(lat2) * sin(diff.long/2)^2
  b <- 2 * asin(pmin(1, sqrt(a))) 
  d = R * b
  return(d)
}

私があなたが言ったことを明確にするために:あなたがポストの終わりに与えるコード:それはVincentyの式の実装ですか?あなたが知る限りでは、それはVincentyを地球圏で呼び出すのと同じ答えを与えるべきですか?[私は地球圏や他のライブラリを持っていません。クロスプラットフォームアプリに含めるコードを探しているだけです。もちろん、既知の優れた計算機に対していくつかのテストケースを検証します。]
ToolmakerSteve '25

1
@ToolmakerSteve回答の最後にある関数は、Haversineメソッドの実装です
Jaap

こんにちは@Jaapフォーミュラの測定単位は何ですか?それはメートルですか?
ジャクソン

11

ヘイバシンは間違いなくおそらくほとんどの場合に適した式です。他の回答にはすでにそれが含まれているので、スペースを取りません。ただし、どの式を使用しても(1つだけではない)ことに注意することが重要です。可能な精度の範囲が広く、必要な計算時間がかかるためです。式の選択には、単純なノーブレイナーの答えよりも少し考えが必要です。

nasaの人からのこの投稿は、オプションの説明で見つけた中で最高のものです。

http://www.cs.nyu.edu/visual/home/proj/tiger/gisfaq.html

たとえば、半径100マイルの距離で行を並べ替えるだけの場合です。フラットアースフォーミュラは、ヘイバーシンよりもはるかに高速です。

HalfPi = 1.5707963;
R = 3956; /* the radius gives you the measurement unit*/

a = HalfPi - latoriginrad;
b = HalfPi - latdestrad;
u = a * a + b * b;
v = - 2 * a * b * cos(longdestrad - longoriginrad);
c = sqrt(abs(u + v));
return R * c;

余弦が1つと平方根が1つしかないことに注意してください。対Haversineフォーミュラ。


それは素晴らしい可能性です。ディスカッションで推奨される最大距離は100マイルではなく12マイルであり、それでもエラーは地球の位置によっては最大30メートル(100フィート)に達する可能性があることに注意してください。
Eric Wu

7

CLLocationDistanceのビルドを使用して、これを計算できます。

CLLocation *location1 = [[CLLocation alloc] initWithLatitude:latitude1 longitude:longitude1];
CLLocation *location2 = [[CLLocation alloc] initWithLatitude:latitude2 longitude:longitude2];
[self distanceInMetersFromLocation:location1 toLocation:location2]

- (int)distanceInMetersFromLocation:(CLLocation*)location1 toLocation:(CLLocation*)location2 {
    CLLocationDistance distanceInMeters = [location1 distanceFromLocation:location2];
    return distanceInMeters;
}

あなたの場合、キロメートルが必要な場合は1000で割ってください。


7

さらに別の答えを追加するのは好きではありませんが、Google Maps API v.3には球形のジオメトリ(およびその他)があります。WGS84を10進度に変換した後、これを行うことができます:

<script src="http://maps.google.com/maps/api/js?sensor=false&libraries=geometry" type="text/javascript"></script>  

distance = google.maps.geometry.spherical.computeDistanceBetween(
    new google.maps.LatLng(fromLat, fromLng), 
    new google.maps.LatLng(toLat, toLng));

Googleの計算がどの程度正確であるか、またはどのモデルが使用されているかについては何も言われていません(ただし、「ジオイド」ではなく「球形」と表示されています。ところで、「直線」の距離は、明らかに誰もが推測しているように見える地球の表面。


距離はメートル単位です。代替的に一方がcomputeLength()を使用することができる
electrobabe

7

Pythonの具現化Originは隣接する米国の中心です。

from haversine import haversine
origin = (39.50, 98.35)
paris = (48.8567, 2.3508)
haversine(origin, paris, miles=True)

キロメートルで答えを得るには、単にmiles = falseを設定します。


1
すべての作業を行う非標準のパッケージをインポートしています。それがそれだけ役立つかどうかはわかりません。
Teepeemm、2015

このパッケージは、numpyおよびscikit-learnとともにpython 3パッケージとして、PyPI、Pythonパッケージインデックスにあります。なぜパッケージに付けられるのかわからない。それらは非常に役立つ傾向があります。オープンソースとして、含まれているメソッドを調べることもできます。多くの人がこのパッケージが便利だと思うので、反対票があっても投稿を残します。乾杯。:)
theshellを

7

より簡単な解決策があり、より正確である可能性があります。地球の周囲は赤道で40,000 Km、グリニッジ(または任意の経度)サイクルで約37,000です。したがって:

pythagoras = function (lat1, lon1, lat2, lon2) {
   function sqr(x) {return x * x;}
   function cosDeg(x) {return Math.cos(x * Math.PI / 180.0);}

   var earthCyclePerimeter = 40000000.0 * cosDeg((lat1 + lat2) / 2.0);
   var dx = (lon1 - lon2) * earthCyclePerimeter / 360.0;
   var dy = 37000000.0 * (lat1 - lat2) / 360.0;

   return Math.sqrt(sqr(dx) + sqr(dy));
};

私はそれが楕円体であると私が言ったので、それを微調整する必要があることに同意します。そのため、コサインで乗算される半径は異なります。しかし、それはもう少し正確です。Googleマップと比較すると、エラーが大幅に減少しました。


この関数は距離をkm単位で返しますか?
Wikki、2016年

それは、赤道と経度の周期がKmであるためです。マイルの場合は、40000と37000を1.6で割ります。
マニアックな感覚で

これはここで提供される最良の答えのようです。私はそれを使いたいのですが、このアルゴリズムの正当性を検証する方法があるのか​​と思います。私はf(50,5,58,3)をテストしました。それは832kmを与えますが、「haversine」式を使用したmovable-type.co.uk/scripts/latlong.htmlは899kmを与えます。そのような大きな違いはありますか?
Chong Lip Phang

さらに、上記のコードによって返される値はkmではなくmであると思います。
Chong Lip Phang

@ChongLipPhang-注意:ピタゴラスの定理は、地球が平らであると想定しているため、小さな領域に対してのみ妥当な近似です。極端な場合として、赤道から始めて、東に90度、北に90度移動します。もちろん、最終結果は北極であり、東に0度、北に90度移動するのと同じです。そのため、sqrt(sqr(dx)+ sqr(dy))を実行すると、最初のケースでは大幅にオフになります。〜sqrt(10km sqr + 10km sqr)〜= 14.4 km vs正しい距離〜10km。
ToolmakerSteve 2018年

7

上記のすべての答えは、地球が球であると仮定しています。ただし、より正確な近似は、扁平回転楕円体の近似になります。

a= 6378.137#equitorial radius in km
b= 6356.752#polar radius in km

def Distance(lat1, lons1, lat2, lons2):
    lat1=math.radians(lat1)
    lons1=math.radians(lons1)
    R1=(((((a**2)*math.cos(lat1))**2)+(((b**2)*math.sin(lat1))**2))/((a*math.cos(lat1))**2+(b*math.sin(lat1))**2))**0.5 #radius of earth at lat1
    x1=R*math.cos(lat1)*math.cos(lons1)
    y1=R*math.cos(lat1)*math.sin(lons1)
    z1=R*math.sin(lat1)

    lat2=math.radians(lat2)
    lons2=math.radians(lons2)
    R1=(((((a**2)*math.cos(lat2))**2)+(((b**2)*math.sin(lat2))**2))/((a*math.cos(lat2))**2+(b*math.sin(lat2))**2))**0.5 #radius of earth at lat2
    x2=R*math.cos(lat2)*math.cos(lons2)
    y2=R*math.cos(lat2)*math.sin(lons2)
    z2=R*math.sin(lat2)

    return ((x1-x2)**2+(y1-y2)**2+(z1-z2)**2)**0.5

6

以下は、距離をkm単位で計算するSQL実装です。

SELECT UserId, ( 3959 * acos( cos( radians( your latitude here ) ) * cos( radians(latitude) ) * 
cos( radians(longitude) - radians( your longitude here ) ) + sin( radians( your latitude here ) ) * 
sin( radians(latitude) ) ) ) AS distance FROM user HAVING
distance < 5  ORDER BY distance LIMIT 0 , 5;

プログラミング言語による実装の詳細については、ここに記載されているphpスクリプトを実行するだけです。


5

これがHaversine式のtypescript実装です

static getDistanceFromLatLonInKm(lat1: number, lon1: number, lat2: number, lon2: number): number {
    var deg2Rad = deg => {
        return deg * Math.PI / 180;
    }

    var r = 6371; // Radius of the earth in km
    var dLat = deg2Rad(lat2 - lat1);   
    var dLon = deg2Rad(lon2 - lon1);
    var a =
        Math.sin(dLat / 2) * Math.sin(dLat / 2) +
        Math.cos(deg2Rad(lat1)) * Math.cos(deg2Rad(lat2)) *
        Math.sin(dLon / 2) * Math.sin(dLon / 2);
    var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
    var d = r * c; // Distance in km
    return d;
}

5

指摘したように、正確な計算では地球が完全な球体ではないことを考慮する必要があります。ここで提供されるさまざまなアルゴリズムの比較をいくつか示します。

geoDistance(50,5,58,3)
Haversine: 899 km
Maymenn: 833 km
Keerthana: 897 km
google.maps.geometry.spherical.computeDistanceBetween(): 900 km

geoDistance(50,5,-58,-3)
Haversine: 12030 km
Maymenn: 11135 km
Keerthana: 10310 km
google.maps.geometry.spherical.computeDistanceBetween(): 12044 km

geoDistance(.05,.005,.058,.003)
Haversine: 0.9169 km
Maymenn: 0.851723 km
Keerthana: 0.917964 km
google.maps.geometry.spherical.computeDistanceBetween(): 0.917964 km

geoDistance(.05,80,.058,80.3)
Haversine: 33.37 km
Maymenn: 33.34 km
Keerthana: 33.40767 km
google.maps.geometry.spherical.computeDistanceBetween(): 33.40770 km

距離が短い場合、KerertanaのアルゴリズムはGoogleマップのアルゴリズムと一致するようです。Googleマップは単純なアルゴリズムに従っていないようで、ここでは最も正確な方法である可能性があります。

とにかく、ここにKeerthanaのアルゴリズムのJavascript実装があります:

function geoDistance(lat1, lng1, lat2, lng2){
    const a = 6378.137; // equitorial radius in km
    const b = 6356.752; // polar radius in km

    var sq = x => (x*x);
    var sqr = x => Math.sqrt(x);
    var cos = x => Math.cos(x);
    var sin = x => Math.sin(x);
    var radius = lat => sqr((sq(a*a*cos(lat))+sq(b*b*sin(lat)))/(sq(a*cos(lat))+sq(b*sin(lat))));

    lat1 = lat1 * Math.PI / 180;
    lng1 = lng1 * Math.PI / 180;
    lat2 = lat2 * Math.PI / 180;
    lng2 = lng2 * Math.PI / 180;

    var R1 = radius(lat1);
    var x1 = R1*cos(lat1)*cos(lng1);
    var y1 = R1*cos(lat1)*sin(lng1);
    var z1 = R1*sin(lat1);

    var R2 = radius(lat2);
    var x2 = R2*cos(lat2)*cos(lng2);
    var y2 = R2*cos(lat2)*sin(lng2);
    var z2 = R2*sin(lat2);

    return sqr(sq(x1-x2)+sq(y1-y2)+sq(z1-z2));
}

4

このスクリプト(PHP)は、2点間の距離を計算します。

public static function getDistanceOfTwoPoints($source, $dest, $unit='K') {
        $lat1 = $source[0];
        $lon1 = $source[1];
        $lat2 = $dest[0];
        $lon2 = $dest[1];

        $theta = $lon1 - $lon2;
        $dist = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) +  cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($theta));
        $dist = acos($dist);
        $dist = rad2deg($dist);
        $miles = $dist * 60 * 1.1515;
        $unit = strtoupper($unit);

        if ($unit == "K") {
            return ($miles * 1.609344);
        }
        else if ($unit == "M")
        {
            return ($miles * 1.609344 * 1000);
        }
        else if ($unit == "N") {
            return ($miles * 0.8684);
        } 
        else {
            return $miles;
        }
    }

4

Haversine式によるJava実装

double calculateDistance(double latPoint1, double lngPoint1, 
                         double latPoint2, double lngPoint2) {
    if(latPoint1 == latPoint2 && lngPoint1 == lngPoint2) {
        return 0d;
    }

    final double EARTH_RADIUS = 6371.0; //km value;

    //converting to radians
    latPoint1 = Math.toRadians(latPoint1);
    lngPoint1 = Math.toRadians(lngPoint1);
    latPoint2 = Math.toRadians(latPoint2);
    lngPoint2 = Math.toRadians(lngPoint2);

    double distance = Math.pow(Math.sin((latPoint2 - latPoint1) / 2.0), 2) 
            + Math.cos(latPoint1) * Math.cos(latPoint2)
            * Math.pow(Math.sin((lngPoint2 - lngPoint1) / 2.0), 2);
    distance = 2.0 * EARTH_RADIUS * Math.asin(Math.sqrt(distance));

    return distance; //km value
}

3

球体上の2点間の距離を計算するには、大圏計算を行う必要があります

平面までの距離を投影する必要がある場合に、MapToolsでの地図の投影に役立つC / C ++ライブラリがいくつかあります。これを行うには、さまざまな座標系の投影文字列が必要です。

あなたも見つけることがMapWindowポイントを可視化するための便利なツールを。また、そのオープンソースとして、コアオープンソースプロジェクションライブラリのように見えるproj.dllライブラリの使用方法に関する便利なガイドです。


3

これは、Javaに移植された、受け入れられた回答の実装です。

package com.project529.garage.util;


/**
 * Mean radius.
 */
private static double EARTH_RADIUS = 6371;

/**
 * Returns the distance between two sets of latitudes and longitudes in meters.
 * <p/>
 * Based from the following JavaScript SO answer:
 * http://stackoverflow.com/questions/27928/calculate-distance-between-two-latitude-longitude-points-haversine-formula,
 * which is based on https://en.wikipedia.org/wiki/Haversine_formula (error rate: ~0.55%).
 */
public double getDistanceBetween(double lat1, double lon1, double lat2, double lon2) {
    double dLat = toRadians(lat2 - lat1);
    double dLon = toRadians(lon2 - lon1);

    double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
            Math.cos(toRadians(lat1)) * Math.cos(toRadians(lat2)) *
                    Math.sin(dLon / 2) * Math.sin(dLon / 2);
    double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
    double d = EARTH_RADIUS * c;

    return d;
}

public double toRadians(double degrees) {
    return degrees * (Math.PI / 180);
}

2

これがVB.NETの実装です。この実装は、渡したEnum値に基づいて、KMまたはマイルで結果を提供します。

Public Enum DistanceType
    Miles
    KiloMeters
End Enum

Public Structure Position
    Public Latitude As Double
    Public Longitude As Double
End Structure

Public Class Haversine

    Public Function Distance(Pos1 As Position,
                             Pos2 As Position,
                             DistType As DistanceType) As Double

        Dim R As Double = If((DistType = DistanceType.Miles), 3960, 6371)

        Dim dLat As Double = Me.toRadian(Pos2.Latitude - Pos1.Latitude)

        Dim dLon As Double = Me.toRadian(Pos2.Longitude - Pos1.Longitude)

        Dim a As Double = Math.Sin(dLat / 2) * Math.Sin(dLat / 2) + Math.Cos(Me.toRadian(Pos1.Latitude)) * Math.Cos(Me.toRadian(Pos2.Latitude)) * Math.Sin(dLon / 2) * Math.Sin(dLon / 2)

        Dim c As Double = 2 * Math.Asin(Math.Min(1, Math.Sqrt(a)))

        Dim result As Double = R * c

        Return result

    End Function

    Private Function toRadian(val As Double) As Double

        Return (Math.PI / 180) * val

    End Function

End Class

「a」を計算するときに、誤ってMath.Sin(dLat ..)を2回書いたのですか。
Marco Ottina

2

式を簡略化することで、計算を簡略化しました。

ここではRubyです:

include Math
earth_radius_mi = 3959
radians = lambda { |deg| deg * PI / 180 }
coord_radians = lambda { |c| { :lat => radians[c[:lat]], :lng => radians[c[:lng]] } }

# from/to = { :lat => (latitude_in_degrees), :lng => (longitude_in_degrees) }
def haversine_distance(from, to)
  from, to = coord_radians[from], coord_radians[to]
  cosines_product = cos(to[:lat]) * cos(from[:lat]) * cos(from[:lng] - to[:lng])
  sines_product = sin(to[:lat]) * sin(from[:lat])
  return earth_radius_mi * acos(cosines_product + sines_product)
end

2
function getDistanceFromLatLonInKm(lat1,lon1,lat2,lon2,units) {
  var R = 6371; // Radius of the earth in km
  var dLat = deg2rad(lat2-lat1);  // deg2rad below
  var dLon = deg2rad(lon2-lon1); 
  var a = 
    Math.sin(dLat/2) * Math.sin(dLat/2) +
    Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * 
    Math.sin(dLon/2) * Math.sin(dLon/2)
    ; 
  var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 
  var d = R * c; 
  var miles = d / 1.609344; 

if ( units == 'km' ) {  
return d; 
 } else {
return miles;
}}

チャックの解法、マイルにも有効。


2

これは、検索後の小数度による距離の計算のための私のJava実装です。(ウィキペディアからの)世界の平均半径をkmで使用しました。結果のマイルが必要な場合は、ワールド半径をマイルで使用します。

public static double distanceLatLong2(double lat1, double lng1, double lat2, double lng2) 
{
  double earthRadius = 6371.0d; // KM: use mile here if you want mile result

  double dLat = toRadian(lat2 - lat1);
  double dLng = toRadian(lng2 - lng1);

  double a = Math.pow(Math.sin(dLat/2), 2)  + 
          Math.cos(toRadian(lat1)) * Math.cos(toRadian(lat2)) * 
          Math.pow(Math.sin(dLng/2), 2);

  double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));

  return earthRadius * c; // returns result kilometers
}

public static double toRadian(double degrees) 
{
  return (degrees * Math.PI) / 180.0d;
}

2

Mysqlでは、次の関数を使用して、パラメータを使用して渡します POINT(LONG,LAT)

CREATE FUNCTION `distance`(a POINT, b POINT)
 RETURNS double
    DETERMINISTIC
BEGIN

RETURN

GLength( LineString(( PointFromWKB(a)), (PointFromWKB(b)))) * 100000; -- To Make the distance in meters

END;

2
function getDistanceFromLatLonInKm(position1, position2) {
    "use strict";
    var deg2rad = function (deg) { return deg * (Math.PI / 180); },
        R = 6371,
        dLat = deg2rad(position2.lat - position1.lat),
        dLng = deg2rad(position2.lng - position1.lng),
        a = Math.sin(dLat / 2) * Math.sin(dLat / 2)
            + Math.cos(deg2rad(position1.lat))
            * Math.cos(deg2rad(position1.lat))
            * Math.sin(dLng / 2) * Math.sin(dLng / 2),
        c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
    return R * c;
}

console.log(getDistanceFromLatLonInKm(
    {lat: 48.7931459, lng: 1.9483572},
    {lat: 48.827167, lng: 2.2459745}
));

2

これはpostgres sqlの例です(kmで、マイルバージョンの場合、1.609344を0.8684バージョンに置き換えます)

CREATE OR REPLACE FUNCTION public.geodistance(alat float, alng float, blat  

float, blng  float)
  RETURNS float AS
$BODY$
DECLARE
    v_distance float;
BEGIN

    v_distance = asin( sqrt(
            sin(radians(blat-alat)/2)^2 
                + (
                    (sin(radians(blng-alng)/2)^2) *
                    cos(radians(alat)) *
                    cos(radians(blat))
                )
          )
        ) * cast('7926.3352' as float) * cast('1.609344' as float) ;


    RETURN v_distance;
END 
$BODY$
language plpgsql VOLATILE SECURITY DEFINER;
alter function geodistance(alat float, alng float, blat float, blng float)
owner to postgres;

2

Rubyコードに変換された別のコードを次に示します。

include Math
#Note: from/to = [lat, long]

def get_distance_in_km(from, to)
  radians = lambda { |deg| deg * Math.PI / 180 }
  radius = 6371 # Radius of the earth in kilometer
  dLat = radians[to[0]-from[0]]
  dLon = radians[to[1]-from[1]]

  cosines_product = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(radians[from[0]]) * Math.cos(radians[to[1]]) * Math.sin(dLon/2) * Math.sin(dLon/2)

  c = 2 * Math.atan2(Math.sqrt(cosines_product), Math.sqrt(1-cosines_product)) 
  return radius * c # Distance in kilometer
end

1

PHP http://www.geodatasource.com/developers/phpで距離を計算する良い例がここにあります

 function distance($lat1, $lon1, $lat2, $lon2, $unit) {

     $theta = $lon1 - $lon2;
     $dist = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) +  cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($theta));
     $dist = acos($dist);
     $dist = rad2deg($dist);
     $miles = $dist * 60 * 1.1515;
     $unit = strtoupper($unit);

     if ($unit == "K") {
         return ($miles * 1.609344);
     } else if ($unit == "N") {
          return ($miles * 0.8684);
     } else {
          return $miles;
     }
 }
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.