2つの地理的ポイント間の距離を取得する


108

ユーザーのいる場所に最も近い場所を確認するアプリを作りたい。ユーザーの場所を簡単に取得でき、緯度と経度のある場所のリストがすでにあります。

現在のユーザーの場所に対してリストの最も近い場所を知るための最良の方法は何でしょうか。

Google APIで何も見つかりませんでした。

回答:


164
Location loc1 = new Location("");
loc1.setLatitude(lat1);
loc1.setLongitude(lon1);

Location loc2 = new Location("");
loc2.setLatitude(lat2);
loc2.setLongitude(lon2);

float distanceInMeters = loc1.distanceTo(loc2);

リファレンス:http : //developer.android.com/reference/android/location/Location.html#distanceTo(android.location.Location)


2
Locationオブジェクトを使用しているので、おそらくLocation.DistanceBetween()を使用するよりも遅くなりますが、私の目的には非常によく機能します。
ZoltanF 2014

ロケーションimport android.location.Location;またはどのクラスをインポートする必要があるか
Pranav MS

@PranavMSはいandroid.location.Location;
AndrewS 2018年

私はdistanceToが最初の点と最後の点の間の距離を直腸線で返すと思うので、a点からb点への他の方向をとる場合、パスが異なるため、distanceBetweenが参加するとき、それは決して推定されません作成された点間の各距離を保存してから、最終的なパラメータresults []を使用して正しい距離を取得します。
ガストンSaillén

122

http://developer.android.com/reference/android/location/Location.html

distanceToまたはdistanceBetweenを調べます。緯度と経度からLocationオブジェクトを作成できます。

Location location = new Location("");
location.setLatitude(lat);
location.setLongitude(lon);

37
distanceBetweenは、2セットの緯度
経度の

4
私は彼がdistanceTo方法のためにそれを意味したと確信しています。
ラフ2013

これは非常に便利ですが、コンストラクターの文字列プロバイダーは何ですか?
miss.serena 2013年

33

近似解(正距円筒図法に基づく)、はるかに高速(1つのトリガーと1つの平方根しか必要ありません)。

この近似は、ポイントが離れすぎていない場合に関係します。それは意志オーバー推定常に本当の半正矢の距離に比べて。たとえば、2点間のデルタ緯度または経度が10進4度を超えない場合、実際の距離に追加されるのは0.05382%以下です。です。

標準の式(Haversine)は正確な式です(つまり、地球上の経度/緯度の任意のカップルで機能します)が、7つの三角関数と2つの平方根を必要とするため、はるかに遅くなります。いくつかの点が離れすぎておらず、絶対精度が最も重要でない場合は、この近似バージョン(正距円筒)を使用できます。これは、1つの三角関数と1つの平方根しか使用しないため、はるかに高速です。

// Approximate Equirectangular -- works if (lat1,lon1) ~ (lat2,lon2)
int R = 6371; // km
double x = (lon2 - lon1) * Math.cos((lat1 + lat2) / 2);
double y = (lat2 - lat1);
double distance = Math.sqrt(x * x + y * y) * R;

次のいずれかにより、これをさらに最適化できます。

  1. 平方根を削除する距離を単純に比較する場合はます(その場合、両方の平方距離を比較します)。
  2. 1つのマスターポイントから他の多くのポイントまでの距離を計算する場合は、コサインを因数分解します(その場合、マスターポイントを中心に正距円筒図法を行うため、すべての比較でコサインを一度計算できます)。

詳細については、以下を参照してください。 http //www.movable-type.co.uk/scripts/latlong.htmlをください。

いくつかの言語でのHaversine式の優れたリファレンス実装がhttp://www.codecodex.com/wiki/Calculate_Distance_Between_Two_Points_on_a_Globeにあります。


偉人ありがとう。しかし、境界内の1つの場所の周りに一連の場所を取得する必要がある場合、whileループを使用して、検索された場所に対して各場所をチェックし、境界内にある場所のみを保持する必要がありますか?
themhz

できますが、これはのブルートフォースアプローチですO(n)。以下のためにO(1)溶液、厳密解を計算する前に潜在的なマッチをトリミングする2D空間インデックスを使用します。この質問の範囲は
外し

これは、可能な最適化の非常に素晴らしいラップアップです。thx!まさに私が探していたもの
Sam Vloeberghs

私はちょうどこの式は長い距離のために動作するかどうかを知りたいと思った
Sandipan Majhi

答えをご覧ください。ただし、いいえ。距離が長い場合は機能しません。2点間の距離が大きいほど、正確なHaversine式に比べて誤差が大きくなります。
LaurentGrégoire19年

11

使用できる方法はいくつかありますが、ユーザーの高度と他のポイントの高度を知っているかどうかを知るために、最初に知っておくべき最善の方法を決定するには、

求める精度のレベルに応じて、HaversineまたはVincentyのいずれかの式を調べることができます...

これらのページでは、数式について詳しく説明し、数学的にあまり傾いていない場合は、スクリプトでそれらを実装する方法についても説明します。

Haversine Formula:http : //www.movable-type.co.uk/scripts/latlong.html

Vincenty Formula:http : //www.movable-type.co.uk/scripts/latlong-vincenty.html

数式のいずれかの意味に問題がある場合は、コメントしてください。答えるように最善を尽くします:)


4

LatLng間の距離を取得するには2つの方法があります。

public static void distanceBetween (double startLatitude, double startLongitude, double endLatitude, double endLongitude, float[] results)

これを見て

そして二番目

public float distanceTo (Location dest) プラビーンが答えたように。


3
private float getDistance(double lat1, double lon1, double lat2, double lon2) {
        float[] distance = new float[2];
        Location.distanceBetween(lat1, lon1, lat2, lon2, distance);
        return distance[0];
    }

1

次のメソッドを使用して、緯度と経度を渡し、距離をメートル単位で取得します。

private static double distance_in_meter(final double lat1, final double lon1, final double lat2, final double lon2) {
    double R = 6371000f; // Radius of the earth in m
    double dLat = (lat1 - lat2) * Math.PI / 180f;
    double dLon = (lon1 - lon2) * Math.PI / 180f;
    double a = Math.sin(dLat/2) * Math.sin(dLat/2) +
            Math.cos(latlong1.latitude * Math.PI / 180f) * Math.cos(latlong2.latitude * Math.PI / 180f) *
                    Math.sin(dLon/2) * Math.sin(dLon/2);
    double c = 2f * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
    double d = R * c;
    return d;
}

2
latlong1とlatlong2は定義されていません
Boy

1
latlong1&latlong2とは何ですか?
Nisal Malinda Livera 2017

0

Google Map APIを使用して距離と時間を取得できます Google Map APIます

ダウンロードしたJSONをこのメソッドに渡すだけで、2つの緯度経度間の距離と時間をリアルタイムで取得できます

void parseJSONForDurationAndKMS(String json) throws JSONException {

    Log.d(TAG, "called parseJSONForDurationAndKMS");
    JSONObject jsonObject = new JSONObject(json);
    String distance;
    String duration;
    distance = jsonObject.getJSONArray("routes").getJSONObject(0).getJSONArray("legs").getJSONObject(0).getJSONObject("distance").getString("text");
    duration = jsonObject.getJSONArray("routes").getJSONObject(0).getJSONArray("legs").getJSONObject(0).getJSONObject("duration").getString("text");

    Log.d(TAG, "distance : " + distance);
    Log.d(TAG, "duration : " + duration);

    distanceBWLats.setText("Distance : " + distance + "\n" + "Duration : " + duration);


}

0

a =sin²(Δφ/ 2)+ cosφ1⋅cosφ2⋅sin²(Δλ/ 2)

c = 2⋅atan2(√a、√(1-a))

距離= R⋅c

ここで、φは緯度、λは経度、Rは地球の半径(平均半径= 6,371km)です。

トリガー関数に渡すには、角度をラジアンにする必要があることに注意してください。

fun distanceInMeter(firstLocation: Location, secondLocation: Location): Double {
    val earthRadius = 6371000.0
    val deltaLatitudeDegree = (firstLocation.latitude - secondLocation.latitude) * Math.PI / 180f
    val deltaLongitudeDegree = (firstLocation.longitude - secondLocation.longitude) * Math.PI / 180f
    val a = sin(deltaLatitudeDegree / 2).pow(2) +
            cos(firstLocation.latitude * Math.PI / 180f) * cos(secondLocation.latitude * Math.PI / 180f) *
            sin(deltaLongitudeDegree / 2).pow(2)
    val c = 2f * atan2(sqrt(a), sqrt(1 - a))
    return earthRadius * c
}


data class Location(val latitude: Double, val longitude: Double)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.