PHP возвращает NaN

У меня есть функция, которая рассчитывает расстояние между двумя GPS-координатами. Затем я получаю все координаты из базы данных и перебираю их все, чтобы получить расстояние между текущим и предыдущим, а затем добавляю это в массив для конкретного устройства GPS. Почему-то это возврат NaN. Я попытался привести его к двойному, целому и округлению числа.

Вот мой PHP-код:

function distance($lat1, $lon1, $lat2, $lon2) {
$lat1 = round($lat1, 3);
$lon1 = round($lon1, 3);
$lat2 = round($lat2, 3);
$lon2 = round($lon2, 3);
$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;
if($miles < 0) $miles = $miles * -1;
return ($miles * 1.609344);
}
$this->db->query("SELECT * FROM `gps_loc` WHERE `imeiN`='" . $sql . "' AND `updatetime`>=$timeLimit ORDER BY `_id` DESC");
$dist = array();
$dist2 = array();
while($row = $this->db->getResults()) {
$dist2[$row['imeiN']] = 0;
$dist[$row['imeiN']][]["lat"] = $row['lat'];
$dist[$row['imeiN']][count($dist[$row['imeiN']]) - 1]["lng"] = $row['lon'];
}

foreach($dist as $key=>$d) {
$a = 0;
$b = 0;
foreach($dist[$key] as $n) {
if($a > 0) {
$dist2[$key] += $this->distance($n['lat'], $n['lng'], $dist[$key][$a - 1]['lat'], $dist[$key][$a - 1]['lng']);
}
$a++;
}

}
echo json_encode($dist2);

-1

Решение

Значения, которые вы извлекаете из базы данных, могут быть строками, которые могут вызвать эту проблему.

Вы также можете проверить вопросы, которые Колинк поднял в своем посте.

2

Другие решения

Диапазон sin() а также cos() между -1 и 1. Поэтому в вашем первом расчете $dist диапазон результатов от -2 до 2. Затем вы передаете это acos(), чей аргумент должен быть между -1 и 1. Таким образом acos(2) например дает NaN. Все остальное оттуда тоже дает NaN.

Я не уверен, какая именно формула должна быть, но именно отсюда исходит ваш NaN. Дважды проверьте свою тригонометрию.

4

Алгоритм будет выдавать NaN, если точки расположены слишком близко друг к другу. В этом случае $ dist получает значение 1. acos (1) равно NaN. Все последующие вычисления также дают NaN.
Вы округляете координаты в качестве первого шага, поэтому становится более вероятным, что значения станут равными после округления, и получится NaN

4

Это сферический закон косинусов, который вы используете? Я бы переключился на формулу Haversine:

function distance($lat1, $lon1, $lat2, $lon2)
{
$radius = 3959;  //approximate mean radius of the earth in miles, can change to any unit of measurement, will get results back in that unit

$delta_Rad_Lat = deg2rad($lat2 - $lat1);  //Latitude delta in radians
$delta_Rad_Lon = deg2rad($lon2 - $lon1);  //Longitude delta in radians
$rad_Lat1 = deg2rad($lat1);  //Latitude 1 in radians
$rad_Lat2 = deg2rad($lat2);  //Latitude 2 in radians

$sq_Half_Chord = sin($delta_Rad_Lat / 2) * sin($delta_Rad_Lat / 2) + cos($rad_Lat1) * cos($rad_Lat2) * sin($delta_Rad_Lon / 2) * sin($delta_Rad_Lon / 2);  //Square of half the chord length
$ang_Dist_Rad = 2 * asin(sqrt($sq_Half_Chord));  //Angular distance in radians
$distance = $radius * $ang_Dist_Rad;

return $distance;
}

Вы должны быть в состоянии изменить радиус Земли на любую форму измерения от радиуса в световых годах до радиуса в нанометрах и получить правильное число обратно для используемой единицы.

0

Спасибо за все ответы здесь — в результате я сделал функцию, которая объединяет вычисления и тесты для NaN в каждом, если оба не являются NaN — он усредняет вычисления, если один является NaN, а другой нет — он использует тот это верно и выдает отчет об ошибках для координат, которые не смогли выполнить одно из вычислений:

function distance_slc($lat1, $lon1, $lat2, $lon2) {
$earth_radius = 3960.00; # in miles
$distance  = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) + cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($lon2-$lon1)) ;
$distance  = acos($distance);
$distance  = rad2deg($distance);
$distance  = $distance * 60 * 1.1515;
$distance1  = round($distance, 4);

// use a second method as well and average
$radius = 3959;  //approximate mean radius of the earth in miles, can change to any unit of measurement, will get results back in that unit
$delta_Rad_Lat = deg2rad($lat2 - $lat1);  //Latitude delta in radians
$delta_Rad_Lon = deg2rad($lon2 - $lon1);  //Longitude delta in radians
$rad_Lat1 = deg2rad($lat1);  //Latitude 1 in radians
$rad_Lat2 = deg2rad($lat2);  //Latitude 2 in radians

$sq_Half_Chord = sin($delta_Rad_Lat / 2) * sin($delta_Rad_Lat / 2) + cos($rad_Lat1) * cos($rad_Lat2) * sin($delta_Rad_Lon / 2) * sin($delta_Rad_Lon / 2);  //Square of half the chord length
$ang_Dist_Rad = 2 * asin(sqrt($sq_Half_Chord));  //Angular distance in radians
$distance2 = $radius * $ang_Dist_Rad;
//echo "distance=$distance and distance2=$distance2\n";
$avg_distance=-1;
$distance1=acos(2);
if((!is_nan($distance1)) && (!is_nan($distance2))){
$avg_distance=($distance1+$distance2)/2;
} else {
if(!is_nan($distance1)){
$avg_distance=$distance1;
try{
throw new Exception("distance1=NAN with lat1=$lat1 lat2=$lat2 lon1=$lon1 lon2=$lon2");
} catch(Exception $e){
trigger_error($e->getMessage());
trigger_error($e->getTraceAsString());
}
}
if(!is_nan($distance2)){
$avg_distance=$distance2;
try{
throw new Exception("distance1=NAN with lat1=$lat1 lat2=$lat2 lon1=$lon1 lon2=$lon2");
} catch(Exception $e){
trigger_error($e->getMessage());
trigger_error($e->getTraceAsString());
}
}
}
return $avg_distance;
}

HTH кто-то в будущем, а также.

0
По вопросам рекламы [email protected]