PHP MySql 和地理定位

发布于 2024-09-16 07:51:53 字数 752 浏览 2 评论 0原文

我正在编写一个网站,基本上使用 php 和 mysql 查找纬度和经度 25 英里半径内的地方。

我想知道这样的事情是如何运作的?

我会将纬度和经度传递给票据,并让它从我的位置数据库中仅提取纬度和经度 25 英里以内的位置。

最好的方法是什么?

编辑: 我发现这个代码用于计算两点之间的距离。

    function distance($lat1, $lon1, $lat2, $lon2, $unit) { 

  $theta = $lon1 - $lon2; 
  $dist = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) +  cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($theta)); 
  $dist = acos($dist); 
  $dist = rad2deg($dist); 
  $miles = $dist * 60 * 1.1515;
  $unit = strtoupper($unit);

  if ($unit == "K") {
    return ($miles * 1.609344); 
  } else if ($unit == "N") {
      return ($miles * 0.8684);
    } else {
        return $miles;
      }
}

有没有办法在 MYSQL 查找中执行此计算,这样我只能在 Miles =< 时返回25?

I am writing a site that basically looks for places within a 25 mile radius of a lat and long using php and mysql.

I am wondering how something like this would work?

I would pass a lat and long to the scrip and have it pull out only locations that are within 25 miles of the lat and long from my Database of locations.

What is the best way to do this?

EDIT:
I found this code for calculating the distance between 2 points.

    function distance($lat1, $lon1, $lat2, $lon2, $unit) { 

  $theta = $lon1 - $lon2; 
  $dist = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) +  cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($theta)); 
  $dist = acos($dist); 
  $dist = rad2deg($dist); 
  $miles = $dist * 60 * 1.1515;
  $unit = strtoupper($unit);

  if ($unit == "K") {
    return ($miles * 1.609344); 
  } else if ($unit == "N") {
      return ($miles * 0.8684);
    } else {
        return $miles;
      }
}

Is ther a way to do this calc in the MYSQL look up so I can only return if miles =< 25?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

孤者何惧 2024-09-23 07:51:53

使用该函数计算距离的计算成本相当高,因为它涉及一大堆超越函数。当您有大量的行需要过滤时,这将会出现问题。

这是一种替代方案,一种计算成本较低的近似值:

以英里为单位的近似距离:

sqrt(x * x + y * y)

where x = 69.1 * (lat2 - lat1) 
and y = 53.0 * (lon2 - lon1) 

您可以通过添加余弦数学函数来提高此近似距离计算的准确性:

改进以英里为单位的近似距离:

sqrt(x * x + y * y)

where x = 69.1 * (lat2 - lat1) 
and y = 69.1 * (lon2 - lon1) * cos(lat1/57.3) 

来源:http://www.meridianworlddata.com/Distance-Calculation.asp


我使用随机生成的数据集进行了一系列测试。

  • 3 种算法的准确度差异最小,尤其是在短距离时。
  • 最慢的算法当然是带有三角函数的算法(您问题中的算法)。它比其他两个慢 4 倍。

绝对不值得。只需进行近似即可。
代码在这里: http://pastebin.org/424186


要在 MySQL 上使用它,请创建一个 存储过程接受坐标参数并返回距离,那么你可以做类似的事情:

SELECT columns 
  FROM table 
 WHERE DISTANCE(col_x, col_y, target_x, target_y) < 25

Calculating the distance using that function there is pretty computationally expensive, because it involves a whole bunch of transcendental functions. This is going to be problematic when you have a large number of rows to filter on.

Here's an alternative, an approximation that's way less computationally expensive:

Approximate distance in miles:

sqrt(x * x + y * y)

where x = 69.1 * (lat2 - lat1) 
and y = 53.0 * (lon2 - lon1) 

You can improve the accuracy of this approximate distance calculation by adding the cosine math function:

Improved approximate distance in miles:

sqrt(x * x + y * y)

where x = 69.1 * (lat2 - lat1) 
and y = 69.1 * (lon2 - lon1) * cos(lat1/57.3) 

Source: http://www.meridianworlddata.com/Distance-Calculation.asp


I ran a bunch of tests with randomly generated datasets.

  • The difference in accuracy for the 3 algorithms is minimal, especially at short distances
  • The slowest algorithm is, of course, the one with the trig functions (the one on your question). It is 4x slower than the other two.

Definitely not worth it. Just go with an approximation.
Code is here: http://pastebin.org/424186


To use this on MySQL, create a stored procedure that takes coordinate arguments and returns the distance, then you can do something like:

SELECT columns 
  FROM table 
 WHERE DISTANCE(col_x, col_y, target_x, target_y) < 25
原来是傀儡 2024-09-23 07:51:53

您可能想看看此解决方案 - 一个有点聪明的解决方法。

You may want to take a look at this solution - a somewhat brilliat workaround.

浅忆 2024-09-23 07:51:53

您只需两步即可轻松完成:

  • 查找该点各个方向 25 英里范围内的所有位置。这看起来像: WHERE lat BETWEEN $lat1 AND $lat2 AND lng BETWEEN $lng1 AND $lng2

  • 然后循环遍历每个结果并使用您的代码检查它是否确实在 25 英里之内。 (即,过滤掉正方形角落中的那些位置。)

对于第一部分,这是我放置的一些代码(不记得来源):

$lat_range = $radius / ((6076 / 5280) * 60);
$lng_range = $radius / (((cos(($city['lat'] * 3.141592653589 / 180)) * 6076) / 5280) * 60);

基本上只使用 ($lat - $lat_range 、$lat + $lat_range)($lng - $lng_range, $lng + $lng_range) 半径以英里为单位。

显然你可以稍微清理一下数学。

编辑:我忘了提到,如果您需要支持赤道、国际日期变更线等附近的位置,则需要稍微调整一下。显然对于北美来说,按原样就可以了。

You can do it easily in two steps:

  • Find all locations within 25 miles in each direction of the point. This will look like: WHERE lat BETWEEN $lat1 AND $lat2 AND lng BETWEEN $lng1 AND $lng2

  • Then loop through each result and check to see if it really is within 25 miles using your code. (i.e., Filter out those locations that are in the corners of the square.)

For the first part, here's some code I have laying around (don't remember the source):

$lat_range = $radius / ((6076 / 5280) * 60);
$lng_range = $radius / (((cos(($city['lat'] * 3.141592653589 / 180)) * 6076) / 5280) * 60);

Basically just use ($lat - $lat_range, $lat + $lat_range) and ($lng - $lng_range, $lng + $lng_range) Radius is in miles.

Obviously you can clean up the math a bit.

Edit: I forgot to mention that you would need to tweak it a bit if you need to support locations near the equator, international date line, etc. Obviously for North America, it would be fine as-is.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文