Created
June 10, 2015 14:36
-
-
Save Lexx918/65c57edf7e803ce9f403 to your computer and use it in GitHub Desktop.
distance
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* author: domino, 28 апр 2008 | |
* http://phpclub.ru/talk/members/domino.521/ | |
* http://phpclub.ru/talk/threads/%D1%80%D0%B0%D1%81%D1%81%D1%82%D0%BE%D1%8F%D0%BD%D0%B8%D0%B5-%D0%BC%D0%B5%D0%B6%D0%B4%D1%83-%D0%B4%D0%B2%D1%83%D0%BC%D1%8F-%D1%82%D0%BE%D1%87%D0%BA%D0%B0%D0%BC%D0%B8-%D0%B7%D0%B5%D0%BC%D0%BB%D0%B8-%D0%B2-gps-%D0%BA%D0%BE%D0%BE%D1%80%D0%B4%D0%B8%D0%BD%D0%B0%D1%82%D0%B0%D1%85-%D1%81%D1%82%D0%B0%D0%BD%D0%B4%D0%B0%D1%80%D1%82%D0%B0-wgs84.54170/ | |
* | |
* $gps_1['lat'] - latitude (широта) | |
* $gps_1['lon'] - longitude (долгота) | |
* $gps_1['point_elevation'] (высота точки) // == 0 if this is sea. but must be defined! | |
*/ | |
class GPS { | |
const COORDINATES_FORMAT = 'WGS84'; | |
const MAJOR_AXIS = 6378137.0; // meters | |
const MINOR_AXIS = 6356752.3142; // meters | |
const MAJOR_AXIS_POW_2 = 40680631590769; // meters, pow(MAJOR_AXIS, 2) | |
const MINOR_AXIS_POW_2 = 40408299984087; // meters, pow(MINOR_AXIS, 2) | |
/** | |
* get arrays with gps coordinates, returns earth terrestrial distance between 2 points | |
*/ | |
public static function get_distance_between_2_points($gps_1, $gps_2, $decart = false) | |
{ | |
if ($decart) { | |
return sqrt(pow(($gps_1['lat'] - $gps_2['lat']), 2) + pow(($gps_1['lon'] - $gps_2['lon']), 2)); | |
} | |
$true_angle_1 = self::get_true_angle($gps_1); | |
$true_angle_2 = self::get_true_angle($gps_2); | |
$point_radius_1 = self::get_point_radius($gps_1, $true_angle_1); | |
$point_radius_2 = self::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 = self::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) ); | |
} | |
/** | |
* returns degree's decimal measure, getting degree, minute and second | |
*/ | |
public static function get_decimal_degree($deg = 0, $min = 0, $sec = 0) | |
{ | |
return $deg < 0 | |
? (abs($deg) + abs($min)/60 + abs($sec)/3600) * -1 | |
: abs($deg) + abs($min)/60 + abs($sec)/3600; | |
} | |
/** | |
* get point, returns true angle | |
*/ | |
public static function get_true_angle($gps) | |
{ | |
return atan( | |
(self::MINOR_AXIS_POW_2 / self::MAJOR_AXIS_POW_2) * | |
tan(deg2rad($gps['lat'])) | |
) * 180/pi(); | |
} | |
/** | |
* get point and true angle, returns radius of small circle (radius between meridians) | |
*/ | |
public static function get_point_radius($gps, $true_angle) | |
{ | |
return $gps['point_elevation'] + 1 / sqrt( | |
pow(cos(deg2rad($true_angle)), 2) / self::MAJOR_AXIS_POW_2 + | |
pow(sin(deg2rad($true_angle)), 2) / self::MINOR_AXIS_POW_2 | |
); | |
} | |
public static function check_lat($lat) | |
{ | |
if ($lat >= 0 && $lat <= 90) { | |
return 'north'; | |
} elseif ($lat >= -90 && $lat <= 0) { | |
return 'south'; | |
} | |
return false; | |
} | |
public static function check_lon($lon) | |
{ | |
if ($lon >= 0 && $lon <= 180) { | |
return 'east'; | |
} elseif ($lon >= -180 && $lon <= 0) { | |
return 'west'; | |
} | |
return false; | |
} | |
} | |
/* test: | |
$gps_1 = ['lat' => 55.75368061, 'lon' => 37.61991869, 'point_elevation' => 0]; // Москва | |
$gps_2 = ['lat' => 52.76502378, 'lon' => 55.81304567, 'point_elevation' => 0]; // мой комп у окна в моей комнате в моём доме | |
echo "~1230 === ".(GPS::get_distance_between_2_points($gps_1, $gps_2)/1000)." ?\n"; | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment