php 如何在php中计算纬度/经度的距离?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7672759/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 03:08:55  来源:igfitidea点击:

How to calculate distance from lat/long in php?

phplatitude-longitude

提问by iPhoneDev

What I am trying to do is I have entries in the database which have a lat/long stored with them. I want to calculate the distance between users lat/long and entries lat/long (in DB). After that, I want to echo the ones with distance less than 500 meters. So far I am able to do this using foreach.

我想要做的是我在数据库中有条目,这些条目存储了纬度/经度。我想计算用户纬度/经度和条目纬度/经度(在 DB 中)之间的距离。之后,我想回声距离小于500米的那些。到目前为止,我能够使用foreach.

<?php
mysql_connect("localhost", "beepbee_kunwarh", "kunwar") or die('MySQL Error.');
mysql_select_db("beepbee_demotest") or die('MySQL Error.');

$Lat = $_REQUEST['Lat'];
$long = $_REQUEST['long'];

$query = mysql_query("SELECT a.*, 3956 * 2 * ASIN(SQRT( POWER(SIN(($Lat - Lat) * pi()/180 / 2), 2) + COS($Lat * pi()/180) * COS(Lat * pi()/180) *POWER(SIN(($long - long) * pi()/180 / 2), 2) )) as distance FROM userResponse GROUP BY beepid HAVING distance <= 500 ORDER by distance ASC;");
$data = array();
while ($row = mysql_fetch_array($query)) {
    $data[] = $row;
}
echo json_encode($data);
?>

回答by tony gil

i would not recommend dumping distance calculations in your sql statement, even though i admit that the solution presented by 'denil' is ingenious.

我不建议在您的 sql 语句中倾销距离计算,即使我承认“denil”提出的解决方案是巧妙的。

there are 3 downsides: code maintenance, sql server overload AND (above all) the earth is not symmetrical (it is like an old dented baseball that was run over by a truck). this means that you might want to change the code in the future (there are some VERY sophisticated algorithms out there - http://en.wikipedia.org/wiki/Geographical_distance).

有 3 个缺点:代码维护、sql server 过载和(最重要的是)地球不对称(就像一个被卡车碾过的有凹痕的旧棒球)。这意味着您将来可能想要更改代码(有一些非常复杂的算法 - http://en.wikipedia.org/wiki/Geographical_distance)。

i recommend using a separate function that calculates distance with a simple common algorithm (similar if not identical to denil's). i submit this code which is pure php (no need to use googlemaps api):

我建议使用一个单独的函数来计算距离,该函数使用简单的通用算法(如果与 denil 不同,则类似)。我提交了这个纯 php 代码(不需要使用 googlemaps api):

<?php

function distanceGeoPoints ($lat1, $lng1, $lat2, $lng2) {

    $earthRadius = 3958.75;

    $dLat = deg2rad($lat2-$lat1);
    $dLng = deg2rad($lng2-$lng1);


    $a = sin($dLat/2) * sin($dLat/2) +
       cos(deg2rad($lat1)) * cos(deg2rad($lat2)) *
       sin($dLng/2) * sin($dLng/2);
    $c = 2 * atan2(sqrt($a), sqrt(1-$a));
    $dist = $earthRadius * $c;

    // from miles
    $meterConversion = 1609;
    $geopointDistance = $dist * $meterConversion;

    return $geopointDistance;
}

// YOUR CODE HERE
echo distanceGeoPoints(22,50,22.1,50.1);

?>

there are a number of free softwares (try gps trackmaker) that will allow you to check the margin of error for your part of the globe (if you need precision). for the above lat/long pair, the error is within +/- 0.1% (according to local topographers).

有许多免费软件(尝试 gps trackmaker)可以让您检查地球上的误差幅度(如果您需要精确度)。对于上述纬度/经度对,误差在 +/- 0.1% 以内(根据当地地形学家的说法)。

ATTENTION: this formula gives you CARTOGRAPHIC distance (distance at sea level), not TOPOGRAPHIC distance (disconsiders topography).

注意:此公式为您提供 CARTOGRAPHIC 距离(海平面距离),而不是 TOPOGRAPHIC 距离(不考虑地形)。

回答by Latox

I did this a few weeks ago.

几周前我做了这个。

This link is your best bet:

此链接是您最好的选择:

http://code.google.com/apis/maps/articles/phpsqlsearch.html

http://code.google.com/apis/maps/articles/phpsqlsearch.html

Even if you don't use their API, their PHP and SQL query helped really well.

即使您不使用他们的 API,他们的 PHP 和 SQL 查询也非常有用。

回答by denil

Try this query. I found this one when googling but forgot who created it

试试这个查询。我在谷歌搜索时发现了这个,但忘记了是谁创建的

SELECT a.*,
            3956 * 2 * ASIN(SQRT( POWER(SIN(($lat - lat) * pi()/180 / 2), 2) + COS($lat * pi()/180) * COS(lat * pi()/180) *
            POWER(SIN(($long - longi) * pi()/180 / 2), 2) )) as
            distance FROM table
            GROUP BY id HAVING distance <= 500 ORDER by distance ASC

$lat and $long variable is the current position of user. lat and longi is the latitude and longitudle of entries

$lat 和 $long 变量是用户的当前位置。lat 和 longi 是条目的纬度和经度

回答by lbsweek

http://www.geodatasource.com/developers/php

http://www.geodatasource.com/developers/php

<?php

/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
/*::                                                                         :*/
/*::  This routine calculates the distance between two points (given the     :*/
/*::  latitude/longitude of those points). It is being used to calculate     :*/
/*::  the distance between two locations using GeoDataSource(TM) Products    :*/
/*::                                                                         :*/
/*::  Definitions:                                                           :*/
/*::    South latitudes are negative, east longitudes are positive           :*/
/*::                                                                         :*/
/*::  Passed to function:                                                    :*/
/*::    lat1, lon1 = Latitude and Longitude of point 1 (in decimal degrees)  :*/
/*::    lat2, lon2 = Latitude and Longitude of point 2 (in decimal degrees)  :*/
/*::    unit = the unit you desire for results                               :*/
/*::           where: 'M' is statute miles                                   :*/
/*::                  'K' is kilometers (default)                            :*/
/*::                  'N' is nautical miles                                  :*/
/*::  Worldwide cities and other features databases with latitude longitude  :*/
/*::  are available at http://www.geodatasource.com                          :*/
/*::                                                                         :*/
/*::  For enquiries, please contact [email protected]                  :*/
/*::                                                                         :*/
/*::  Official Web site: http://www.geodatasource.com                        :*/
/*::                                                                         :*/
/*::         GeoDataSource.com (C) All Rights Reserved 2014                  :*/
/*::                                                                         :*/
/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
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;
      }
}

echo distance(32.9697, -96.80322, 29.46786, -98.53506, "M") . " Miles<br>";
echo distance(32.9697, -96.80322, 29.46786, -98.53506, "K") . " Kilometers<br>";
echo distance(32.9697, -96.80322, 29.46786, -98.53506, "N") . " Nautical Miles<br>";

?>

回答by Roman Losev

Tested like 3 functions and 3 queries and only one showed good distance:

测试了 3 个函数和 3 个查询,只有一个显示良好的距离:

In meters:

以米为单位:

SELECT *,
(
    (((acos(sin((".$latitude."*pi()/180)) * sin((`latitude`*pi()/180))+cos((".$latitude."*pi()/180))    * cos((`latitude`*pi()/180)) * cos(((".$longitude."- `longitude`)*pi()/180))))*180/pi())*60*1.1515*1.609344) 
    * 1000
) as `distance`
FROM `table`
ORDER BY `distance` ASC

In kilometers:

公里:

SELECT *,
(
    (((acos(sin((".$latitude."*pi()/180)) * sin((`latitude`*pi()/180))+cos((".$latitude."*pi()/180))    * cos((`latitude`*pi()/180)) * cos(((".$longitude."- `longitude`)*pi()/180))))*180/pi())*60*1.1515*1.609344) 
) as `distance`
FROM `table`
ORDER BY `distance` ASC

回答by sabin

Use distance-matrix google api to calculate distance between latitude and longitude.

使用 distance-matrix google api 计算纬度和经度之间的距离。

$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_URL, 
    'https://maps.googleapis.com/maps/api/distancematrix/json?origins='.$prev_add.'&destinations='.$curr_add.'&key=keyyouhavetogenerate'
);
$content = curl_exec($ch);
$array = json_decode($content);
$obj = json_decode($content, TRUE);

$distance = $obj['rows'][0]['elements'][0]['distance']['text'];

to use this api you will need key,to know more about how to generate key visit https://developers.google.com/maps/documentation/distance-matrix/intro

要使用此 API,您将需要密钥,要了解有关如何生成密钥的更多信息,请访问https://developers.google.com/maps/documentation/distance-matrix/intro

回答by Riajul Islam

Simple and easiest way

简单易行的方法

<?php
    $lat1 = Yourstart_latitude;
    $lon1 = Yourstart_longitude;
    $lat2 = Yourend_latitude;
    $lon2 = Yourend_longitude;
    $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 = 'K';
                                $km   = $miles*1.609344;
                              echo number_format($km,1);
                            ?>

回答by ahinkle

For those trying to stay away from Google (and others) APIs, I've been using this one for a while.

对于那些试图远离 Google(和其他)API 的人,我一直在使用这个 API。

Because the earth is round, it will have some weird results for large scale radius submissions. It will work fine for locations within ~500 miles of each other.

因为地球是圆的,大尺度半径投稿会出现一些奇怪的结果。它适用于彼此相距约 500 英里的位置。

/**
 * The max Latitude and Longitude coordinates within a specified milage radius.
 * 
 * @param int $miles
 * @param float $longitude
 * @param float $latitude
 *
 * @return array
 */
public function getMaxCoordinates($miles = 50, $longitude, $latitude) {
    $oneDegree = 69; // 69 Miles = 1 degree

    // Calculate the minimum/maximum possible coordinates.
    $lng_min = $longitude - $miles / abs(cos(deg2rad($latitude)) * $oneDegree);
    $lng_max = $longitude + $miles / abs(cos(deg2rad($latitude)) * $oneDegree);
    $lat_min = $latitude  - ($miles / $oneDegree);
    $lat_max = $latitude  + ($miles / $oneDegree);

    return ([
        'lat_max' => $lat_max,
        'lat_min' => $lat_min,
        'lng_max' => $lng_max,
        'lng_min' => $lng_min,
        'miles'   => $miles,
    ]);
}

回答by Ragnar

This query was perfect for me:

这个查询对我来说是完美的:

$latitude = "23.139422";  //your current lat
$longitude = "-82.382617"; //your current long

SELECT ( 3959 * acos( cos( radians( '.$latitude.' ) ) * cos( radians( latitude ) ) * 
 cos( radians( longitude ) - radians( '.$longitude.' ) ) + sin( radians( '.$latitude.' )
 ) * sin( radians( latitude ) ) ) ) AS distance from TABLE 
 HAVING distance <= 100 ORDER BY distance ASC