2010-01-09 3 views
4

Я использую базу данных SQLITE для хранения широт и долготы местоположений.Android sqlite сортировать по вычисленному столбцу (расстояние между координатами)

Я хочу, чтобы уметь сортировать результаты на грубом расстоянии от текущего местоположения. У меня уже есть текущее местоположение устройства как двойное (lat, lng), lat и lng в базе данных также удваиваются.

Что я хочу - это запрос, который создаст виртуальный столбец, который я могу отсортировать.

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

float pk = (float) (180/3.14159);
float a1 = (float) (db_lat/pk);
float a2 = (float) (db_lon/pk);
float b1 = (float) (current_lat/pk);
float b2 = (float) (current_lon/pk);
float t1 = FloatMath.cos(a1)*FloatMath.cos(a2)*FloatMath.cos(b1)*FloatMath.cos(b2);
float t2 = FloatMath.cos(a1)*FloatMath.sin(a2)*FloatMath.cos(b1)*FloatMath.sin(b2);
float t3 = FloatMath.sin(a1)*FloatMath.sin(b1);
double tt = Math.acos(t1 + t2 + t3);
double dist = (6366000*tt);

Например, MySQL, можно было бы выбрать (взятой из: www.movable-type.co.uk):

Select Lat, Lon, acos(sin($lat)*sin(radians(Lat)) + cos($lat)*cos(radians(Lat))cos(radians(Lon)-$lon))$R As dist From MyTable ORDER BY dist DESC

в настоящее время я выбрать местоположение с помощью следующей:

public Cursor locationGetAllRows(long groupid) { try { return db.query(LOCATION_DATABASE_TABLE, new String[] { "_id", "lat","lon","groupid"}, "groupid="+groupid, null, null, null, null); } catch (SQLException e) { Log.e("Exception on query: ", e.toString()); return null; } }

ОК, можно ли таким образом использовать базу данных SQLITE? Если не единственный вариант, о котором я могу думать, это добавить лишний столбец, перебирать строки, выполняющие указанную выше функцию в каждой строке, и заполнять дополнительный столбец в строке, а затем сортировать по этому столбцу?

ответ

4

Это не поможет, но для подобных ситуаций серьезно рассмотрите возможность использования rawQuery() вместо query(), поэтому вы можете передать полный SQL-запрос против того, чтобы нарезать его на куски.


Ваша большая проблема в том, что я не вижу, что SQLite имеет тригонометрические функции.

Вы не указали, каким образом вы используете Cursor, которые вы получаете по запросу.Например, если вы ставите Cursor в какой-то CursorAdapter, вы могли бы:

  • преобразовать Cursor в ArrayList<Position>, где Position есть некоторые Java класс можно определить с данными
  • закрыть Cursor, чтобы освободить оперативную память она занимает
  • Рассортируйте ArrayList<Position> с помощью Arrays.sort()
  • обернуть ArrayList<Position> в ArrayAdapter<Position> и использовать то, где вы были с помощью CursorAdapter
+0

Хорошо, поэтому для тестирования я создал ArrayList > и заполнил его всеми требуются детали. Я также создал простой класс, который расширяет объект, ArrayList . Я прокручиваю курсор и помещаю данные, в настоящее время, в оба списка, так как я выполняю расчет расстояний и добавляю это. Как я мог бы выполнить сортировку? Класс: класс locationRowDist extends Объект { Публичный заголовок String; общественный двойной лат; общественный двойной лон; public double dist; } – Scoobler

+0

Если «locationRowDist» - это класс, попробуйте реализовать интерфейс Comparable, а затем используйте Arrays.sort() для его сортировки. – CommonsWare

3

Да, это прекрасно работает.

это может быть сделано в хранимую процедуру так:

http://www.thismuchiknow.co.uk/?p=71 [Distance функция SQLite]

есть также Perst spatial database for android, который отлично, и пространственная база данных SpatiaLite который также является удивительным, что вам можно связать в своем приложении.

w/out используя специализированную библиотеку lib, вы можете приблизиться к расстоянию несколькими способами (вычислить ее так же, как если бы она была плоской (прямоугольной), а затем использовать формулу Хаверсина для сортировки подмножества позже, используйте таблицу поиска, которая аппроксимирует cos , sin и т. д., расположение групп в зонах 5 кв. миль и поиск соседних ячеек до максимума и т. д.)

+3

Техника, которую вы описываете, не применима к Android, которая не может использовать sqlite3_create_fun ие(). – CommonsWare

+0

Да, с большой базой данных было бы полезно использовать собственный sqlite/perst/spaceite вместо встроенного встроенного Android. – jspcal

0

Я только что написал приложение, которое должно сортировать набор координат, основанный на расстоянии. То, что я сделал, это создать массив идентификаторов и рассылок, а затем отсортировать их в Java. Затем я мог найти ближайшие местоположения и выбрать их из базы данных. Конечно, этот подход может не работать для вас в зависимости от того, сколько у вас очков и как вы получаете доступ к базе данных. Это работало отлично для ~ 350 пунктов, в приложении Nando Finder.

Кроме того, я использовал Location.distanceBetween (..) из SDK, чтобы рассчитать расстояния для меня. Я бы надеялся, что этот метод будет реализован на C, чтобы убедиться, что он быстрый, однако, быстрый взгляд на SDK source показывает, что он написан на Java :(

3

В моем приложении BostonBusMap я использовал приближение для ускорения расчета ближайших объектов к точке. Вы можете масштабировать долготу на cos(latitude), а затем просто использовать формулу Пифагора для расчета расстояния сортировки (опускание квадратного маршрута, так как это не обязательно для сравнения). Он работает достаточно хорошо для небольших расстояний.

http://en.wikipedia.org/wiki/Geographical_distance#Spherical_Earth_projected_to_a_plane

Смежные вопросы