Android sqlite ordenar en la columna calculada (coordina la distancia)

Estoy utilizando una base de datos SQLITE para almacenar latitudes y longitudes de ubicaciones.

Quiero ser capaz de ordenar los resultados por la distancia aproximada de la ubicación actual. Ya tengo la ubicación actual del dispositivo como un doble (lat, lng), el lat y lng en la base de datos también son dobles.

Lo que quiero es una consulta que va a crear una columna virtual que soy capaz de ordenar los resultados por.

Actualmente utilizo una función para mostrar la distancia de un registro seleccionado:

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

Por ejemplo, una selección de MySQL podría ser (tomada de: 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

Actualmente selecciono ubicaciones usando lo siguiente:

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

Aceptar ¿es posible utilizar la base de datos SQLITE de esta manera? Si no es la única opción que puedo pensar es tener una columna extra, iterar a través de las filas que ejecutan la función anterior en cada fila y rellenar una columna extra en la fila, a continuación, la clasificación en esa columna?

Esto no ayudará completamente, pero para situaciones como esta, considere seriamente el uso de rawQuery() lugar de query() , por lo que puede pasar en una instrucción SQL completa frente a tener que cortar en pedazos.


Su mayor problema es que no veo que SQLite tiene funciones trigonométricas.

No indica cómo está utilizando el Cursor que está recuperando de su consulta. Por ejemplo, si está poniendo el Cursor en algún tipo de CursorAdapter , podría:

  • Convierta el Cursor en un ArrayList<Position> , donde Position es una clase Java que define con sus datos
  • Cierre el Cursor , para liberar la memoria RAM que ocupa
  • Arrays.sort() el ArrayList<Position> utilizando Arrays.sort()
  • Envuelva el ArrayList<Position> en un ArrayAdapter<Position> y utilice aquél donde usted había estado usando su CursorAdapter

Sí, eso funciona perfectamente.

Puede convertirse en un procedimiento almacenado de la siguiente manera:

http://www.thismuchiknow.co.uk/?p=71 [Función de la distancia para sqlite]

También hay la base de datos espacial Prest para Android que es excelente, y la base de datos SpatiaLite espacial que también es impresionante, que podría enlazar en su aplicación.

W / out utilizando un lib especializado, se puede aproximar la distancia de algunas maneras (calcularlo como si fuera planar (rectangular) a continuación, utilizar la fórmula de Haversine para clasificar el subconjunto más tarde, utilice una tabla de búsqueda que se aproxima cos, sin, etc , Localizar grupos en zonas de 5 millas cuadradas y buscar celdas vecinas hasta el máximo, etc …)

En mi aplicación BostonBusMap utilicé una aproximación para acelerar el cálculo de objetos más cercanos a un punto. Puede escalar la longitud por cos(latitude) y luego usar la fórmula de Pythagorean para calcular una distancia de clasificación (omitiendo la ruta cuadrada ya que no es necesario para una distancia de comparación). Funciona razonablemente bien para distancias pequeñas.

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

Acabo de escribir una aplicación que necesita ordenar un conjunto de coordenadas basadas en la distancia. Lo que hice fue crear una matriz de ID y Distancias y luego ordenarlas dentro de Java. Entonces podría encontrar los lugares más cercanos y seleccionarlos de la base de datos. Por supuesto, este enfoque puede no funcionar para usted dependiendo de cuántos puntos tiene y cómo acceder a la base de datos. Esto funcionó bien para ~ 350 puntos, en mi aplicación Nando Finder.

Además utilicé Location.distanceBetween (..) desde el SDK para calcular las distancias para mí. Espero que este método se implementará en C para asegurar que es rápido, sin embargo, un rápido vistazo a la fuente SDK muestra que está escrito en Java :(.

  • Cómo comprobar si ya existe un valor en la base de datos en Android
  • Android - Ruby on Rails - MySQL
  • Android: Incrementar el campo DB a través de ContentValues
  • Cómo evitar objetos duplicados en la base de datos DB4o
  • Alcanzó el tamaño MAX para la caché de instrucciones compiladas-sql para la base de datos
  • ¿Cómo portar un MS Access existente a SQLite para su uso con el desarrollo de aplicaciones para Android?
  • Base de datos en el estudio android
  • Recuperar una lista de todas las tablas de la base de datos
  • Cierre del cursor en onPostExecute no produce nada
  • Adb shell setprop log.tag.SQLiteStatements VERBOSE no hace nada?
  • ¿Qué es lo mejor: 1 tabla por registro o 1 tabla con todos los registros vinculados con claves foráneas?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.