緯度と経度の値を sqlite テーブルに保存しました。例:緯度 = 16.840064および経度 = 96.120286 .私の質問は、デバイスの現在の GPS 位置に基づいて、最も近い位置の sqlite データベースからデータを確認して取得するにはどうすればよいですか?
3 に答える
最善の方法は、クエリで Haversine 式 ( http://en.wikipedia.org/wiki/Haversine_formula ) を使用することです。
この受け入れられた回答はあなたの質問のようですので、そこを見てください: SQlite 最寄りの場所を取得する (緯度と経度)
すでに与えられた答え(ハーバーシン式)は正しいですが、私はより簡単な解決策があなたのために働くかもしれません.
行に格納されている位置の座標が、指定された解よりも 0.1 度小さいか大きいすべての行をデータベースに照会します。これは、赤道では両側に約 11 km、ドイツでは約 6 km です。
上記のクエリに対して回答された各要素について、指定された場所までの距離を計算します。何もない場合は、クエリのより大きな範囲を試してください (例: 0.5 度)。
最小距離で要素に答える
私のアプリケーション ステップでは、飛行場は通常かなりまばらに分布しているため、1 つの行のみに回答します。
編集コンテンツプロバイダーからのコードは次のとおりです。場所はクエリ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() を呼び出します。
Location.distanceTo (Location locationFromDb)
データベースの各エントリから Location オブジェクトを作成し、上記の関数を使用する必要があるようです