Dapatkan jarak antara dua titik geografis

108

Saya ingin membuat aplikasi yang memeriksa tempat terdekat di mana pengguna berada. Saya dapat dengan mudah mendapatkan lokasi pengguna dan saya sudah memiliki daftar tempat dengan lintang dan bujur.

Apa cara terbaik untuk mengetahui tempat terdekat dari daftar dengan lokasi pengguna saat ini.

Saya tidak dapat menemukan apa pun di Google API.

Chmouel Boudjnah
sumber

Jawaban:

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);

Referensi: http://developer.android.com/reference/android/location/Location.html#distanceTo(android.location.Location)

praveen
sumber
2
Mungkin lebih lambat daripada menggunakan Location.DistanceBetween () karena menggunakan objek Lokasi tetapi berfungsi untuk tujuan saya dengan sangat baik.
ZoltanF
Kelas mana yang harus saya impor untuk Lokasi import android.location.Location;atau yang
Pranav MS
@PranavMS ya android.location.Location;
AndrewS
Saya pikir distanceTo mengembalikan jarak antara titik pertama dan terakhir tetapi dalam garis rektal, jadi jika Anda mengambil arah lain dari titik a ke b itu tidak akan pernah diakumulasikan karena jalurnya berbeda, saat itulah jarakBetween bergabung, Anda bisa simpan setiap jarak antara titik-titik yang telah dibuat dan kemudian dengan hasil parameter terakhir [] dapatkan jarak yang benar.
Gastón Saillén
122

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

Lihatlah ke distanceTo atau distanceBetween. Anda dapat membuat objek Lokasi dari lintang dan bujur:

Location location = new Location("");
location.setLatitude(lat);
location.setLongitude(lon);
haseman
sumber
37
distanceBetween adalah metode statis yang mengambil 2 set titik lintang, jadi Anda bahkan tidak perlu membuat instance objek Lokasi =)
Stan Kurdziel
4
Aku yakin maksudnya itu untuk distanceTometode.
laph
Ini bagus dan sangat membantu, tetapi untuk apa penyedia String di konstruktor?
miss.serena
33

Solusi yang diperkirakan (berdasarkan proyeksi persegi panjang), jauh lebih cepat (hanya membutuhkan 1 trigonometri dan 1 akar kuadrat).

Perkiraan ini relevan jika poin Anda tidak terlalu berjauhan. Ini akan selalu melebihi perkiraan dibandingkan dengan jarak haversine yang sebenarnya. Misalnya, jarak tidak lebih dari 0,05382% akan dijumlahkan jika garis lintang atau bujur delta antara dua titik Anda tidak melebihi 4 derajat desimal .

Rumus standar (Haversine) adalah yang tepat (yaitu, rumus ini berfungsi untuk beberapa bujur / lintang di bumi) tetapi jauh lebih lambat karena dibutuhkan 7 trigonometri dan 2 akar kuadrat. Jika pasangan titik Anda tidak terlalu jauh, dan ketepatan absolut tidak terpenting, Anda dapat menggunakan versi perkiraan ini (Equirectangular), yang jauh lebih cepat karena hanya menggunakan satu trigonometri dan satu akar kuadrat.

// 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;

Anda dapat mengoptimalkan ini lebih lanjut dengan:

  1. Menghapus akar kuadrat jika Anda hanya membandingkan jarak dengan yang lain (dalam hal ini bandingkan kedua jarak kuadrat);
  2. Memfaktorkan kosinus jika Anda menghitung jarak dari satu titik master ke banyak titik lainnya (dalam hal ini Anda melakukan proyeksi persegi panjang yang berpusat pada titik master, sehingga Anda dapat menghitung cosinus sekali untuk semua perbandingan).

Untuk info lebih lanjut lihat: http://www.movable-type.co.uk/scripts/latlong.html

Ada implementasi referensi yang bagus dari formula Haversine dalam beberapa bahasa di: http://www.codecodex.com/wiki/Calculate_Distance_Between_Two_Points_on_a_Globe

Laurent Grégoire
sumber
pria hebat, terima kasih. Tetapi jika saya perlu mendapatkan satu set lokasi di sekitar satu lokasi di perimeter, haruskah saya menggunakan loop sementara untuk memeriksa setiap lokasi terhadap lokasi yang dicari dan hanya menyimpan yang ada di perimeter?
themhz
Anda bisa, tapi itu pendekatan kekerasan O(n). Sebagai O(1)solusi, gunakan indeks spasial 2D untuk memangkas potensi kecocokan sebelum menghitung solusi yang tepat. Kami meninggalkan ruang lingkup pertanyaan ini :)
Laurent Grégoire
ini adalah ringkasan yang sangat bagus dari kemungkinan optimasi yang bagus .. thx! Persis dengan apa yang saya cari
Sam Vloeberghs
Saya hanya ingin tahu apakah rumus ini berfungsi untuk jarak yang jauh
Sandipan Majhi
Lihat jawabannya, tetapi singkatnya: tidak , ini tidak berfungsi untuk jarak yang jauh. Semakin besar jarak antara dua titik, semakin besar kesalahan dibandingkan dengan formulanya Haversine yang tepat .
Laurent Grégoire
11

Ada beberapa metode yang dapat Anda gunakan, tetapi untuk menentukan mana yang terbaik, pertama-tama kita perlu mengetahui apakah Anda mengetahui ketinggian pengguna, serta ketinggian titik lainnya?

Bergantung pada tingkat akurasi yang Anda kejar, Anda dapat melihat rumus Haversine atau Vincenty ...

Halaman-halaman ini merinci rumus, dan, bagi yang kurang tertarik secara matematis juga memberikan penjelasan tentang bagaimana menerapkannya dalam skrip!

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

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

Jika Anda memiliki masalah dengan makna apa pun dalam rumus, cukup beri komentar dan saya akan melakukan yang terbaik untuk menjawabnya :)

Dwaine Bailey
sumber
4

Ada dua cara untuk mendapatkan jarak antara LatLng.

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

Lihat ini

dan kedua

public float distanceTo (Location dest) seperti yang dijawab oleh praveen.

Zar E Ahmer
sumber
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];
    }
Levon Petrosyan
sumber
1

Cukup gunakan metode berikut, berikan garis lintang dan panjang dan dapatkan jarak dalam meter:

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;
}
farhad.kargaran
sumber
2
latlong1 dan latlong2 tidak ditentukan
Boy
1
apa itu latlong1 & latlong2?
Nisal Malinda Livera
0

Anda bisa mendapatkan jarak dan waktu menggunakan Google Map API Google Map API

cukup lewati JSON yang diunduh ke metode ini Anda akan mendapatkan Jarak dan Waktu waktu nyata antara dua latlong

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);


}
Sai Gopi Me
sumber
0

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

c = 2 ⋅ atan2 (√a, √ (1 − a))

jarak = R ⋅ c

di mana latitude adalah lintang, λ adalah bujur, R adalah jari-jari bumi (radius rata-rata = 6.371km);

perhatikan bahwa sudut harus dalam radian agar dapat dialihkan ke fungsi trigonometri!

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)
Kourosh
sumber