Сортировать список точек lon \ lat, начать с ближайшего - PullRequest
8 голосов
/ 22 марта 2011

У меня есть местоположение из GPS (lon_base, lat_base).У меня есть список мест (lon1, lat1 | lon2, lat2 | lon3, lat3 ...) Этот список очень длинный и существует по всему миру.

Мои вопросы: 1. Как я могу получить отэтот список только lon \ lat, которые находятся в 1 миле от моего lon_base \ lat_base?2. Как мне отсортировать их от ближайшего к дальнему?

Заранее спасибо!

Ответы [ 5 ]

16 голосов
/ 03 июня 2014
public static List<Location> sortLocations(List<Location> locations, final double myLatitude,final double myLongitude) {
    Comparator comp = new Comparator<Location>() {
        @Override
        public int compare(Location o, Location o2) {
            float[] result1 = new float[3];
            android.location.Location.distanceBetween(myLatitude, myLongitude, o.Lat, o.Long, result1);
            Float distance1 = result1[0];

            float[] result2 = new float[3];
            android.location.Location.distanceBetween(myLatitude, myLongitude, o2.Lat, o2.Long, result2);
            Float distance2 = result2[0];

            return distance1.compareTo(distance2);
        }
    };


    Collections.sort(locations, comp);
    return locations;
}

Где List of Locations - это список, содержащий ваш собственный класс Location, а не android.location.Location.

6 голосов
/ 22 марта 2011

Вы можете использовать расстояние по большому кругу , чтобы вычислить расстояние между двумя точками, для которых вам известны координаты широты и долготы. формулы довольно легко кодировать:

static double distance(double fromLat, double fromLon, double toLat, double toLon) {
    double radius = 6378137;   // approximate Earth radius, *in meters*
    double deltaLat = toLat - fromLat;
    double deltaLon = toLon - fromLon;
    double angle = 2 * Math.asin( Math.sqrt(
        Math.pow(Math.sin(deltaLat/2), 2) + 
        Math.cos(fromLat) * Math.cos(toLat) * 
        Math.pow(Math.sin(deltaLon/2), 2) ) );
    return radius * angle;
}
3 голосов
/ 22 марта 2011

Вы хотите определить свой собственный Comparator, который, в общем, выглядит примерно так:

LonLat myHouse = /* whatever */ ;
Comparable comp = new Comparable () {
    LonLat a;
    int compareTo (Object b) {
        int aDist = calcDistance(a, myHouse) ;
        int bDist = calcDistance(b, myHouse) ;
        return aDist - bDist;
    }
};
myLonLatList.sort(lonLatList, comp);

, где calcDistance() просто вычисляет расстояние между двумя точками.Если вы работаете на Android, я думаю, у Google Maps есть функция где-то в их API, которая сделает это за вас.

EDIT : вам нужно, чтобы ваша функция calcDistance() выгляделанапример distance функция ChrisJ

1013 * -tjw
1 голос
/ 22 марта 2011

Вы можете использовать приближение followig (поскольку 1 миля намного меньше радиуса Земли), чтобы вычислить расстояния от вашей базы:

dx = cos(phi_base) * (theta - theta_base)
dy = phi - phi_base

dist = sqrt(dx*dx+dy*dy) 

с: phi = широтой и theta= долгота

Результат в единицах 60 морских миль, если theta и phi указаны в градусах.Результаты будут совершенно неверными для точек, которые имеют широту, которая сильно отличается от вашей базовой широты, но это не имеет значения, если вы просто хотите знать, какие точки находятся в 1 миле от вашей базы.

ДляДля большинства языков программирования вам нужно преобразовать phi_base в радианы (умножить на pi / 180), чтобы использовать его для cos().

(Внимание: вы должны проявлять особую осторожность, если ваша базовая долгота очень близка к 180 ° или -180 °, но, вероятно, это не так :-)

Используйте рассчитанные расстоянияв качестве ключа сортировки для сортировки ваших очков.

Если вам нужно быть более точным (например, если вы хотите знать все точки, которые находятся примерно в 2000 милях от вашего дома), чем вы должны использовать формулу для Great Circle Distance для вычисления точного расстояния двух точек на сфере.

0 голосов
/ 02 ноября 2011

По этой ссылке я сделал метод работы.Ответ выше был неправильным, потому что он не переводит градусы широты / долготы в радианы.

    private double getDistance(double fromLat, double fromLon, double toLat, double toLon){
        double radius = 6371;   // Earth radius in km
        double deltaLat = Math.toRadians(toLat - fromLat);
        double deltaLon = Math.toRadians(toLon - fromLon);
        double lat1 = Math.toRadians(fromLat);
        double lat2 = Math.toRadians(toLat);
        double aVal = Math.sin(deltaLat/2) * Math.sin(deltaLat/2) +
            Math.sin(deltaLon/2) * Math.sin(deltaLon/2) * Math.cos(lat1) * Math.cos(lat2);
        double cVal = 2*Math.atan2(Math.sqrt(aVal), Math.sqrt(1-aVal));  

        double distance = radius*cVal;
        Log.d("distance","radius * angle = " +distance);
        return distance;
    }
...