I've stored latitude and longitude value into my sqlite table. Eg: latitude = 16.840064 and longitude = 96.120286.My question is how can I check and retrieve data from sqlite database for nearest location based on device current GPS location?
问问题
327 次
3 回答
1
您可以做的最好的事情是在查询中使用 Haversine 公式 ( http://en.wikipedia.org/wiki/Haversine_formula )。
这个公认的答案似乎是你的问题,所以看看那里: SQlite Getting最近的位置(纬度和经度)
于 2013-06-13T08:35:12.633 回答
1
虽然已经给出的答案(Harversine 公式)是正确的,但可能是我更简单的解决方案适合您:我正在使用此解决方案对给定位置的最近机场进行反向地理编码(用于我的飞行记录器应用程序):
查询数据库中存储在行中的位置的坐标比给定解决方案小或大 0.1 度的所有行。这在赤道两侧大约 11 公里,在德国大约 6 公里。
对于上述查询回答的每个元素,计算到给定位置的距离。如果没有,请尝试更大的查询范围(例如 0.5 度)。
以最小距离回答元素
对于我的应用程序,第一步只回答一行,因为机场通常分布得相当稀疏。
编辑这是来自内容提供者的一些代码,位置是查询 URI 的一部分
@Override
public Cursor query(final Uri uri, final String[] projection, final String selection, final String[] selectionArgs, String sortOrder) {
String pathSegment;
Location loc;
Object[] result;
MatrixCursor result_cursor;
final SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
qb.setTables(AirfieldsTable.TABLE_NAME);
final SQLiteDatabase dbCon = this.db.getReadableDatabase();
switch( URI_MATCHER.match(uri) ) {
// ... the location is encoded in the URI used to query the provider
case NRST_AIRFIELD:
pathSegment = uri.getPathSegments().get(1);
if( DEBUG )
Log.d( TAG, "Query nearest airfield: " + pathSegment);
loc = this.parsePosition(pathSegment);
if( loc == null )
return null;
// try a range query first
result = this.rangeQuery(dbCon, loc.getLatitude(), loc.getLongitude());
if( result == null )
// range query had no hits, try a full table scan
// **Here you could enlarge the range as suggested in the text before the EDIT**
return this.nearestBruteForce(dbCon, loc.getLatitude(), loc.getLongitude());
result_cursor = new MatrixCursor(AirfieldsTable.allColumnNames());
result_cursor.addRow(result);
return result_cursor;
// ...
default:
throw new IllegalArgumentException("Unknown URI: " + uri);
}
}
这是范围查询:
/**
* Query the airfields table for airfields near the given position.
* @param dbCon DB connection
* @param ref_lat latitude
* @param ref_lon longitude
* @return Answer the airfield nearest to the given position as array
* of objects: id, designator, latitude, longitude.
* Answer <code>null</code> if their is no airfield near the
* given position plus or minus 0.1 degrees.
*/
private Object[] rangeQuery(final SQLiteDatabase dbCon, final double ref_lat, final double ref_lon) {
if( DEBUG )
Log.d( TAG, "rangeQuery lat=" + ref_lat + ", lon=" + ref_lon);
final SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
qb.setTables(AirfieldsTable.TABLE_NAME);
final String[] whereArgs = new String[] {
Double.toString(ref_lat - 0.1d), Double.toString(ref_lat + 0.1d),
Double.toString(ref_lon - 0.1d), Double.toString(ref_lon + 0.1d)
};
final Cursor crsr = qb.query(dbCon, allFields(), AirfieldsTable.RANGE_CLAUSE, whereArgs, null, null, null);
final Object[] val = this.scanForNearest(crsr, ref_lat, ref_lon);
crsr.close();
if( DEBUG )
Log.d( TAG, "scanForNearest returned " + val);
return val;
}
这是寻找最小距离的机场:
/**
* Select the airfield nearest to the given position from the
* given cursor.
* @param crsr a cursor
* @param ref_lat latitude
* @param ref_lon longitude
* @return Answer the airfield nearest to the given position as array
* of objects: id, designator, latitude, longitude.
* Answer <code>null</code> if the cursor is empty.
*/
private Object[] scanForNearest(final Cursor crsr, final double ref_lat, final double ref_lon) {
String designator = null;
long id = -1;
double lat = 0.0f, lon = 0.0f, dist = Float.MAX_VALUE;
int ctr = 0;
final float[] results = new float[1];
if( ! crsr.moveToFirst() ) {
if( DEBUG )
Log.d( TAG, "scan for nearest with empty cursor");
return null;
}
do {
ctr += 1;
final double tmp_lat = crsr.getDouble(AirfieldColumns.IDX_LATITUDE);
final double tmp_lon = crsr.getDouble(AirfieldColumns.IDX_LONGITUDE);
Location.distanceBetween(tmp_lat, tmp_lon, ref_lat, ref_lon, results);
final float tmp_dist = results[0];
if( tmp_dist < dist ) {
// first element or nearer element
designator = crsr.getString(AirfieldColumns.IDX_DESIGNATOR);
id = crsr.getLong(AirfieldColumns.IDX_ID);
lat = tmp_lat;
lon = tmp_lon;
dist = tmp_dist;
}
} while( crsr.moveToNext() );
if( DEBUG )
Log.d( TAG, "nearest is " + designator + ", dist=" + dist + ", ctr=" + ctr + ", id=" + id);
final Object[] val = {
id,
designator,
lat,
lon };
return val;
}
NearestBruteForce() 很简单:从全表扫描中获取游标并调用 scanForNearest()。
于 2013-06-13T12:48:34.180 回答
0
Location.distanceTo (Location locationFromDb)
看起来您需要从数据库中的每个条目中创建一个 Location 对象并使用上述函数
于 2013-06-13T08:39:12.953 回答