0

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?

4

3 回答 3

1

您可以做的最好的事情是在查询中使用 Haversine 公式 ( http://en.wikipedia.org/wiki/Haversine_formula )。

这个公认的答案似乎是你的问题,所以看看那里: SQlite Getting最近的位置(纬度和经度)

于 2013-06-13T08:35:12.633 回答
1

虽然已经给出的答案(Harversine 公式)是正确的,但可能是我更简单的解决方案适合您:我正在使用此解决方案对给定位置的最近机场进行反向地理编码(用于我的飞行记录器应用程序):

  1. 查询数据库中存储在行中的位置的坐标比给定解决方案小或大 0.1 度的所有行。这在赤道两侧大约 11 公里,在德国大约 6 公里。

  2. 对于上述查询回答的每个元素,计算到给定位置的距离。如果没有,请尝试更大的查询范围(例如 0.5 度)。

  3. 以最小距离回答元素

对于我的应用程序,第一步只回答一行,因为机场通常分布得相当稀疏。

编辑这是来自内容提供者的一些代码,位置是查询 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 回答