PHP에서 두 좌표 사이의 거리 측정
안녕 나는 위도와 경도를 가진 두 점 사이의 거리를 계산할 필요가있다.
외부 API에 대한 호출을 피하고 싶습니다.
PHP에서 Haversine Formula를 구현하려고했습니다.
코드는 다음과 같습니다.
class CoordDistance
{
public $lat_a = 0;
public $lon_a = 0;
public $lat_b = 0;
public $lon_b = 0;
public $measure_unit = 'kilometers';
public $measure_state = false;
public $measure = 0;
public $error = '';
public function DistAB()
{
$delta_lat = $this->lat_b - $this->lat_a ;
$delta_lon = $this->lon_b - $this->lon_a ;
$earth_radius = 6372.795477598;
$alpha = $delta_lat/2;
$beta = $delta_lon/2;
$a = sin(deg2rad($alpha)) * sin(deg2rad($alpha)) + cos(deg2rad($this->lat_a)) * cos(deg2rad($this->lat_b)) * sin(deg2rad($beta)) * sin(deg2rad($beta)) ;
$c = asin(min(1, sqrt($a)));
$distance = 2*$earth_radius * $c;
$distance = round($distance, 4);
$this->measure = $distance;
}
}
공공 거리가있는 특정 지점으로 테스트하면 신뢰할 수있는 결과를 얻지 못합니다.
원래 수식이나 구현에 오류가 있는지 이해할 수 없습니다.
얼마 전 나는 헤르 세인 공식의 예를 작성하여 내 웹 사이트에 게시했습니다.
/**
* Calculates the great-circle distance between two points, with
* the Haversine formula.
* @param float $latitudeFrom Latitude of start point in [deg decimal]
* @param float $longitudeFrom Longitude of start point in [deg decimal]
* @param float $latitudeTo Latitude of target point in [deg decimal]
* @param float $longitudeTo Longitude of target point in [deg decimal]
* @param float $earthRadius Mean earth radius in [m]
* @return float Distance between points in [m] (same as earthRadius)
*/
function haversineGreatCircleDistance(
$latitudeFrom, $longitudeFrom, $latitudeTo, $longitudeTo, $earthRadius = 6371000)
{
// convert from degrees to radians
$latFrom = deg2rad($latitudeFrom);
$lonFrom = deg2rad($longitudeFrom);
$latTo = deg2rad($latitudeTo);
$lonTo = deg2rad($longitudeTo);
$latDelta = $latTo - $latFrom;
$lonDelta = $lonTo - $lonFrom;
$angle = 2 * asin(sqrt(pow(sin($latDelta / 2), 2) +
cos($latFrom) * cos($latTo) * pow(sin($lonDelta / 2), 2)));
return $angle * $earthRadius;
}
parameter 파라미터로 전달할 때와 동일한 단위로 거리를 다시 얻습니다 $earthRadius
. 기본값은 6371000 미터이므로 결과도 [m]이됩니다. 마일 단위로 결과를 얻으려면 예를 들어 3959 마일을 통과 $earthRadius
하면 결과는 [mi]가됩니다. 제 생각에는 달리 할 특별한 이유가 없다면 SI 단위를 고수하는 것이 좋습니다.
편집하다:
TreyA가 올바르게 지적한 바와 같이, Haversine 공식은 반올림 오차로 인해 대 지점에 약점이 있습니다 ( 소 거리 에서는 안정적 임). 그것들을 해결하기 위해 대신 Vincenty 공식을 사용할 수 있습니다 .
/**
* Calculates the great-circle distance between two points, with
* the Vincenty formula.
* @param float $latitudeFrom Latitude of start point in [deg decimal]
* @param float $longitudeFrom Longitude of start point in [deg decimal]
* @param float $latitudeTo Latitude of target point in [deg decimal]
* @param float $longitudeTo Longitude of target point in [deg decimal]
* @param float $earthRadius Mean earth radius in [m]
* @return float Distance between points in [m] (same as earthRadius)
*/
public static function vincentyGreatCircleDistance(
$latitudeFrom, $longitudeFrom, $latitudeTo, $longitudeTo, $earthRadius = 6371000)
{
// convert from degrees to radians
$latFrom = deg2rad($latitudeFrom);
$lonFrom = deg2rad($longitudeFrom);
$latTo = deg2rad($latitudeTo);
$lonTo = deg2rad($longitudeTo);
$lonDelta = $lonTo - $lonFrom;
$a = pow(cos($latTo) * sin($lonDelta), 2) +
pow(cos($latFrom) * sin($latTo) - sin($latFrom) * cos($latTo) * cos($lonDelta), 2);
$b = sin($latFrom) * sin($latTo) + cos($latFrom) * cos($latTo) * cos($lonDelta);
$angle = atan2(sqrt($a), $b);
return $angle * $earthRadius;
}
신뢰할 수있는 결과를 제공하는 이 코드 를 찾았습니다 .
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>";
@martinstoeckli 및 @Janith Chinthana 답변에 추가되었습니다 . 어떤 알고리즘이 가장 빠른지 궁금한 사람들을 위해 성능 테스트를 작성했습니다 . 최고의 성능 결과는 codexworld.com의 최적화 된 기능을 보여줍니다 .
/**
* Optimized algorithm from http://www.codexworld.com
*
* @param float $latitudeFrom
* @param float $longitudeFrom
* @param float $latitudeTo
* @param float $longitudeTo
*
* @return float [km]
*/
function codexworldGetDistanceOpt($latitudeFrom, $longitudeFrom, $latitudeTo, $longitudeTo)
{
$rad = M_PI / 180;
//Calculate distance from latitude and longitude
$theta = $longitudeFrom - $longitudeTo;
$dist = sin($latitudeFrom * $rad)
* sin($latitudeTo * $rad) + cos($latitudeFrom * $rad)
* cos($latitudeTo * $rad) * cos($theta * $rad);
return acos($dist) / $rad * 60 * 1.853;
}
테스트 결과는 다음과 같습니다.
Test name Repeats Result Performance
codexworld-opt 10000 0.084952 sec +0.00%
codexworld 10000 0.104127 sec -22.57%
custom 10000 0.107419 sec -26.45%
custom2 10000 0.111576 sec -31.34%
custom1 10000 0.136691 sec -60.90%
vincenty 10000 0.165881 sec -95.26%
다음은 위도와 경도 사이의 거리를 계산하기위한 간단하고 완벽한 코드입니다. 다음 코드는 여기에서 발견되었습니다-http: //www.codexworld.com/distance-between-two-addresses-google-maps-api-php/
$latitudeFrom = '22.574864';
$longitudeFrom = '88.437915';
$latitudeTo = '22.568662';
$longitudeTo = '88.431918';
//Calculate distance from latitude and longitude
$theta = $longitudeFrom - $longitudeTo;
$dist = sin(deg2rad($latitudeFrom)) * sin(deg2rad($latitudeTo)) + cos(deg2rad($latitudeFrom)) * cos(deg2rad($latitudeTo)) * cos(deg2rad($theta));
$dist = acos($dist);
$dist = rad2deg($dist);
$miles = $dist * 60 * 1.1515;
$distance = ($miles * 1.609344).' km';
짧고 빠른 것을 좋아하는 사람들을 위해 (deg2rad ()를 호출하지 않음).
function circle_distance($lat1, $lon1, $lat2, $lon2) {
$rad = M_PI / 180;
return acos(sin($lat2*$rad) * sin($lat1*$rad) + cos($lat2*$rad) * cos($lat1*$rad) * cos($lon2*$rad - $lon1*$rad)) * 6371;// Kilometers
}
이 멋진 결과를 제공하십시오
function getDistance($point1_lat, $point1_long, $point2_lat, $point2_long, $unit = 'km', $decimals = 2) {
// Calculate the distance in degrees
$degrees = rad2deg(acos((sin(deg2rad($point1_lat))*sin(deg2rad($point2_lat))) + (cos(deg2rad($point1_lat))*cos(deg2rad($point2_lat))*cos(deg2rad($point1_long-$point2_long)))));
// Convert the distance in degrees to the chosen unit (kilometres, miles or nautical miles)
switch($unit) {
case 'km':
$distance = $degrees * 111.13384; // 1 degree = 111.13384 km, based on the average diameter of the Earth (12,735 km)
break;
case 'mi':
$distance = $degrees * 69.05482; // 1 degree = 69.05482 miles, based on the average diameter of the Earth (7,913.1 miles)
break;
case 'nmi':
$distance = $degrees * 59.97662; // 1 degree = 59.97662 nautic miles, based on the average diameter of the Earth (6,876.3 nautical miles)
}
return round($distance, $decimals);
}
아주 오래된 질문이지만 Google지도와 동일한 결과를 반환하는 PHP 코드에 관심이있는 사람들은 다음과 같은 일을합니다.
/**
* Computes the distance between two coordinates.
*
* Implementation based on reverse engineering of
* <code>google.maps.geometry.spherical.computeDistanceBetween()</code>.
*
* @param float $lat1 Latitude from the first point.
* @param float $lng1 Longitude from the first point.
* @param float $lat2 Latitude from the second point.
* @param float $lng2 Longitude from the second point.
* @param float $radius (optional) Radius in meters.
*
* @return float Distance in meters.
*/
function computeDistance($lat1, $lng1, $lat2, $lng2, $radius = 6378137)
{
static $x = M_PI / 180;
$lat1 *= $x; $lng1 *= $x;
$lat2 *= $x; $lng2 *= $x;
$distance = 2 * asin(sqrt(pow(sin(($lat1 - $lat2) / 2), 2) + cos($lat1) * cos($lat2) * pow(sin(($lng1 - $lng2) / 2), 2)));
return $distance * $radius;
}
I've tested with various coordinates and it works perfectly.
I think it should be faster then some alternatives too. But didn't tested that.
Hint: Google Maps uses 6378137 as Earth radius. So using it with other algorithms might work as well.
For exact values do it like that:
public function DistAB()
{
$delta_lat = $this->lat_b - $this->lat_a ;
$delta_lon = $this->lon_b - $this->lon_a ;
$a = pow(sin($delta_lat/2), 2);
$a += cos(deg2rad($this->lat_a9)) * cos(deg2rad($this->lat_b9)) * pow(sin(deg2rad($delta_lon/29)), 2);
$c = 2 * atan2(sqrt($a), sqrt(1-$a));
$distance = 2 * $earth_radius * $c;
$distance = round($distance, 4);
$this->measure = $distance;
}
Hmm I think that should do it...
Edit:
For formulars and at least JS-implementations try: http://www.movable-type.co.uk/scripts/latlong.html
Dare me... I forgot to deg2rad all the values in the circle-functions...
Hello here Code For Get Distance and Time Using Two Different Lat and Long
$url ="https://maps.googleapis.com/maps/api/distancematrix/json?units=imperial&origins=16.538048,80.613266&destinations=23.0225,72.5714";
$ch = curl_init();
// Disable SSL verification
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
// Will return the response, if false it print the response
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// Set the url
curl_setopt($ch, CURLOPT_URL,$url);
// Execute
$result=curl_exec($ch);
// Closing
curl_close($ch);
$result_array=json_decode($result);
print_r($result_array);
You can check Example Below Link get time between two different locations using latitude and longitude in php
Try this function out to calculate distance between to points of latitude and longitude
function calculateDistanceBetweenTwoPoints($latitudeOne='', $longitudeOne='', $latitudeTwo='', $longitudeTwo='',$distanceUnit ='',$round=false,$decimalPoints='')
{
if (empty($decimalPoints))
{
$decimalPoints = '3';
}
if (empty($distanceUnit)) {
$distanceUnit = 'KM';
}
$distanceUnit = strtolower($distanceUnit);
$pointDifference = $longitudeOne - $longitudeTwo;
$toSin = (sin(deg2rad($latitudeOne)) * sin(deg2rad($latitudeTwo))) + (cos(deg2rad($latitudeOne)) * cos(deg2rad($latitudeTwo)) * cos(deg2rad($pointDifference)));
$toAcos = acos($toSin);
$toRad2Deg = rad2deg($toAcos);
$toMiles = $toRad2Deg * 60 * 1.1515;
$toKilometers = $toMiles * 1.609344;
$toNauticalMiles = $toMiles * 0.8684;
$toMeters = $toKilometers * 1000;
$toFeets = $toMiles * 5280;
$toYards = $toFeets / 3;
switch (strtoupper($distanceUnit))
{
case 'ML'://miles
$toMiles = ($round == true ? round($toMiles) : round($toMiles, $decimalPoints));
return $toMiles;
break;
case 'KM'://Kilometers
$toKilometers = ($round == true ? round($toKilometers) : round($toKilometers, $decimalPoints));
return $toKilometers;
break;
case 'MT'://Meters
$toMeters = ($round == true ? round($toMeters) : round($toMeters, $decimalPoints));
return $toMeters;
break;
case 'FT'://feets
$toFeets = ($round == true ? round($toFeets) : round($toFeets, $decimalPoints));
return $toFeets;
break;
case 'YD'://yards
$toYards = ($round == true ? round($toYards) : round($toYards, $decimalPoints));
return $toYards;
break;
case 'NM'://Nautical miles
$toNauticalMiles = ($round == true ? round($toNauticalMiles) : round($toNauticalMiles, $decimalPoints));
return $toNauticalMiles;
break;
}
}
Then use the fucntion as
echo calculateDistanceBetweenTwoPoints('11.657740','77.766270','11.074820','77.002160','ML',true,5);
Hope it helps
The multiplier is changed at every coordinate because of the great circle distance theory as written here :
http://en.wikipedia.org/wiki/Great-circle_distance
and you can calculate the nearest value using this formula described here:
http://en.wikipedia.org/wiki/Great-circle_distance#Worked_example
the key is converting each degree - minute - second value to all degree value:
N 36°7.2', W 86°40.2' N = (+) , W = (-), S = (-), E = (+)
referencing the Greenwich meridian and Equator parallel
(phi) 36.12° = 36° + 7.2'/60'
(lambda) -86.67° = 86° + 40.2'/60'
참고URL : https://stackoverflow.com/questions/10053358/measuring-the-distance-between-two-coordinates-in-php
'development' 카테고리의 다른 글
Visual Studio 2010 IntelliSense는 기본값을 선택하지 않고 표시 만합니다. (0) | 2020.07.06 |
---|---|
UITableView가 정적 셀로 설정되었습니다. (0) | 2020.07.06 |
머티리얼 디자인 아이콘을 안드로이드 프로젝트로 가져 오기 (0) | 2020.07.06 |
GitHub로 푸시 오류-저장소 데이터베이스에 객체를 추가 할 수있는 권한이 없습니다 (0) | 2020.07.06 |
PHP에는 스레딩이 있습니까? (0) | 2020.07.06 |