У меня есть долгота и широта как строка на PHP, как показано ниже
49.648881 -103.575312
И я хочу взять это и посмотреть в массиве значений, чтобы найти ближайший. Массив выглядит так:
array( '0'=>array('item1','otheritem1details....','55.645645','-42.5323'), '1'=>array('item1','otheritem1details....','100.645645','-402.5323') );
Я хочу вернуть массив, у которого есть ближайший длинный и парень. В этом случае это будет первый (и да, я знаю, -400 не является возможным значением).
Есть ли быстрый и простой способ сделать это? Я попробовал поиск массива, но это не сработало.
Разностный код
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; } }
Сначала вам нужно сопоставить расстояние каждого элемента до контрольной точки.
Затем вы сортируете карту, а затем можете определить, у которой самая низкая (или самая высокая, если вы отмените поиск):
$ref = array(49.648881, -103.575312); $items = array( '0' => array('item1','otheritem1details....','55.645645','-42.5323'), '1' => array('item1','otheritem1details....','100.645645','-402.5323') ); $distances = array_map(function($item) use($ref) { $a = array_slice($item, -2); return distance($a, $ref); }, $items); asort($distances); echo 'Closest item is: ', var_dump($items[key($distances)]);
Вывод:
Closest item is: array(4) { [0]=> string(5) "item1" [1]=> string(21) "otheritem1details...." [2]=> string(9) "55.645645" [3]=> string(8) "-42.5323" }
Позаботьтесь, у вас есть правильный порядок лат и долго.
Функция расстояния (только заголовок слегка изменился, и единицы были сброшены):
function distance($a, $b) { list($lat1, $lon1) = $a; list($lat2, $lon2) = $b; $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; return $miles; }
Скорее, используя закон косинусов для расстояния, вы можете использовать приближение плоской земли. Уравнения с плоской землей уменьшают количество триг-функций в расчете. Δlat, Δlon – это разница между вашей контрольной точкой и контрольной точкой.
Эта формула не была бы точной для дальних навигации (в тысячах миль), но для этой конкретной проблемы вы не очень заинтересованы в точном расстоянии, но кто ближе всего для меня. Это более простая формулировка, которая должна дать вам это.
x = Δlon * cos(lat) // lat/lon are in radians! y = Δlat distance = R * sqrt( x² + y² ) // R is radius of the earth; // typical value is 6371 km
Ссылка: http://www.movable-type.co.uk/scripts/latlong.html
Код расстояния
function distanceMeters($lat1, $lon1, $lat2, $lon2) { $x = deg2rad( $lon1 - $lon2 ) * cos( deg2rad( $lat1 ) ); $y = deg2rad( $lat1 - $lat2 ); $dist = 6371000.0 * sqrt( $x*$x + $y*$y ); return $dist; }
Это не быстрый и простой способ сделать это. Вы должны проходить через все элементы и вычислять расстояние между ними и отправной точкой, сохранять результат и повторять, сохраняя результат, только если он ниже предыдущего.
Итерации через массив, сравнивая значения с тем, что у вас есть. Если значение меньше вашего текущего сохраненного значения (или если у вас нет сохраненного значения), сохраните это значение вместо этого, иначе выбросьте его.
$closest = null; foreach($array as $key => $value){ $distance = //compare distance here; if ($closest === null || $closest > $distance) { $closest = $distance; }; };
Конечно, это будет затруднено тем, что широта и долгота находятся на сфере, а долготы 179 и -179 ближе, чем 90 и 179.