0

緯度と経度の値を sqlite テーブルに保存しました。例:緯度 = 16.840064および経度 = 96.120286 .私の質問は、デバイスの現在の GPS 位置に基づいて、最も近い位置の sqlite データベースからデータを確認して取得するにはどうすればよいですか?

4

3 に答える 3

1

最善の方法は、クエリで Haversine 式 ( http://en.wikipedia.org/wiki/Haversine_formula ) を使用することです。

この受け入れられた回答はあなたの質問のようですので、そこを見てください: SQlite 最寄りの場所を取得する (緯度と経度)

于 2013-06-13T08:35:12.633 に答える
1

すでに与えられた答え(ハーバーシン式)は正しいですが、私はより簡単な解決策があなたのために働くかもしれません.

  1. 行に格納されている位置の座標が、指定された解よりも 0.1 度小さいか大きいすべての行をデータベースに照会します。これは、赤道では両側に約 11 km、ドイツでは約 6 km です。

  2. 上記のクエリに対して回答された各要素について、指定された場所までの距離を計算します。何もない場合は、クエリのより大きな範囲を試してください (例: 0.5 度)。

  3. 最小距離で要素に答える

私のアプリケーション ステップでは、飛行場は通常かなりまばらに分布しているため、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() を呼び出します。

于 2013-06-13T12:48:34.180 に答える
0
Location.distanceTo (Location locationFromDb)

データベースの各エントリから Location オブジェクトを作成し、上記の関数を使用する必要があるようです

于 2013-06-13T08:39:12.953 に答える