Рассчитать широту/долготу углов наложения на землю из kml-файла

Мне нужно найти углы в широте/долготе наземного наложения, заданного в kml-файле либо в php, либо в javascript.

т.е. для конкретного примера мне нужно получить от:

  <LatLonBox>
    <north>60.406505416667</north>
    <south>60.400570555556</south>
    <east>5.3351572222222</east>
    <west>5.3190577777778</west>
    <rotation>3.7088732260919</rotation>
  </LatLonBox>

угловые координаты

SW: 60.400316388889;5.3194425
SE: 60.400824722222;5.3355405555556
NE: 60.406759444444;5.3347738888889
NW: 60.406251388889;5.3186730555556

Я могу получить другой путь (приблизительно, по крайней мере, указанный php-код) с помощью

$w=($nw_lng+$sw_lng)/2;
$e=($ne_lng+$se_lng)/2;
$n=($ne_lat+$nw_lat)/2;
$s=($se_lat+$sw_lat)/2;
$rot= rad2deg (atan ( ( $nw_lng - $sw_lng ) / ($sw_lat - $nw_lat ) / 2  ) );

Должно быть легко вернуться, но я потратил на это часы, не добираясь туда. Какие-нибудь советы?


person jankoc    schedule 26.10.2009    source источник
comment
Реализация Python тоже подойдет — я могу преобразовать ее в javascript/php. Мне это нужно в проекте, чтобы показать ваше текущее положение на карте (например, файл kmz пользовательской карты Garmin) на основе данных GPS. Веб-приложение для мобильных устройств, большая часть которого завершена, но эта часть отсутствует. Не домашнее задание.   -  person jankoc    schedule 26.10.2009


Ответы (1)


Вам необходимо использовать сферическую тригонометрию, часть сферическая геометрия для полной точности. Однако, поскольку вы имеете дело только с небольшим участком сферы, евклидова геометрия подойдет, если вы помните одну вещь.

По мере увеличения широты линии долготы сближаются. Например, вблизи Северного полюса линии широты почти соприкасаются. Так что обусловьте свои различия в широте, уменьшив их, умножив на коэффициент cos (широта). Это даст вам достаточную точность для вашего приложения.

 $n = 60.406505416667;
 $s = 60.400570555556;
 $e = 5.3351572222222;
 $w = 5.3190577777778;
 $rotn = 3.7088732260919;

 $a = ($e + $w) / 2.0;
 $b = ($n + $s) / 2.0;
 $squish = cos(deg2rad($b));
 $x = $squish * ($e - $w) / 2.0;
 $y = ($n - $s) / 2.0;

 $ne = array(
   $a + ($x * cos(deg2rad($rotn)) - $y * sin(deg2rad($rotn))) /$squish,
   $b + $x * sin(deg2rad($rotn)) + $y *cos(deg2rad($rotn))
   );
 $nw = array(
   $a - ($x * cos(deg2rad($rotn)) + $y * sin(deg2rad($rotn))) /$squish,
   $b - $x * sin(deg2rad($rotn)) + $y *cos(deg2rad($rotn))
   );
 $sw = array(
   $a - ($x * cos(deg2rad($rotn)) - $y * sin(deg2rad($rotn))) /$squish,
   $b - $x * sin(deg2rad($rotn)) - $y *cos(deg2rad($rotn))
   );
 $se = array(
   $a + ($x * cos(deg2rad($rotn)) + $y * sin(deg2rad($rotn))) /$squish,
   $b + $x * sin(deg2rad($rotn)) - $y *cos(deg2rad($rotn))
   );
 print_r(array(
 'sw'=>$sw,
 'se'=>$se,
 'ne'=>$ne,
 'nw'=>$nw,
 ));

Моя переменная $squish — это cos(lat), о котором я упоминал. Существует устранение сжатия относительной части горизонтальных длин. Таблица синусов выглядит так:

NE: (a + x cos A - y sin A, b + x sin A + y cos A)
NW: (a - x cos A - y sin A, b - x sin A + y cos A)
SW: (a - x cos A + y sin A, b - x sin A - y cos A)
SE: (a + x cos A + y sin A, b + x sin A - y cos A)

Возможно, tttppp может объяснить отличия от таблицы ttppp.

person Ewan Todd    schedule 26.10.2009
comment
расстояния мне кажутся малыми, так что, может быть, евклидова аппроксимации будет достаточно - person Victor; 26.10.2009
comment
Я уже знаю, что мне нужно использовать какую-то тригонометрию. Я думаю, что подойдет евклидово приближение (это то, что использует обратная формула, которая отлично работает для карт, которые я рассматривал). Однако мне не удалось получить правильную тригонометрию для прямого случая, даже после нескольких часов работы. Обратную формулу вычислить несложно... - person jankoc; 26.10.2009
comment
Сейчас это выглядит очень хорошо! Вероятно, моя обратная формула также потребует некоторого исправления, чтобы получить точный ответ. Это дало Array ( [sw] => Array ( [0] => 5.3194632953201 [1] => 60.400319597408 ) Stack Exchange => Array ([0 ] =› 5.3355290212874 [1] =› 60.400833943604 ) [ne] =› Array ( [0] =› 5.3347517046799 [1] =› 60.406756374815 ) [nw] =› Array ( [0] =› 5.318685978712 6 [1] )) - person jankoc; 26.10.2009
comment
Это правильно - сегодня я перепроверил свой ответ. Прошло всего пять с половиной лет после публикации. Вы можете сказать, что мой ответ был неправильным, взяв в качестве примера угол 0. - person tttppp; 27.05.2015