Android sqlite sort on calculated column (co-ordinates distance)

I am using an SQLITE database to store latitudes and longitudes of locations.

I want to be able to sort the results by rough distance from the current location. I already have the current location of the device as a double (lat, lng), the lat and lng in the database are also doubles.

What I want is a query that will create a virtual column that I am able to sort the results by.

I currently use a function to show the distance for a selected record:

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

For example, a MySQL select could be (taken from:

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

Currently I select locations using the following:

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

OK so is it possible to use the SQLITE database in this way? If not the only option I can think of is to have an extra column, iterate through the rows running the above function on each row and filling out an extra column on the row, then sorting on that column?

Asked by: Patrick658 | Posted: 25-01-2022

Answer 1

This won't completely help, but for situations like this, seriously consider using rawQuery() instead of query(), so you can pass in a full SQL statement vs. having to chop it into pieces.

Your bigger problem is that I don't see that SQLite has trigonometric functions.

You do not indicate how you are using the Cursor you are getting back from your query. For example, if you are putting the Cursor into some sort of CursorAdapter, you could:

  • convert the Cursor into an ArrayList<Position>, where Position is some Java class you define with your data
  • close the Cursor, to release the RAM it takes up
  • sort the ArrayList<Position> using Arrays.sort()
  • wrap the ArrayList<Position> in an ArrayAdapter<Position> and use that where you had been using your CursorAdapter

Answered by: Lyndon148 | Posted: 26-02-2022

Answer 2

yeah, that works perfectly.

it can be made into a stored procedure like so: [Distance function for sqlite]

there's also the Perst spatial database for android which is excellent, and the SpatiaLite spatial database which is also awesome, which you could link to in your app.

w/out using a specialized lib, you could approximate the distance a few ways (calculate it just as if it were planar (rectangular) then use the Haversine formula to sort the subset later, use a lookup table that approximates cos, sin, etc, group locations into 5 sq. mile zones and search neighboring cells up to the max, etc...)

Answered by: First Name287 | Posted: 26-02-2022

Answer 3

In my app BostonBusMap I used an approximation to speed up the calculation of closest objects to a point. You can scale the longitude by cos(latitude) and then just use the Pythagorean formula to calculate a sorting distance (omitting the square route since it's not necessary for a comparison distance). It works reasonably well for small distances.


Answered by: Grace333 | Posted: 26-02-2022

Answer 4

I've just written an app that needs to sort a set of coordinates based on distance. What I did was create an array of IDs and Distances and then sorted them within Java. Then I could find the nearest locations and select them from the Database. Of course this approach may not work for you depending on how many points you have and how you access the database. This worked fine for ~350 points, in my Nando's Finder app.

Additionally I used Location.distanceBetween(..) from the SDK to calculate the distances for me. I would hope this method would be implemented in C to ensure it is fast, however, a quick look at the SDK source shows it is written in Java :(.

Answered by: Emily524 | Posted: 26-02-2022

Similar questions

Still can't find your answer? Check out these communities...

Android Google Support | Android Community | Android Community (Facebook) | Android