Вычисление расстояния между двумя GPS координатами
В данной статье представлена реализация алгоритма вычисления расстояния между двумя точками, с известными GPS координатами
В данной статье представлена реализация алгоритма вычисления расстояния между двумя точками, с известными GPS координатами
JS
function latlng2distance(lat1, long1, lat2, long2) { //радиус Земли var R = 6372795; //перевод коордитат в радианы lat1 *= Math.PI / 180; lat2 *= Math.PI / 180; long1 *= Math.PI / 180; long2 *= Math.PI / 180; //вычисление косинусов и синусов широт и разницы долгот var cl1 = Math.cos(lat1); var cl2 = Math.cos(lat2); var sl1 = Math.sin(lat1); var sl2 = Math.sin(lat2); var delta = long2 - long1; var cdelta = Math.cos(delta); var sdelta = Math.sin(delta); //вычисления длины большого круга var y = Math.sqrt(Math.pow(cl2 * sdelta, 2) + Math.pow(cl1 * sl2 - sl1 * cl2 * cdelta, 2)); var x = sl1 * sl2 + cl1 * cl2 * cdelta; var ad = Math.atan2(y, x); var dist = ad * R; //расстояние между двумя координатами в метрах return dist }
PHP
function latlng2distance($lat1, $long1, $lat2, $long2) { //радиус Земли $R = 6372795; //перевод коордитат в радианы $lat1 *= pi() / 180; $lat2 *= pi() / 180; $long1 *= pi() / 180; $long2 *= pi() / 180; //вычисление косинусов и синусов широт и разницы долгот $cl1 = cos($lat1); $cl2 = cos($lat2); $sl1 = sin($lat1); $sl2 = sin($lat2); $delta = $long2 - $long1; $cdelta = cos($delta); $sdelta = sin($delta); //вычисления длины большого круга $y = sqrt(pow($cl2 * $sdelta, 2) + pow($cl1 * $sl2 - $sl1 * $cl2 * $cdelta, 2)); $x = $sl1 * $sl2 + $cl1 * $cl2 * $cdelta; $ad = atan2($y, $x); $dist = $ad * $R; //расстояние между двумя координатами в метрах return $dist; }
еще один более точный вариант Вычисления расстояние между двумя точками земли, в GPS координатах стандарта WGS84
define('MAJOR_AXIS', 6378137.0); //meters define('MINOR_AXIS', 6356752.3142); //meters define('MAJOR_AXIS_POW_2', pow(MAJOR_AXIS, 2)); //meters define('MINOR_AXIS_POW_2', pow(MINOR_AXIS, 2)); //meters /* $gps_1['lat'] - latitude (широта) $gps_1['lon'] - longitude (долгота) $gps_1['point_elevation'] (высота точки) // == 0 if this is sea. but must be defined! */ //get arrays with gps coordinates, returns earth terrestrial distance between 2 points function get_distance_between_2_points($gps_1, $gps_2, $decart=false) { if(!$decart) { $true_angle_1 = get_true_angle($gps_1); $true_angle_2 = get_true_angle($gps_2); $point_radius_1 = get_point_radius($gps_1, $true_angle_1); $point_radius_2 = get_point_radius($gps_2, $true_angle_2); $earth_point_1_x = $point_radius_1 * cos(deg2rad($true_angle_1)); $earth_point_1_y = $point_radius_1 * sin(deg2rad($true_angle_1)); $earth_point_2_x = $point_radius_2 * cos(deg2rad($true_angle_2)); $earth_point_2_y = $point_radius_2 * sin(deg2rad($true_angle_2)); $x = get_distance_between_2_points(array('lat'=>$earth_point_1_x, 'lon'=>$earth_point_1_y), array('lat'=>$earth_point_2_x, 'lon'=>$earth_point_2_y), true); $y = pi() * ( ($earth_point_1_x + $earth_point_2_x) / 360 ) * ( $gps_1['lon'] - $gps_2['lon'] ); return sqrt( pow($x,2) + pow($y,2) ); } else { return sqrt(pow(($gps_1['lat'] - $gps_2['lat']), 2) + pow(($gps_1['lon'] - $gps_2['lon']), 2)); } } //returns degree's decimal measure, getting degree, minute and second function get_decimal_degree($deg=0, $min=0, $sec=0) { return ($deg<0) ? (-1*(abs($deg) + (abs($min)/60) + (abs($sec)/3600))) : (abs($deg) + (abs($min)/60) + (abs($sec)/3600)); } // get point, returns true angle function get_true_angle($gps) { return atan( ( (MINOR_AXIS_POW_2 / MAJOR_AXIS_POW_2) * tan(deg2rad( $gps['lat'])) ) ) * 180/pi(); } //get point and true angle, returns radius of small circle (radius between meridians) function get_point_radius($gps, $true_angle) { return (1 / sqrt((pow(cos(deg2rad($true_angle)), 2) / MAJOR_AXIS_POW_2) + (pow(sin(deg2rad($true_angle)), 2) / MINOR_AXIS_POW_2))) + $gps['point_elevation']; } function check_lat($lat) { if($lat>=0 && $lat<=90) { return 'north'; } else if($lat>=-90 && $lat<=0) { return 'south'; } return false; } function check_lon($lon) { if($lon>=0 && $lon<=180) { return 'east'; } else if($lon>=-180 && $lon<=0) { return 'west'; } return false; }