【问题标题】:Android sqlite sort on calculated column (co-ordinates distance)计算列上的Android sqlite排序(坐标距离)
【发布时间】:2010-01-09 18:10:42
【问题描述】:

我正在使用 SQLITE 数据库来存储位置的纬度和经度。

我希望能够按与当前位置的粗略距离对结果进行排序。我已经将设备的当前位置作为双精度(lat,lng),数据库中的 lat 和 lng 也是双精度。

我想要的是一个查询,该查询将创建一个虚拟列,我可以根据该列对结果进行排序。

我目前使用一个函数来显示所选记录的距离:

float pk = (float) (180/3.14159);
float a1 = (float) (db_lat / pk);
float a2 = (float) (db_lon / pk);
float b1 = (float) (current_lat / pk);
float b2 = (float) (current_lon / pk);
float t1 = FloatMath.cos(a1)*FloatMath.cos(a2)*FloatMath.cos(b1)*FloatMath.cos(b2);
float t2 = FloatMath.cos(a1)*FloatMath.sin(a2)*FloatMath.cos(b1)*FloatMath.sin(b2);
float t3 = FloatMath.sin(a1)*FloatMath.sin(b1);
double tt = Math.acos(t1 + t2 + t3);
double dist = (6366000*tt);

例如,MySQL 选择可能是(取自:www.movable-type.co.uk):

Select Lat, Lon, acos(sin($lat)*sin(radians(Lat)) + cos($lat)*cos(radians(Lat))cos(radians(Lon)-$lon))$R As dist From MyTable ORDER BY dist DESC

目前我使用以下方法选择位置:

public Cursor locationGetAllRows(long groupid) { try { return db.query(LOCATION_DATABASE_TABLE, new String[] { "_id", "lat","lon","groupid"}, "groupid="+groupid, null, null, null, null); } catch (SQLException e) { Log.e("Exception on query: ", e.toString()); return null; } }

好的,那么可以以这种方式使用 SQLITE 数据库吗?如果不是我能想到的唯一选择是有一个额外的列,遍历在每一行上运行上述函数的行并在该行上填写一个额外的列,然后对该列进行排序?

【问题讨论】:

    标签: android sqlite coordinates


    【解决方案1】:

    这不会完全有帮助,但对于这种情况,请认真考虑使用 rawQuery() 而不是 query(),这样您就可以传入完整的 SQL 语句,而不必将其切成碎片。


    你更大的问题是我没有看到 SQLite 有三角函数。

    您没有说明您是如何使用从查询中返回的Cursor。例如,如果您将Cursor 放入某种CursorAdapter,您可以:

    • Cursor 转换为ArrayList<Position>,其中Position 是您使用数据定义的某个Java 类
    • 关闭Cursor,释放它占用的内存
    • 使用Arrays.sort()ArrayList<Position> 进行排序
    • ArrayList<Position> 包裹在ArrayAdapter<Position> 中,并在您使用CursorAdapter 的地方使用它

    【讨论】:

    • 好的,所以为了测试,我创建了一个 ArrayList> 并用所有需要的细节填充它。我还创建了一个扩展对象的简单类 ArrayList。我遍历光标并将数据当前放入两个列表中,就像我执行距离计算并添加它一样。然后我将如何执行排序?类是:class locationRowDist extends Object { public String title;公共双纬度;公共双 lon;公共双区; }
    • 如果“locationRowDist”是一个类,让它实现Comparable接口,然后使用Arrays.sort()对其进行排序。
    【解决方案2】:

    是的,效果很好。

    可以做成这样的存储过程:

    http://www.thismuchiknow.co.uk/?p=71 [sqlite 的距离函数]

    还有很棒的Perst spatial database for android,还有很棒的SpatiaLite空间数据库,你可以在你的应用程序中链接。

    如果不使用专门的库,您可以通过几种方式近似距离(计算它就像它是平面(矩形)然后使用Haversine公式稍后对子集进行排序,使用近似cos的查找表, sin 等,将位置分组到 5 平方英里的区域中,并搜索相邻单元格直至最大等...)

    【讨论】:

    • 您描述的技术似乎不适用于Android,无法使用sqlite3_create_function()。
    • 是的,如果有一个大的位置数据库,最好使用你自己的 sqlite/perst/spatialite 而不是 android 的内置
    【解决方案3】:

    在我的应用程序 BostonBusMap 中,我使用了一个近似值来加速计算最接近某个点的对象。您可以通过cos(latitude) 缩放经度,然后只需使用毕达哥拉斯公式来计算排序距离(省略方形路线,因为比较距离不是必需的)。它适用于小距离。

    来源:http://en.wikipedia.org/wiki/Geographical_distance#Spherical_Earth_projected_to_a_plane

    【讨论】:

      【解决方案4】:

      我刚刚编写了一个需要根据距离对一组坐标进行排序的应用。我所做的是创建一个 ID 和距离数组,然后在 Java 中对它们进行排序。然后我可以找到最近的位置并从数据库中选择它们。当然,这种方法可能对您不起作用,具体取决于您拥有多少点以及您访问数据库的方式。在我的 Nando 的 Finder 应用中,这对大约 350 点效果很好。

      此外,我使用 SDK 中的 Location.distanceBetween(..) 为我计算距离。我希望这个方法可以在 C 中实现以确保它很快,但是,快速查看SDK source 表明它是用 Java 编写的:(。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-12-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-11-01
        相关资源
        最近更新 更多