Расчет правильной долготы, когда она закончится | 180 |?

11

Я пытаюсь разработать "формулу", чтобы исправить значения lat-lng.

Я использую vue-листовку, но когда вы перемещаетесь за пределы «первого» мира, вы получаете большие цифры. Более +180 или ниже -180.

Например: когда я поворачиваюсь в Америку вправо (восточное направление), я получаю как lng 215. В моем уме, я просто исправлю это с 215-360=-145

То же самое для случая, когда я поворачиваюсь на восток России влево (западное направление) и получаю, например, -222. Теперь мне нужно рассчитать-222+360=138

Однако, поскольку мир неопределен, пользователь может перемещаться в восьмой мир, и мне пришлось скорректировать значения.

Можно ли рассчитать правильную долготу? (и еще одно требование - когда пользователь находится в первом мире, 24 lng все равно должно быть 24 lng.

Shadrix
источник

Ответы:

16

Вам нужно многократно прибавлять (или вычитать) 360 к вашему значению, пока оно не окажется в диапазоне от -180 до 180. Поэтому обычно пара циклов выглядит так:

lon = -187;
while(lon < -180){
  lon +=360;
}
while (lon > 180){
  lon -= 360;
}
Ян Тертон
источник
знаки неправильно? Должно быть lon + = 360 в первом случае.
ДжимТ
4
Вы можете сделать это только с одним циклом, while (Math.abs(lon) > 180) { lon -= Math.sign(lon) * 360 }хотя я не предоставляю его в качестве ответа, потому что ваша версия на самом деле соответствует объяснению, а моя версия - просто оптимизация, которая, вероятно, не имеет никакого значения Я оставляю это как комментарий, только как напоминание о том, что все может быть сделано несколькими способами, некоторые более оптимизированы, чем другие.
Андрей
2
Я не думаю, что когда-либо использовал бы это, поскольку он использует 2 вызова функции на цикл, и только один из моих циклов будет когда-либо выполняться. Вероятно, не имеет значения в этом примере, но это мое предубеждение
Ян Тертон
в то время как они выглядят как функции, математические функции в JavaScript должны больше походить на операторы с подробными символами. В этом смысле мы также можем видеть + - и даже <как функции. Изменить: у меня было решение здесь, что оно на самом деле не работает
Андрей
2
Вы не можете сделать lon %= 180?
Фонд Моника иск
15

Ответ, который избегает условных выражений и вызовов функций:

longitude = (longitude % 360 + 540) % 360 - 180

Я написал быструю микробенчмарку по адресу https://jsperf.com/longitude-normalisation, и условный код работает быстрее (в Chrome на моем компьютере) для «разумных» диапазонов входных значений. В общем, вам, вероятно, не стоит заранее беспокоиться о производительности при таких небольших вычислениях, которые придают больший вес читабельности и согласованности с остальной частью вашего кода.

Вероятно, более важным в этом случае является вопрос о том, может ли ваш код когда-либо сталкиваться с экстремальными входными значениями (1e10, Infinity и т. Д.). Если это так, реализация цикла может в конечном итоге работать очень медленно или беззвучно зависать в вашей программе. Это может произойти с расчетами, выполненными вблизи полюсов, например, попытка панорамирования на восток или запад на некотором расстоянии (а не на угол) от полюса может легко привести к бесконечной долготе.

Джо Ли-Мойет
источник
1
Интересный. Давайте поспорим, что условный jmp против деления FP. Хм, интересно.
Джошуа
1
@ Джошуа Вы не можете использовать условный переход. Вы должны использовать несколько условных переходов , или петлю. (Плюс цикл содержит дополнительные числа с плавающей запятой, что не является бесплатным.) Сколько итераций нужно циклу, зависит от входных данных. Таким образом, вы должны знать что-то о данных, чтобы посмотреть на производительность. Если подавляющее большинство приближается к желаемому диапазону и требует нескольких итераций, конечно, цикл сложения может быть быстрее, но это не так очевидно, как предполагает ваш сарказм.
jpmc26
1
@ jpmc26: В этом случае ожидать обхода цикла более одного раза глупо.
Джошуа
1
Сарказма не было. Я на самом деле не знаю, каким образом это упадет.
Джошуа
1
@ Джошуа, да, я тоже не был уверен :). Я добавил больше к ответу о производительности (и возможном случае сбоя цикла кода)
Джо Ли-Мойет
5

Один лайнер:

normalized = remainder(longitude, 360);

Объяснение: Вы хотите знать, что остается после того, как вы не учитываете полные повороты (360 °).

Этот процесс называется нормализацией.

Пример (cpp.sh)

Основан
источник
1
Не приведет ли это к значению [0, 360), а не к [-180, 180], как запрашивал Шадрикс?
Парень со шляпой
@TheGuywithTheHat Проверьте этот пример: cpp.sh/7uy2v
На основе
Ах, не знал, что это был C ++. В контексте JavaScript Шадрикс я интерпретировал remainderкак modulus. Модуль в JS приведет к [0, 360).
Парень со шляпой
1
Я не думаю, что это сработает. Вам нужно будет вычесть 360, если результат> 180. Другая проблема, которую я только что понял с JavaScript, состоит в том, что по модулю симметрично по 0, например, -1 % 3это -1, а не 2, как было бы необходимо для его работы здесь. remainderЭто отличное C ++ решение, но, к сожалению, в JS просто нет функции / оператора, достаточно похожих, чтобы быть полезными.
Парень со шляпой
0

Другой вариант: долгота = atan2 (cos (long), sin (long))

Andres
источник
1
Это не кажется хорошей идеей. Это очень трудно понять, вычислительно дорого и потенциально подвержено ошибкам округления.
Дэвид Ричерби
0

Если используемый вами язык программирования поддерживает оператор% (mod) для чисел с плавающей запятой (например, Python и Ruby), я бы порекомендовал использовать его. В противном случае, некоторые другие языки (например, C и C ++) позволяют использовать fmod ().

(Какой бы мод оператор вы ни использовали, заранее убедитесь, что он будет выполнять операции с модами над числами с плавающей запятой и всегда будет давать вам неотрицательные ответы. В противном случае вы получите неприятный сюрприз позже, когда многие из ваших точки широты / долготы не верны.)

Используйте это так:

# Put the longitude in the range of [0,360):
longitude %= 360

# Put the longitude in the range of [-180,180):
if longitude >= 180:
    longitude -= 360

Если вы предпочитаете делать все это в одной строке:

# Put the longitude in the range of [-180,180):
longitude = (longitude + 180) % 360 - 180

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

Редактировать:

Хммм ... Я только что заметил, что Javascript, похоже, не справляется %с отрицательными значениями, как я думал, что это будет.

В этом случае попробуйте эту строку:

longitude = (longitude + 36180) % 360 - 180

36180Мы добавляем в 36000 + 180. 36000, чтобы переместить отрицательное значение в положительной области, и 180, чтобы сдвинуть его над тем , что , когда он модом на 360, он будет находиться в диапазоне [0360) , В - 180сдвиги часть его обратно в диапазоне [-180,180).

Вот еще один вкладыш, который не полагается на 36000, будучи достаточно большим:

longitude = (longitude % 360 + 360 + 180) % 360 - 180

Эта longitude % 360 + 360часть гарантирует, что значение останется в положительном домене, когда оно будет позже изменено 360. В + 180сдвигах части ее над тем , что , когда он позже получает 180 вычитает из него (с - 180), он будет находиться в требуемом диапазоне [-180,180).

JL
источник
1
Примечание: C, C ++ fmod(longitude, 360)-> (-360,0 ... +360,0) и ilongitude % 360-> [-359 ... +359].
Chux - Восстановить Монику
@chux - Я не знал об этом, поэтому я просто проверил это, и, похоже, ты прав. Спасибо за указание на это.
JL