在我的网络/ MySQL应用程序中,我有类似的东西来获得两点之间的距离:
6371 * acos(cos(radians(-19.83996)) * cos(radians(lat)) * cos(radians(-43.94910) - radians(lng)) + sin(radians(-19.83996)) * sin(radians(lat)))
但我在SQLite中测试过,这些数学函数(acos,cos,radians,sin)不存在。有没有东西可以直接在数据库中计算距离?
但是,我有一个使用this method计算的iPhone应用程序。工作得很好,但现在我需要在Android应用程序的数据库中执行相同的搜索。
提前致谢。
更新
我有9000个点来计算距离并获得给定点附近的5个位置。
答案 0 :(得分:6)
以下是我要做的事情:
按照你的观点。测量a(这是一个要精炼的任意值)~2km宽的方形围绕它并取东/西/北/南边界的值。
查询此方块内的元素。这个很简单,你只需要
select * from points where lat between ? and ? and lon between ? and ?
计算结果。结果不够(显然不到5个,但我要说两次才能确定),以更大的半径重试。太多(比如超过100),再次尝试半径越小。
一旦你有足够的,加载它们,确保你需要的所有5个元素不仅在Xkm宽的方形中,而且在Xkm半径圆中(以避免前一个近似未检测到的潜在的更近的元素)。
仅当您的指定点与您正在搜索的点相对接近时才有效。
测量平坦地球的局部近似。接近你的观点,你可以考虑lat,lon和distance之间的线性关系。这允许您通过简单的微积分进行排序。 (乘法和加法)。再次,选择多一点以便在SQLite请求之后进行正确的计算。
答案 1 :(得分:3)
将cos_lat_rad,sin_lat_rad,cos_lon_rad,sin_lon_rad插入您的表格
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)));
度到弧度
public static double deg2rad(double deg) {
return (deg * Math.PI / 180.0);
}
查询,以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)));
查询
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;
}
将distance_acos转换为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());
答案 2 :(得分:0)
Angel的回复并没有解决SQLite的问题,因为它仍然包含SQLite中不存在的ACOS功能
经过深入研究后我得出的结论是,应该选择粗略估计在SQLite中使用以下公式:
km的距离估计:
SQRT(SQUARE((TO_LAT-FROM_LAT)*110)+
SQUARE((TO_LONG-FROM_LONG)*COS(TO_LAT)*111))
答案 3 :(得分:0)
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
答案 4 :(得分:-3)
在android中我们有一个Location类,我们需要初始化location类,在其中我们有一个名为distanceBetween()的方法,它给出了两个地理位置之间的距离。
请参阅此LINK