PHP MySQL 从 GPS 获取半径用户位置的位置

发布于 2024-09-12 09:51:08 字数 187 浏览 8 评论 0原文

例如,我的数据库中有汽车事故。这些事件有纬度和经度。在使用 GPS 的手机上,我可以获取用户的位置及其坐标。用户可以选择他想知道他周围是否有事件的半径。假设他想了解他周围 2 英里的事件。

因此,我将用户的纬度、经度和他选择的半径从手机发送到网络服务。我需要进行 SQL 查询来获取用户周围 2 英里的事件。

你知道该怎么做吗?

I have in my database car incidents for example. These incidents have a latitude and longitude. On a mobile using the GPS, I get the user's location with his coordinates. The user can select a radius that he wants to know if there are incidents around him. So let's say he want to know incidents 2 miles around him.

So I send from the phone to a web service the user's latitude, longitude and the radius he selected. I need to make a SQL query to get the incidents 2 miles around the user.

Do you have any idea how to do that?

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

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

发布评论

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

评论(5

旧话新听 2024-09-19 09:51:08

正如其他人所说,计算距离的计算成本相当高。返回巨大的数据集也不是一个好主意 - 特别是考虑到 PHP 的性能并不是那么好。

我会使用启发式方法,例如通过简单的加法和减法来近似距离。

1 分钟 = 1.86 公里 = 1.15
英里

只需搜索数据库中包含该范围内的事件(实际上是一个正方形,而不是一个圆形),然后您就可以使用 PHP 处理这些事件。


编辑:这是一个替代方案;计算成本较低的近似值:

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

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


编辑2:我跑了一堆使用随机生成的数据集进行测试。

  • 3 种算法的准确度差异很小,尤其是在短距离时。
  • 最慢的算法(具有整组三角函数的算法)比其他两种算法慢 4 倍。

绝对不值得。只需进行近似即可。

代码在这里:http://pastebin.org/424186

Calculating the distance is pretty computationally expensive, as others have said. Returning huge datasets is also not a very good idea - specially considering PHP isn't that great in performance.

I would use a heuristic, like approximating the distance with simple addition and subtraction.

1 minute = 1.86 kilometers = 1.15
miles

Just search the db with incidents within that range (effectively a square, rather than a circle), and then you can work on those with PHP.


EDIT: 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


EDIT 2: 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 (the one with the whole bunch of trig functions) is 4x slower than the other two.

Definitely not worth it. Just go with an approximation.

Code is here: http://pastebin.org/424186

为你拒绝所有暧昧 2024-09-19 09:51:08
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;
    }
  } // end function

$x_lat=center_of_serach;
$x_lon=center_of_serach;
$_distance=some_distance_in_miles;
$query1 = "SELECT * FROM `location_table` WHERE somefield=somefilter";
$result=mysql_db_query($db_conn, $query1);
$max_rows=mysql_num_rows($result); 
if ($max_rows>0)
  {
while ( $data1=mysql_fetch_assoc($result) )
  {
  if ( distance($x_lat,$x_lon,$data1['lat'],$data1['lng'],'m')<$_distance )
    {
    //do stuff
    }
  }

如果您的数据库不太大,则获取所有数据并通过函数运行它比使用查询更快。

它也适用于公斤和海里。 ;)

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;
    }
  } // end function

$x_lat=center_of_serach;
$x_lon=center_of_serach;
$_distance=some_distance_in_miles;
$query1 = "SELECT * FROM `location_table` WHERE somefield=somefilter";
$result=mysql_db_query($db_conn, $query1);
$max_rows=mysql_num_rows($result); 
if ($max_rows>0)
  {
while ( $data1=mysql_fetch_assoc($result) )
  {
  if ( distance($x_lat,$x_lon,$data1['lat'],$data1['lng'],'m')<$_distance )
    {
    //do stuff
    }
  }

Its faster to fetch all the data and run it through a function, rather than use a query if your database isn't too big.

It works for Kilos and Nautical miles too. ;)

赤濁 2024-09-19 09:51:08
 SELECT 3963 * ACOS(
    SIN(RADIANS($pointAlat)) * SIN(RADIANS($pointAlat)) + COS(RADIANS($pointAlat))  * COS(RADIANS($pointBlat)) * COS(RADIANS($pointAlong) - RADIANS($pointBlong)))
 AS
 distance;

另外,如果您正在寻找这方面的好读物/教程..请查看此处
http://www.phpfreaks.com/forums/index.php/主题,208965.0.html

 SELECT 3963 * ACOS(
    SIN(RADIANS($pointAlat)) * SIN(RADIANS($pointAlat)) + COS(RADIANS($pointAlat))  * COS(RADIANS($pointBlat)) * COS(RADIANS($pointAlong) - RADIANS($pointBlong)))
 AS
 distance;

Also, if you're looking for a good read/tutorial on this.. Check here
http://www.phpfreaks.com/forums/index.php/topic,208965.0.html

空名 2024-09-19 09:51:08

我快速搜索了一下,找到了这篇博文,它给出了很好的解释和可供选择的 SQL给定半径内的记录。

在评论中,他建议“为了提高大型数据集的速度,您可能希望首先通过在纬度/经度之间添加一英里左右作为原点,然后使用上面的内容作为子选择来工作,从而在原点周围抓取一个正方形块从中间向外”,这对我来说听起来像是要走的路。

I did a quick search and turned up this blog post which gives a good explanation and SQL to select records in a given radius.

In the comments, he suggests "For speed on large datasets you probably want to grab a square block around the origin point first by adding a mile or so to and from both lat/lon for origin and then using the above as a subselect to work from the middle out" which sounds to me like the way to go.

五里雾 2024-09-19 09:51:08

有一个公式可以计算两个纬度/经度坐标之间的距离。但请注意——这在计算上相当昂贵,所以如果你有很多事件,你会想要聪明地对待它。首先,了解涉及数学

至于PHP代码,快速谷歌一下就找到了 此链接,看起来可能有效。

现在,您可能希望使用一些更有效的方法将事件点分为两组:那些可能在范围内的点(希望是一个较小的集合),以及那些您可以完全忽略的点。检查几十个事件坐标可能会出现性能问题。

我对此没有任何特别的见解,但如果没有其他人提出一些聪明的东西,我会在时间允许的情况下尝试自己想出一些东西。

There is a formula to compute the distance between two lat/lon coordinates. Beware though -- it's rather computationally expensive, so if you have lots of incidents, you'll want to be smart about it. First up, read about the maths involved.

As for PHP code, a quick google turned up this link, which looks like it probably works.

Now, you probably want to use some more efficient method to divide your incident points into two sets: those points that might be within range (hopefully a smallish set), and those that you can discount entirely. Checking more than a few dozen incident coordinates is likely to be a performance issue.

I don't have any particular insight into that, but if nobody else comes along with something clever, I'll try to come up with something myself later, time permitting.

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