最接近球面坐标系上的另一个点

时间:2013-08-01 01:11:47

标签: mysql geolocation geoip

我有一个数据库,我填充了我选择的特定位置。对于每个位置,我将提供经度和纬度。

我想获取我网站访问者的geoIP(在maxmind.com等数据库中匹配的给定IP的经度和纬度)。使用geoIP,我想从我的位置数据库表中找到最接近访问者的位置。

我花了很多时间试图找出如何以有效的方式实现这一目标;我不希望这个过程对每个访客来说都很昂贵。这个过程不必精确,只需要足够精确。如果它给用户萨克拉门托而不是旧金山,这本来更正确,那没关系。只要误差程度足够小,就不会打扰大多数用户。什么是不可能的是,如果算法给出一个完全关闭的位置并且与它们的位置无关,比如芝加哥(当他们住在加利福尼亚时)。

所以说,有什么解决方案?

以下是我的一些想法:

1

使用毕达哥拉斯定理来找出平面中两点之间的距离。唯一的问题是地球不在平面坐标系上,而是在球面坐标系上。所以,我需要一种方法将地理位置数据(long。和lat。)转换为X和Y坐标。然后我可以运行一个SQL查询,找到最短distance的记录,该记录使用以下公式计算:sqrt(abs(locationX - geoIpX)^2 + abs(locationY - geoIpY)^2)

我不确定这是不是一个合理的解决方案。如果是,那么请为我平滑粗糙的边缘,这样我就可以实现它。

2

找出使用经度和纬度差异的算法。例如,首先找到与geoIP经度具有最接近经度的位置,然后找到该集合中具有与geoIP纬度最近纬度的位置。刚刚描述的算法的唯一问题是误差范围可能巨大。例如,假设加利福尼亚州的一个城市距离geoIP是3度经度,但加拿大经度的城市距离是2度,将会发生这样的经线将用于找到最近的纬度,这可能只是加拿大的城市。尽管加拿大的纬度比加利福尼亚州的纬度多得多,但用户将获得与加拿大而不是加利福尼亚州相关的数据,这将是一个太大的错误。但是,也许这个算法有一些修改可以解决这个问题吗?

后记

感谢阅读。所有解决方案和帮助都非常感谢! :)

3 个答案:

答案 0 :(得分:1)

您可以使用Haversine公式。 http://www.scribd.com/doc/2569355/Geo-Distance-Search-with-MySQL

为了优化搜索,您可以提供最大,最小坐标 对于max min coords,您可以使用服务器端函数进行处理,也可以使用存储过程来计算这些函数 max min coords的示例:

RewriteEngine on

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^([^/]+)/?$ /$1.php [L,NC]

Mysql + php:

$minLng = $lng-($distance/(abs(cos(rad2deg($lat))*69)));
$maxLng = $lng+($distance/(abs(cos(rad2deg($lat))*69)));
$minLat = $lat-($distance/69);
$maxLat = $lat+($distance/69);

然后在having子句中使用此distance_to_destination 或使用where in where子句

缩小搜索范围

$select = "3956 * 2 * ASIN(SQRT(POWER(SIN((initial.pin_lat - " . $destination.lat . ") * pi()/180 / 2), 2) +COS(" .
        "initial.pin_lat * pi()/180) * COS(" . $destination.lat . " * pi()/180) *POWER(SIN((" .
        "initial.pin_lng - " . $destination.long . ") * pi()/180 / 2),2))) as distance_to_destination";

答案 1 :(得分:0)

你想要Haversine formula。由于该计算涉及三角函数,因此它往往有点昂贵。

您可以考虑将部分数据复制到支持内置地理位置搜索的配套技术。 MySQL在这种类型的搜索方面并不擅长,但其他一些工具也是如此。

例如,Sphinx Search支持地理距离搜索:


MySQL确实支持spatial indexes,但只支持MyISAM表。避免使用MyISAM表的原因有很多。

答案 2 :(得分:0)

mysql和其他数据库一样好。你可以使用空间索引。我写了一个php类,用怪物曲线解决空间索引。你可以在phpclasses下载我的希尔伯特曲线包。它也使用mercantor投影,我使用它非常成功。其他数据库有本机支持,但您可以在几个小时内自己完成。