In my web/MySQL application I have something like this to get distance between two points:
6371 * acos(cos(radians(-19.83996)) * cos(radians(lat)) * cos(radi
For windows:
Install minGw full options. modify environment variable: system variable path, including
c:\mingw\bin
test functionality command:
g++ --version
copy files: extension-functions.c, sqlite3.h, sqlite3ext.h in sqlite3 program directory. Go to sqlite3 directory and compile:
gcc -shared -I "path" -o libsqlitefunctions.so extension-functions.c
(path = path of sqlite3ext.h; i.e. C:\sqlite3)
If the program is built so that loading extensions is permitted, the following will work:
sqlite> SELECT load_extension('./libsqlitefunctions.so');
sqlite> select cos(radians(45));
0.707106781186548
SQLite Distance implementation:
From: https://www.movable-type.co.uk/scripts/latlong.html https://en.wikipedia.org/wiki/Haversine_formula
Distance
This uses the ‘haversine’ formula to calculate the great-circle distance between two points – that is, the shortest distance over the earth’s surface – giving an ‘as-the-crow-flies’ distance between the points (ignoring any hills they fly over, of course!).
Haversine
formula: a = sin²(Δφ/2) + cos φ1 * cos φ2 * sin²(Δλ/2)
c = 2 * atan2( √a, √(1−a) )
c = 2 *
d = R * c
where φ is latitude, λ is longitude, R is earth’s radius (mean radius = 6,371km);
note that angles need to be in radians to pass to trig functions!
JavaScript:
const R = 6378136.6 ; // meters equatorial radius
const φ1 = lat1 * Math.PI/180; // φ, λ in radians
const φ2 = lat2 * Math.PI/180;
const Δφ = (lat2-lat1) * Math.PI/180;
const Δλ = (lon2-lon1) * Math.PI/180;
const a = Math.sin(Δφ/2) * Math.sin(Δφ/2) +
Math.cos(φ1) * Math.cos(φ2) *
Math.sin(Δλ/2) * Math.sin(Δλ/2);
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
const c = 2 * Math.asen(MIN (1, Math.sqrt(a))); //sqlite implementation
const d = R * c; // in metres
Distance = 2 * R * ASIN( MIN (1, SQRT( SIN( (RADIANS(lat1)-RADIANS(lat2))/2 )^2 + COS( RADIANS(lat1) )*COS( RADIANS(lat2) )*SIN( (RADIANS(long1)-RADIANS(long2))/2 )^2 )))
Physical Properties of Earth https://en.wikipedia.org/wiki/Earth_ellipsoid :Ecuatorial radius: 6378.1366 Kms. Average radius: 6367 Kms
Constant = 2 * 6378136.6 = 12756273.2
SQLite query command with coordinates taken from table PAR:
ROUND (
12756273.2 * ASIN(
MIN (1 ,
SQRT(
POWER( SIN(RADIANS(PAR.Lat1 - PAR.Lat2)/2) , 2) +
COS(RADIANS(PAR.Lat1)) * COS(RADIANS(PAR.Lat2)) * POWER ( SIN(RADIANS(PAR.Long1 - PAR.Long2)/2) , 2)
)
)
)
, 0) AS Distance
Here is what I would do:
Take your given point. Measure a (that is an arbitrary value to be refined) ~2km wide square around it and take the values for the east/west/north/south bounds.
Make a query for elements inside this square. This one is easy, you just have to
select * from points where lat between ? and ? and lon between ? and ?
Count your result. Not enough result (less than 5, obviously, but I would say twice that to be sure), retry with a larger radius. Too much (say, more than 100), try again with a smaller radius.
Once you have enough, load them, make sure all 5 elements you need are not only in the Xkm wide square, but also in the Xkm radius circle (to avoid having a potential closer element not detected by the previous approximation).
Valid only if your given point is relatively close to those you are searching.
Measure a local approximation of a flat earth. Close to your point, you can consider a linear relation between lat, lon, and distance. That allows you to make a request sorted by a simple calculus. (multiplication and addition). Again, select a little more points in order to make the proper calculation after the SQLite request.
Insert cos_lat_rad,sin_lat_rad,cos_lon_rad,sin_lon_rad in to your table
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)));
degree to radian
public static double deg2rad(double deg) {
return (deg * Math.PI / 180.0);
}
query , distance in km
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)));
query
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;
}
convert distance_acos to 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());
In android we have a Location class, we need initialize the location class and in it we have a method called distanceBetween() which gives the distance between two geopoints.
Refer this LINK
Reply of Angel does not solve the problem for SQLite since it still includes ACOS function which does not exist in SQLite
What I have concluded after a thorough research is that one should pick a rough estimation to use in SQLite with the formula below:
Distance estimation for km:
SQRT(SQUARE((TO_LAT-FROM_LAT)*110)+
SQUARE((TO_LONG-FROM_LONG)*COS(TO_LAT)*111))