Query to Get Records Based on Radius in SQLite

Query to get records based on Radius in SQLite?

You can create 4 new columns, being sin and cos of lat and lon. Since cos(a+b) = cos a cos b - sin a sin b, and other appearances of sin and cos like SIN(12.345 * PI() / 180) can be calculated in the program before running the query, the big "distance" expression reduces to something of the form P * SIN_LAT + Q * COS_LAT + ... that can be handled by SQLite3.

BTW, see also Sqlite on Android: How to create a sqlite dist db function - to be used in the app for distance calculation using lat, long.

Sqlite: select items based on distance (latitude and longitude)

I don't actually see the problem, but I re-engineered the selection/where so it's easier to read. And now it works. You can also checkout this fiddle.

public static String buildDistanceWhereClause(double latitude, double longitude, double distanceInKilometers) {

// see: http://stackoverflow.com/questions/3126830/query-to-get-records-based-on-radius-in-sqlite

final double coslat = Math.cos(Math.toRadians(latitude));
final double sinlat = Math.sin(Math.toRadians(latitude));
final double coslng = Math.cos(Math.toRadians(longitude));
final double sinlng = Math.sin(Math.toRadians(longitude));

final String format = "(%1$s * %2$s * (%3$s * %4$s + %5$s * %6$s) + %7$s * %8$s) > %9$s";
final String selection = String.format(format,
coslat, COLUMN_LATITUDE_COS,
coslng, COLUMN_LONGITUDE_COS,
sinlng, COLUMN_LONGITUDE_SIN,
sinlat, COLUMN_LATITUDE_SIN,
Math.cos(distanceInKilometers / 6371.0)
);

Log.d(TAG, selection);
return selection;
}

How to retrieve a set of locations within particular range from user's location from SQLite database

You can write a SQL query with following where condition :

where ( (my_lat - LAT)*(my_lat - LAT) + (my_lon - LON)*(my_lon - LON) ) <= 1KM

The idea is that use Pythagoras method to calculate approx location and filter based on that.
Here I have not taken the square root because I guess SQL functions in SQLite don't have sqrt.

This is good for approximate calculations ...

I used following SQL and it worked ...

// Table with columns as String and Float
CREATE TABLE "locations" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL , "lat_string" VARCHAR, "long_string" VARCHAR, "lat_val" FLOAT, "long_val" FLOAT)

// Insert example data
INSERT INTO "locations" VALUES(1,'12.9587926','77.7477416',12.9587926,77.7477416);
INSERT INTO "locations" VALUES(2,'12.9973486','77.6967362',12.9973486,77.69673619999999);
INSERT INTO "locations" VALUES(3,'12.9715987','77.5945627',12.9715987,77.5945627);
INSERT INTO "locations" VALUES(4,'12.9629354','77.7122996',12.9629354,77.7122996);

// Select when column format is string. This works in SQLIte
SELECT id, ( (77.7580827 - long_string)*(77.7580827 - long_string) + (12.9905542 - lat_string)*(12.9905542 - lat_string) ) as dist FROM locations

// Select when column format is float. This works in SQLIte
SELECT id, ( (77.7580827 - long_val)*(77.7580827 - long_val) + (12.9905542 - lat_val)*(12.9905542 - lat_val) ) as dist FROM locations

how to retrieve data based on the closest distance in room persistance

I've found the right query by calculating the straight distance..

@Query("SELECT * FROM customers ORDER BY ABS(latitude - :latitude) + ABS(longitude - :longitude) ASC")
abstract fun findByDistance(latitude:Double,longitude:Double): MutableList<Customers>

Maybe this can help you who need the same thing as me.. thank you..

SQlite Getting nearest locations (with latitude and longitude)

1) At first filter your SQLite data with a good approximation and decrease amount of data that you need to evaluate in your java code. Use the following procedure for this purpose:

To have a deterministic threshold and more accurate filter on data, It is better to calculate 4 locations that are in radius meter of the north, west, east and south of your central point in your java code and then check easily by less than and more than SQL operators (>, <) to determine if your points in database are in that rectangle or not.

The method calculateDerivedPosition(...) calculates those points for you (p1, p2, p3, p4 in picture).

Sample Image

/**
* Calculates the end-point from a given source at a given range (meters)
* and bearing (degrees). This methods uses simple geometry equations to
* calculate the end-point.
*
* @param point
* Point of origin
* @param range
* Range in meters
* @param bearing
* Bearing in degrees
* @return End-point from the source given the desired range and bearing.
*/
public static PointF calculateDerivedPosition(PointF point,
double range, double bearing)
{
double EarthRadius = 6371000; // m

double latA = Math.toRadians(point.x);
double lonA = Math.toRadians(point.y);
double angularDistance = range / EarthRadius;
double trueCourse = Math.toRadians(bearing);

double lat = Math.asin(
Math.sin(latA) * Math.cos(angularDistance) +
Math.cos(latA) * Math.sin(angularDistance)
* Math.cos(trueCourse));

double dlon = Math.atan2(
Math.sin(trueCourse) * Math.sin(angularDistance)
* Math.cos(latA),
Math.cos(angularDistance) - Math.sin(latA) * Math.sin(lat));

double lon = ((lonA + dlon + Math.PI) % (Math.PI * 2)) - Math.PI;

lat = Math.toDegrees(lat);
lon = Math.toDegrees(lon);

PointF newPoint = new PointF((float) lat, (float) lon);

return newPoint;

}

And now create your query:

PointF center = new PointF(x, y);
final double mult = 1; // mult = 1.1; is more reliable
PointF p1 = calculateDerivedPosition(center, mult * radius, 0);
PointF p2 = calculateDerivedPosition(center, mult * radius, 90);
PointF p3 = calculateDerivedPosition(center, mult * radius, 180);
PointF p4 = calculateDerivedPosition(center, mult * radius, 270);

strWhere = " WHERE "
+ COL_X + " > " + String.valueOf(p3.x) + " AND "
+ COL_X + " < " + String.valueOf(p1.x) + " AND "
+ COL_Y + " < " + String.valueOf(p2.y) + " AND "
+ COL_Y + " > " + String.valueOf(p4.y);

COL_X is the name of the column in the database that stores latitude values and COL_Y is for longitude.

So you have some data that are near your central point with a good approximation.

2) Now you can loop on these filtered data and determine if they are really near your point (in the circle) or not using the following methods:

public static boolean pointIsInCircle(PointF pointForCheck, PointF center,
double radius) {
if (getDistanceBetweenTwoPoints(pointForCheck, center) <= radius)
return true;
else
return false;
}

public static double getDistanceBetweenTwoPoints(PointF p1, PointF p2) {
double R = 6371000; // m
double dLat = Math.toRadians(p2.x - p1.x);
double dLon = Math.toRadians(p2.y - p1.y);
double lat1 = Math.toRadians(p1.x);
double lat2 = Math.toRadians(p2.x);

double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.sin(dLon / 2)
* Math.sin(dLon / 2) * Math.cos(lat1) * Math.cos(lat2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
double d = R * c;

return d;
}

Enjoy!

I used and customized this reference and completed it.

How to display the nearby marker from the SQLite DB

You should add a criteria when retrieving the list of markers like only retrieving markers in certain radius.

you can refer to this qustion if you decided to go with this approach :
Query to get records based on Radius in SQLite?



Related Topics



Leave a reply



Submit