Skip to content

Instantly share code, notes, and snippets.

@Lexx918
Created June 10, 2015 14:36
Show Gist options
  • Save Lexx918/65c57edf7e803ce9f403 to your computer and use it in GitHub Desktop.
Save Lexx918/65c57edf7e803ce9f403 to your computer and use it in GitHub Desktop.
distance
<?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