두 지리적 지점 사이의 거리 가져 오기


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.DistanceBetween ()을 사용하는 것보다 느리지 만 Location 객체를 사용하고 있지만 내 목적에 아주 잘 작동합니다.
ZoltanF

나는 위치에 대한 수입을 가지고있는 클래스 import android.location.Location;있는 나
PRANAV MS

@PranavMS 예 android.location.Location;
AndrewS

나는 distanceTo가 첫 번째 지점과 마지막 지점 사이의 거리를 반환하지만 직장 라인에 있다고 생각하므로 a 지점에서 b 지점까지 다른 방향을 취하면 경로가 다르기 때문에 절대로 계산되지 않을 것입니다. 생성 된 점 사이의 각 거리를 저장 한 다음 최종 매개 변수 결과 []로 정확한 거리를 얻습니다.
Gastón Saillén 2018

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 개 세트를 취하는 정적 방법입니다 =)
스탠 Kurdziel

4
나는 그가 distanceTo방법 을 의미한다고 확신 합니다.
laph

이것은 훌륭하고 매우 유용하지만 생성자에서 String 공급자는 무엇입니까?
miss.serena 2013 년

33

정방형 투영을 기반으로 한 근사 솔루션, 훨씬 빠릅니다 (1 삼각근과 1 제곱근 만 필요).

이 근사는 포인트가 너무 멀리 떨어져 있지 않은 경우 관련이 있습니다. 그것은 것입니다 항상 이상 견적 실제 하버 사인 거리에 비교했다. 예를 들어 두 지점 사이의 델타 위도 또는 경도가 10 진수 4도를 초과하지 않는 경우 실제 거리에 0.05382 % 이하 를 추가 합니다 .

표준 공식 (Haversine)은 정확한 공식 ( 즉, 지구상의 임의의 경도 / 위도에 대해 작동 함)이지만 7 삼각법과 2 제곱근이 필요하므로 훨씬 느립니다 . 두 개의 점이 너무 멀리 떨어져 있지 않고 절대 정밀도가 가장 중요하지 않은 경우이 근사 버전 (Equirectangular)을 사용할 수 있습니다. 이것은 삼각법과 제곱근을 하나만 사용하므로 훨씬 빠릅니다.

// 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. 한 마스터 포인트에서 다른 많은 포인트까지의 거리를 계산하는 경우 코사인을 분해 합니다 (이 경우 마스터 포인트를 중심으로 정방형 투영을 수행하므로 모든 비교에 대해 코사인을 한 번 계산할 수 있음).

자세한 내용은 http://www.movable-type.co.uk/scripts/latlong.html을 참조하십시오.

http://www.codecodex.com/wiki/Calculate_Distance_Between_Two_Points_on_a_Globe 에 여러 언어로 된 Haversine 공식의 멋진 참조 구현이 있습니다 .


위대한 사람 고맙습니다. 그러나 경계에서 한 위치 주변의 위치 집합을 가져와야하는 경우 while 루프를 사용하여 검색된 위치와 비교하여 각 위치를 확인하고 경계에있는 위치 만 유지해야합니까?
themhz dec.

당신은 할 수 있지만, 그것은 O(n). A에 대한 O(1)해결책, 정확한 솔루션을 계산하기 전에 잠재적 인 일치를 손질하는 2 차원 공간 인덱스를 사용합니다. 우리는 :)이 질문의 범위를 떠난다
로랑 그레 구 아르

이것은 가능한 좋은 최적화의 아주 멋진 요약입니다 .. thx! Excactly 내가 찾던
샘 Vloeberghs

이 공식은 먼 거리를 위해 작동하는 경우 난 그냥 알고 싶어
Sandipan Majhi

대답을 참조하십시오. 간단히 말해서 아니요 , 먼 거리에서는 작동하지 않습니다. 두 점 사이의 거리가 멀수록 정확한 Haversine 공식에 비해 오차가 더 큽니다.
로랑 그레 구 아르

11

사용할 수있는 몇 가지 방법이 있지만 가장 좋은 방법을 결정하려면 먼저 사용자의 고도와 다른 지점의 고도를 알고 있는지 알아야합니다.

추구하는 정확도 수준에 따라 Haversine 또는 Vincenty 공식을 살펴볼 수 있습니다.

이 페이지는 공식을 자세히 설명하고 수학적으로 덜 기울이는 사람들을 위해 스크립트로 구현하는 방법에 대한 설명도 제공합니다!

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

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

수식의 의미에 문제가있는 경우 의견 만 남겨 주시면 최선을 다해 답변 해 드리겠습니다. :)


4

LatLng 간의 거리를 얻는 방법에는 두 가지가 있습니다.

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

이것 좀 봐

그리고 두 번째

public float distanceTo (Location dest) 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

다음 방법을 사용하여 위도와 경도를 전달하고 미터 단위로 거리를 얻으십시오.

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

0

Google Map API Google Map API를 사용하여 거리와 시간을 얻을 수 있습니다.

다운로드 한 JSON 을이 방법으로 전달하면 두 개의 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);


}

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.