Nhận khoảng cách giữa hai điểm địa lý


108

Tôi muốn tạo một ứng dụng kiểm tra nơi gần nhất mà người dùng đang ở. Tôi có thể dễ dàng lấy vị trí của người dùng và tôi đã có danh sách các địa điểm với vĩ độ và kinh độ.

Cách tốt nhất để biết vị trí gần nhất của danh sách so với vị trí người dùng hiện tại là gì.

Tôi không thể tìm thấy bất kỳ thứ gì trong Google API.

Câu trả lời:


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

Tham khảo: http://developer.android.com/reference/android/location/Location.html#distanceTo(android.location.Location)


2
Có lẽ chậm hơn so với việc sử dụng Location.DistanceBetween () vì nó đang sử dụng các đối tượng Location nhưng hoạt động cho mục đích của tôi rất tốt.
ZoltanF

Tôi phải nhập lớp nào cho Vị trí import android.location.Location;hoặc lớp nào
Pranav MS

@PranavMS có android.location.Location;
AndrewS

Tôi nghĩ rằng khoảng cách Để trả về khoảng cách giữa điểm đầu tiên và điểm cuối cùng nhưng trong một đường trực tràng, vì vậy nếu bạn thực hiện bất kỳ hướng nào khác từ điểm a đến b, nó sẽ không bao giờ được đo chính xác vì đường dẫn khác nhau, tức là khi khoảng cáchBet giữa tham gia vào, bạn có thể lưu từng khoảng cách giữa các điểm được ký hiệu đã tạo và sau đó với kết quả tham số cuối cùng [] nhận được khoảng cách chính xác.
Gastón Saillén

122

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

Nhìn vào khoảng cáchTo hoặc khoảng cáchBet giữa. Bạn có thể tạo đối tượng Vị trí từ vĩ độ và kinh độ:

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

37
distanceBetween là một phương pháp tĩnh mà có 2 bộ điểm dài lat, vì vậy bạn thậm chí không cần phải tạo một đối tượng Location =)
Stan Kurdziel

4
Tôi chắc chắn rằng anh ấy có ý đó cho distanceTophương pháp.
laph

Điều này thật tuyệt vời và cực kỳ hữu ích, nhưng nhà cung cấp chuỗi để làm gì trong trình tạo?
miss.serena

33

Một giải pháp gần đúng (dựa trên phép chiếu hình tam giác đều), nhanh hơn nhiều (chỉ cần 1 trig và 1 căn bậc hai).

Sự gần đúng này có liên quan nếu các điểm của bạn không quá xa nhau. Nó sẽ luôn ước tính quá mức so với khoảng cách hasrsine thực. Ví dụ: nó sẽ thêm không quá 0,05382% vào khoảng cách thực nếu vĩ độ hoặc kinh độ đồng bằng giữa hai điểm của bạn không vượt quá 4 độ thập phân .

Công thức chuẩn (Haversine) là công thức chính xác (nghĩa là nó hoạt động với bất kỳ cặp kinh độ / vĩ độ nào trên trái đất) nhưng chậm hơn nhiều vì nó cần 7 lượng giác và 2 căn bậc hai. Nếu hai điểm của bạn không quá xa nhau và độ chính xác tuyệt đối không phải là tối quan trọng, bạn có thể sử dụng phiên bản gần đúng này (Hình chữ nhật tương đương), nhanh hơn nhiều vì nó chỉ sử dụng một lượng giác và một căn bậc hai.

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

Bạn có thể tối ưu hóa điều này hơn nữa bằng cách:

  1. Loại bỏ căn bậc hai nếu bạn chỉ đơn giản so sánh khoảng cách với một khoảng cách khác (trong trường hợp đó so sánh cả hai khoảng cách bình phương);
  2. Tính cosin nếu bạn tính khoảng cách từ một điểm chính đến nhiều điểm khác (trong trường hợp đó, bạn thực hiện phép chiếu hình tam giác có tâm ở điểm chính, vì vậy bạn có thể tính cosin một lần cho tất cả các phép so sánh).

Để biết thêm thông tin, hãy xem: http://www.movable-type.co.uk/scripts/latlong.html

Có một triển khai tham chiếu tuyệt vời của công thức Haversine bằng một số ngôn ngữ tại: http://www.codecodex.com/wiki/Calculate_Distance_Between_Two_Points_on_a_Globe


người đàn ông tuyệt vời thanx. Nhưng nếu tôi cần lấy một tập hợp các vị trí xung quanh một vị trí trong chu vi, tôi có nên sử dụng vòng lặp while để kiểm tra từng vị trí so với vị trí đã tìm kiếm và chỉ giữ lại những vị trí nằm trong chu vi không?
themhz 27/12/12

Bạn có thể, nhưng đó là một cách tiếp cận vũ phu trong O(n). Đối với một O(1)giải pháp, hãy sử dụng chỉ mục không gian 2D để cắt các kết quả phù hợp tiềm năng trước khi tính toán giải pháp chính xác. Chúng tôi đang rời khỏi phạm vi của câu hỏi này :)
Laurent Grégoire

đây là một tập hợp rất tốt về các tối ưu hóa tốt có thể có .. thx! Excactly những gì tôi đang tìm kiếm
Sam Vloeberghs

Tôi chỉ muốn biết liệu công thức này có hoạt động với những khoảng cách lớn hay không
Sandipan Majhi

Hãy xem câu trả lời, nhưng tóm lại: không , nó không hoạt động với khoảng cách lớn. Khoảng cách giữa hai điểm càng lớn thì sai số so với công thức Haversine chính xác càng lớn.
Laurent Grégoire

11

Có một số phương pháp bạn có thể sử dụng, nhưng để xác định phương pháp nào là tốt nhất, trước tiên chúng ta cần biết liệu bạn có biết về độ cao của người dùng cũng như độ cao của các điểm khác không?

Tùy thuộc vào mức độ chính xác của bạn, bạn có thể xem xét công thức Haversine hoặc Vincenty ...

Các trang này trình bày chi tiết các công thức và, đối với các công thức ít nghiêng về mặt toán học hơn, cũng cung cấp giải thích về cách triển khai chúng trong script!

Công thức Haversine: http://www.movable-type.co.uk/scripts/latlong.html

Công thức Vincenty: http://www.movable-type.co.uk/scripts/latlong-vincenty.html

Nếu bạn có bất kỳ vấn đề nào với bất kỳ nghĩa nào trong các công thức, chỉ cần bình luận và tôi sẽ cố gắng hết sức để giải đáp chúng :)


4

Có hai cách để xác định khoảng cách giữa LatLng.

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

Xem này

và thứ hai

public float distanceTo (Location dest) như được trả lời bởi praveen.


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

Chỉ cần sử dụng phương pháp sau, vượt qua nó vĩ độ và dài và nhận được khoảng cách bằng mét:

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 và latlong2 không được xác định
Boy

1
latlong1 & latlong2 là gì?
Nisal Malinda Livera 22/09/17

0

bạn có thể biết được khoảng cách và thời gian bằng cách sử dụng Google Map API Google Map API

chỉ cần chuyển JSON đã tải xuống cho phương pháp này, bạn sẽ nhận được thời gian thực Khoảng cách và Thời gian giữa hai thời gian

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

khoảng cách = R ⋅ c

trong đó φ là vĩ độ, λ là kinh độ, R là bán kính trái đất (bán kính trung bình = 6.371km);

lưu ý rằng các góc cần phải tính bằng radian để chuyển đến hàm trig!

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)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.