Вычислить расстояние между двумя точками непосредственно в SQLite

в моем приложении web / MySQL у меня есть что-то вроде этого, чтобы получить расстояние между двумя точками:

6371 * acos(cos(radians(-19.83996)) * cos(radians(lat)) * cos(radians(-43.94910) - radians(lng)) + sin(radians(-19.83996)) * sin(radians(lat)))

но я тестировал в SQLite, и эти математические функции (acos, cos, radians, sin) не существуют. Есть ли что-то эквивалентное для меня, чтобы вычислить расстояние напрямую в базе данных?

однако у меня есть приложение для iPhone, которое использует этот метод для расчета. Отлично работает, но теперь мне нужно выполнить этот же поиск в базе данных в приложении для Android.

спасибо заранее.

обновление

У меня есть 9000 точек для вычисления расстояния и получения 5 близлежащих местоположений данной точки.

4 ответов


вот что я бы сделал:

возьмите заданную точку. Измерьте a (это произвольное значение, которое нужно уточнить) ~ 2km широкий квадрат вокруг него и возьмите значения для восточной/западной/северной/южной границ.

сделайте запрос для элементов внутри этого квадрата. Это легко, вы просто должны

select * from points where lat between ? and ? and lon between ? and ?

посчитай свой результат. Недостаточно результата (менее 5, очевидно, но я бы сказал, что в два раза больше, чтобы быть уверенным), повторите попытку с большим радиусом. Слишком много (скажем, больше, чем 100), попробуйте еще раз с меньшим радиусом.

Как только у вас будет достаточно, загрузите их, убедитесь, что все 5 элементов, которые вам нужны, находятся не только в квадрате шириной Xkm, но и в круге радиуса Xkm (чтобы избежать потенциального более близкого элемента, не обнаруженного предыдущим приближением).

другой подход

действителен только в том случае, если заданная точка относительно близка к искомой.

измерьте локальное приближение плоской Земли. Близко к вашему точка, вы можете рассмотреть линейную связь между lat, lon и расстоянием. Что позволяет сделать запрос отсортированный по простому исчислению. (умножение и сложение). Опять же, выберите немного больше точек, чтобы сделать правильный расчет после запроса SQLite.


вставьте cos_lat_rad, sin_lat_rad, cos_lon_rad, sin_lon_rad в таблицу

contentValues.put("cos_lat_rad", Math.cos(deg2rad(latitude)));
contentValues.put("sin_lat_rad", Math.sin(deg2rad(latitude)));
contentValues.put("cos_lon_rad", Math.cos(deg2rad(longitude)));
contentValues.put("sin_lon_rad", Math.sin(deg2rad(longitude)));

степень Радиан

public static double deg2rad(double deg) {
    return (deg * Math.PI / 180.0);
}

запрос , расстояние в км

 Cursor c=database.dis(String.valueOf(Math.cos((double) distance / (double) 6380)), Math.cos(deg2rad(latitude)), Math.sin(deg2rad(latitude)), Math.cos(deg2rad(longitude)), Math.sin(deg2rad(longitude)));

запрос

public Cursor dis(String dis, double cos_lat_rad, double sin_lat_rad, double cos_lon_rad, double sin_lon_rad) {

    Cursor cursor = sqLiteDatabase.rawQuery("SELECT * ,(" + sin_lat_rad + "*\"sin_lat_rad\"+" + cos_lat_rad + "*\"cos_lat_rad\"*(" + sin_lon_rad + "*\"sin_lon_rad\"+" + cos_lon_rad + "*\"cos_lon_rad\")) AS \"distance_acos\" FROM parish WHERE ("+sin_lat_rad+" * \"sin_lat_rad\" +"+ cos_lat_rad +"* \"cos_lat_rad\" * (+"+sin_lon_rad +"* \"sin_lon_rad\" + "+cos_lon_rad +"* \"cos_lon_rad\")) >"+dis+ " ORDER BY \"distance_acos\" DESC ", null);
    return cursor;

}

преобразовать distance_acos в km

 if(c.moveToFirst())
        do {
            double distance_acos= c.getDouble(c.getColumnIndex("distance_acos"));
                     String Distance=String.valueOf(Math.acos(distance_acos) * 6380); 
        }while (c.moveToNext());

ответ Ангела не решает проблему для SQLite, поскольку он по-прежнему включает функцию ACOS, которая не существует в SQLite

после тщательного исследования я пришел к выводу, что следует выбрать грубую оценку для использования в SQLite с формулой ниже:

оценка расстояния в км:

SQRT(SQUARE((TO_LAT-FROM_LAT)*110)+
     SQUARE((TO_LONG-FROM_LONG)*COS(TO_LAT)*111)) 

в android у нас есть класс местоположения, нам нужно инициализировать класс местоположения, и в нем у нас есть метод distanceBetween (), который дает расстояние между двумя геопоинтами.

передать этот ссылке