Найдите, находится ли угол в пределах X градусов от другого
-
21-09-2019 - |
Вопрос
Мне нужен алгоритм, чтобы выяснить, находится ли один угол в пределах определенного количества градусов от другого угла.
Моей первой мыслью было (a-x < b) && (a+x > b)
, но он терпит неудачу, когда ему приходится работать с углами, которые изменяются от -179 до 180.
На диаграмме выше область (зеленая), между которой должен находиться угол, находится между отрицательной и положительной сторонами.Как я могу определить, попадает ли угол (красная линия) внутрь этой области?
Решение
попробуйте эту формулу:
360-(|a-b|)%360<x || (|a-b|)%360<x
Или, в PHP:
<?php
$b = 10;
$angle1 = -179;
$angle2 = 180;
$diff = $angle1 - $angle2;
if(abs($diff % 360) <= $b || (360-abs($diff % 360))<=$b) {
echo "yes";
} else {
echo "no";
}
?>
Другие советы
Как справедливо отмечает Марсель, деление по модулю на отрицательные числа потенциально проблематично.Кроме того, в чем разница между 355 и 5 градусами?Возможно, предполагается, что температура составит 350 градусов, но 10 градусов - это, вероятно, то, чего ожидают люди.Мы делаем следующие предположения:
- нам нужен наименьший положительный угол между двумя другими углами, чтобы
0 <= diff <= 180
; - мы работаем в градусах.Если в радианах, замените 360 на
2*PI
; - углы могут быть положительными или отрицательными, могут находиться за пределами диапазона
-360 < x < 360
где x - входной угол и - порядок входных углов или направление разницы не имеет значения.
Входные данные:углы a и b.Таким образом, алгоритм прост:
- Нормализуйте a и b, чтобы
0 <= x < 360
; - Вычислите кратчайший угол между двумя нормальными углами.
Для первого шага, чтобы преобразовать угол в желаемый диапазон, есть две возможности:
x >= 0
:норма = x % 360x < 0
:нормальный = (-x / 360 + 1) * 360 + x
Второй предназначен для устранения любой двусмысленности в отношении различий в интерпретации операций с отрицательным модулем.Итак, чтобы привести работающий пример для x = -400:
-x / 360 + 1
= -(-400) / 360 + 1
= 400 / 360 + 1
= 1 + 1
= 2
тогда
normal = 2 * 360 + (-400)
= 320
таким образом, для входов 10 и -400 нормальные углы равны 10 и 320.
Теперь мы вычисляем кратчайший угол между ними.Для проверки работоспособности сумма этих двух углов должна быть равна 360.В данном случае возможны значения 50 и 310 (нарисуйте их, и вы увидите это).Чтобы разобраться с этим:
normal1 = min(normal(a), normal(b))
normal2 = max(normal(a), normal(b))
angle1 = normal2 - normal1
angle2 = 360 + normal1 - normal2
Итак, для нашего примера:
normal1 = min(320, 10) = 10
normal2 = max(320, 10) = 320
angle1 = normal2 - normal1 = 320 - 10 = 310
angle2 = 360 + normal1 - normal2 = 360 + 10 - 320 = 50
Вы заметите normal1 + normal2 = 360
(и вы даже можете доказать, что это будет так, если хотите).
Наконец:
diff = min(normal1, normal2)
или 50 в нашем случае.
При радиусе 1 расстояние между конечными точками линии равно 2sin((a-b/2).Поэтому отбросьте 2, поскольку вас интересует только сравнение, и сравните sin (x / 2) с sin((a-b)/ 2).Тригонометрические функции заботятся обо всей упаковке.
Вы также можете использовать точечный продукт:
cos(a)*cos(b) + sin(a)*sin(b) >= cos(x)
реализация на c++:
float diff = fabsf(angle1 - angle2);
bool isInRange = fmodf(diff, 360.0f) <= ANGLE_RANGE ||
360.0f - fmodf(diff, 360.0f) <= ANGLE_RANGE;