Этот пример и код java-скрипта из текста ссылки
Посмотрите на раздел о линиях румбума.
Учитывая начальную точку и расстояние d вдоль постоянного подшипника θ, это вычислит точку назначения. Если вы поддерживаете постоянный подшипник вдоль линии ручья, вы будете постепенно прокручиваться к одному из полюсов.
Формула :
α = d/R (angular distance) lat2 = lat1 + α.cos(θ) Δφ = ln(tan(lat2/2+π/4)/tan(lat1/2+π/4)) [= the 'stretched' latitude difference] if E:W line q = cos(lat1) otherwise q = Δlat/Δφ Δlon = α.sin(θ)/q lon2 = (lon1+Δlon+π) % 2.π − π where ln is natural log and % is modulo, Δlon is taking shortest route (<180°), and R is the earth's radius
JavaScript :
lat2 = lat1 + d*Math.cos(brng); var dPhi = Math.log(Math.tan(lat2/2+Math.PI/4)/Math.tan(lat1/2+Math.PI/4)); var q = (!isNaN(dLat/dPhi)) ? dLat/dPhi : Math.cos(lat1); // EW line gives dPhi=0 var dLon = d*Math.sin(brng)/q; // check for some daft bugger going past the pole, normalise latitude if so if (Math.abs(lat2) > Math.PI/2) lat2 = lat2>0 ? Math.PI-lat2 : -(Math.PI-lat2); lon2 = (lon1+dLon+Math.PI)%(2*Math.PI) - Math.PI;
Я пытаюсь преобразовать его в php-синтаксис, но я не получаю желаемого результата. У меня широтная часть работает нормально. Я также включил свои тестовые данные.
// test data $R = 6371; $tlatitude = 50.7; $tlongitude = -105.214; $theading = 124; $d = 50; $projlat = $tlatitude + rad2deg(($d/$R)*COS(deg2rad($theading))); //Δφ = ln(tan(lat2/2+π/4)/tan(lat1/2+π/4)) $delta_phi = log(tan(deg2rad($projlat/2) + pi()/4)/(tan(deg2rad($tlatitude/2) + pi()/4))); //q = Δlat/Δφ $delta_lat = deg2rad($projlat - $tlatitude); $q = $delta_lat/$delta_phi; //Δlon = α.sin(θ)/q $delta_long = rad2deg($d/$R*sin(deg2rad($theading))/$q); $projlong = $tlongitude + $delta_long;
Я получаю $projlong = -104.84
согласно ссылочной странице, ответ должен быть -104.63
.
Теперь я пытаюсь заставить это работать, не обращая внимания на восток-запад и возможности полюса.
У меня были некоторые проблемы при выполнении расчетов расстояний, где мои ошибки будут расти довольно немного через некоторое время. Я обнаружил, что если бы я сделал бросок (двойной) в моем коде, точность увеличилась. Я не смотрел на C-код на PHP, чтобы узнать, что это вызвало. Я мог бы после этого отказаться от моей BC-версии кода.
Если вам нужна дополнительная точность, ознакомьтесь с BC-функциями в PHP. http://php.net/manual/en/book.bc.php
Кроме того, помните, что порядок выполнения вычислений на компьютере повлияет на вашу точность. То есть расчет ниже
$d/$R*sin(deg2rad($theading))/$q
не даст тот же результат, что и
$d*sin(deg2rad($theading))/$q/$R
и это также может дать третий результат
$d*sin(deg2rad($theading))/($q*$R)
Это связано с ограниченной точностью для чисел, близких к нулю (0) на компьютерах.
javascript имеет более высокую точность, чем PHP, посмотрите на эту шутку http://ru2.php.net/manual/en/function.doubleval.php
Мне когда-то нужно было проверить IBAN с алгоритмом Луна. Мой код javascript работал красиво. Но мой php потерпел неудачу, поэтому после некоторого исследования я нашел шутку и должен был перекодировать базовые операции (добавить, под, вычислять, делить, по модулю) на основе строки, а не числа.
Может быть, вам придется перекодировать его, чтобы получить ожидаемую точность. Мы не должны использовать php для высокоточных вычислений.