zoukankan      html  css  js  c++  java
  • Distance function for sqlite

    Distance function for sqlite

    As part of an iPhone SDK project, I have an sqlite database with a table full of geographic locations, each stored as a latitude and longitude value in degrees. I wanted to be able to perform an SQL SELECT on this table and ORDER BY each row’s distance from an arbitrary point. I’ve achieved this by defining a custom sqlite function. This article contains the code for the function, together with instructions on using it.

    Here’s the function, together with a convenience macro to convert from degrees to radians. This function is based on an online distance calculator I found which makes use of the spherical law of cosines.


    #define DEG2RAD(degrees) (degrees * 0.01745327) // degrees * pi over 180

    static void distanceFunc(sqlite3_context *context, int argc, sqlite3_value **argv)
    {
    // check that we have four arguments (lat1, lon1, lat2, lon2)
    assert(argc == 4);
    // check that all four arguments are non-null
    if (sqlite3_value_type(argv[0]) == SQLITE_NULL || sqlite3_value_type(argv[1]) == SQLITE_NULL || sqlite3_value_type(argv[2]) == SQLITE_NULL || sqlite3_value_type(argv[3]) == SQLITE_NULL) {
    sqlite3_result_null(context);
    return;
    }
    // get the four argument values
    double lat1 = sqlite3_value_double(argv[0]);
    double lon1 = sqlite3_value_double(argv[1]);
    double lat2 = sqlite3_value_double(argv[2]);
    double lon2 = sqlite3_value_double(argv[3]);
    // convert lat1 and lat2 into radians now, to avoid doing it twice below
    double lat1rad = DEG2RAD(lat1);
    double lat2rad = DEG2RAD(lat2);
    // apply the spherical law of cosines to our latitudes and longitudes, and set the result appropriately
    // 6378.1 is the approximate radius of the earth in kilometres
    sqlite3_result_double(context, acos(sin(lat1rad) * sin(lat2rad) + cos(lat1rad) * cos(lat2rad) * cos(DEG2RAD(lon2) - DEG2RAD(lon1))) * 6378.1);
    }

    This defines an SQL function distance(Latitude1, Longitude1, Latitude2, Longitude2), which returns the distance (in kilometres) between two points.

    To use this function, add the code above to your Xcode project, and then add this line immediately after you call sqlite3_open:


    sqlite3_create_function(sqliteDatabasePtr, "distance", 4, SQLITE_UTF8, NULL, &distanceFunc, NULL, NULL);

    …where sqliteDatabasePtr is the database pointer returned by your call to sqlite3_open.

    Assuming you have a table called Locations, with columns called Latitude and Longitude (both of type double) containing values in degrees, you can then use this function in your SQL like this:


    SELECT * FROM Locations ORDER BY distance(Latitude, Longitude, 51.503357, -0.1199)

    This example orders the locations in your database based on how far away they are from the London Eye, which is at 51.503357, -0.1199.

  • 相关阅读:
    文档数据库 海量文本分析 搜索引擎 NoSql 数据库 NewSql 数据库 图数据库 知识图谱 联想 白盒人工智能
    我发起了 一个 桌面程序 窗体界面 开源项目 WinFormXml
    调幅 是 电子技术, 调频 是 量子技术
    出一道题 : 证明 超外差收音机 的 混频原理
    研究一下 容器 的 原理
    设计 一个 CPU 的 存储管理部件
    我发起了 一个 操作系统 开源项目, 名字待定
    ServerFul 架构
    谈谈 ServerFul 架构
    状态机 控制机 任务机
  • 原文地址:https://www.cnblogs.com/mgbert/p/4146664.html
Copyright © 2011-2022 走看看