Calculating Great-Circle Distance with SQLite(用 SQLite 计算大圆距离)
问题描述
这是我的问题,我有一个包含位置和纬度/经度的 SQLite 表.基本上我需要:
Here is my problem, I have a SQLite table with locations and latitudes / longitudes. Basically I need to:
SELECT location, HAVERSINE(lat, lon) AS distance FROM location ORDER BY distance ASC;
HAVERSINE()
是一个 PHP 函数,它应该返回 大圆距离(以英里或公里为单位)给定一对纬度和经度值.其中一对应由 PHP 提供,另一对应由 locations
表中的每个纬度/经度行提供.
HAVERSINE()
is a PHP function that should return the Great-Circle Distance (in miles or km) given a pair of latitude and longitude values. One of these pairs should be provided by PHP and the other pair should be provided by each latitude / longitude row available in the locations
table.
因为 SQLite 没有任何地理空间扩展 (AFAIK SpatiaLite 存在,但仍然......) 我猜最好的方法是将自定义函数与 PDO 方法之一一起使用:
Since SQLite doesn't has any Geo Spatial extension (AFAIK SpatiaLite exists but still...) I'm guessing the best approach would be to use a custom function with either one of the PDO methods:
PDO::sqliteCreateFunction()
PDO::sqliteCreateAggregate()
我认为对于这种情况 PDO::sqliteCreateFunction()
就足够了,但是我对这个函数的有限经验可以简化为类似于 PHP 手册中提供的用例:>
I think for this case PDO::sqliteCreateFunction()
would be enough, however my limited experience with this function can be reduced to usage cases similar to the one provided in the PHP Manual:
$db = new PDO('sqlite:geo.db');
function md5_and_reverse($string) { return strrev(md5($string)); }
$db->sqliteCreateFunction('md5rev', 'md5_and_reverse', 1);
$rows = $db->query('SELECT md5rev(filename) FROM files')->fetchAll();
我在弄清楚如何让 SQLite 用户定义函数同时处理来自 PHP 和表数据的数据时遇到了一些麻烦,如果有人能帮我解决这个问题,我将不胜感激问题,同时也更好地理解 SQLite UDF(SQLite IMO 的一大胜利).
I'm having some trouble figuring out how can I get an SQLite user defined function to process data from PHP and table data at the same time and I would appreciate if someone could help me solve this problem while also understanding SQLite UDFs (a big win of SQLite IMO) a little bit better.
提前致谢!
推荐答案
来自您的有趣链接".
function sqlite3_distance_func($lat1,$lon1,$lat2,$lon2) {
// convert lat1 and lat2 into radians now, to avoid doing it twice below
$lat1rad = deg2rad($lat1);
$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
return acos( sin($lat1rad) * sin($lat2rad) + cos($lat1rad) * cos($lat2rad) * cos( deg2rad($lon2) - deg2rad($lon1) ) ) * 6378.1;
}
$db->sqliteCreateFunction('DISTANCE', 'sqlite3_distance_func', 4);
然后进行查询:
"SELECT * FROM location ORDER BY distance(latitude,longitude,{$lat},{$lon}) LIMIT 1"
<小时>
编辑(按 QOP):我终于再次需要这个,这个解决方案效果很好,我只是稍微修改了代码,让它不那么冗长,并且可以处理非数字值优雅地,这里是:
EDIT (by QOP): I finally needed this again and this solution worked out great, I just ended up modifying the code a bit to it is a bit less verbose and handles non-numeric values gracefully, here it is:
$db->sqliteCreateFunction('distance', function () {
if (count($geo = array_map('deg2rad', array_filter(func_get_args(), 'is_numeric'))) == 4) {
return round(acos(sin($geo[0]) * sin($geo[2]) + cos($geo[0]) * cos($geo[2]) * cos($geo[1] - $geo[3])) * 6378.14, 3);
}
return null;
}, 4);
这篇关于用 SQLite 计算大圆距离的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:用 SQLite 计算大圆距离
基础教程推荐
- 如何在 Symfony 和 Doctrine 中实现多对多和一对多? 2022-01-01
- 在 CakePHP 2.0 中使用 Html Helper 时未定义的变量 2021-01-01
- Doctrine 2 - 在多对多关系中记录更改 2022-01-01
- 如何在 XAMPP 上启用 mysqli? 2021-01-01
- 找不到类“AppHttpControllersDB",我也无法使用新模型 2022-01-01
- 在 yii2 中迁移时出现异常“找不到驱动程序" 2022-01-01
- 使用 PDO 转义列名 2021-01-01
- phpmyadmin 错误“#1062 - 密钥 1 的重复条目‘1’" 2022-01-01
- HTTP 与 FTP 上传 2021-01-01
- PHP 守护进程/worker 环境 2022-01-01