Наименьшая разница между двумя углами

Учитывая 2 угла в диапазоне -PI → PI вокруг координаты, каково значение наименьшего из двух углов между ними?

Учитывая, что разница между PI и -PI не равна 2 PI, но равна нулю.

Пример:

Представьте себе круг с двумя линиями, выходящими из центра, между этими линиями есть 2 угла, угол, который они делают на внутренней стороне меньший угол, и угол, который они делают на снаружи, ака больший угол. Оба угла при добавлении образуют полный круг. Учитывая, что каждый угол может входить в определенный диапазон, , что такое меньшее значение углов, принимая во внимание опрокидывание

Ответ 1

Это дает угол под знаком для любых углов:

a = targetA - sourceA
a = (a + 180) % 360 - 180

Остерегайтесь во многих языках, операция modulo возвращает значение с тем же знаком, что и дивиденд (например, полный список C, С++, С#, JavaScript, ). Для этого требуется пользовательская функция mod:

mod = (a, n) -> a - floor(a/n) * n

Или так:

mod = (a, n) -> (a % n + n) % n

Если углы находятся в пределах [-180, 180], это также работает:

a = targetA - sourceA
a += (a>180) ? -360 : (a<-180) ? 360 : 0

В более подробном виде:

a = targetA - sourceA
a -= 360 if a > 180
a += 360 if a < -180

Ответ 2

x - целевой угол. y - исходный или начальный угол:

atan2(sin(x-y), cos(x-y))

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

Ответ 3

Если ваши два угла равны x и y, то один из углов между ними - abs (x - y). Другой угол равен (2 * PI) - abs (x - y). Таким образом, значение наименьшего из двух углов:

min((2 * PI) - abs(x - y), abs(x - y))

Это дает абсолютное значение угла, и предполагает, что входы нормализованы (т.е. в пределах диапазона [0, 2π)).

Если вы хотите сохранить знак (то есть: направление) угла, а также принять углы вне диапазона [0, 2π), вы можете обобщить приведенное выше. Здесь код Python для обобщенной версии:

PI = math.pi
TAU = 2*PI
def smallestSignedAngleBetween(x, y):
    a = (x - y) % TAU
    b = (y - x) % TAU
    return -a if a < b else b

Обратите внимание, что оператор % не ведет себя одинаково на всех языках, особенно когда задействованы отрицательные значения, поэтому, если потребуется переносить некоторые корректировки значков.

Ответ 4

Я поднимаю задачу предоставления подписанного ответа:

def f(x,y):
  import math
  return min(y-x, y-x+2*math.pi, y-x-2*math.pi, key=abs)

Ответ 5

Арифметическое (в отличие от алгоритмического) решение:

angle = Pi - abs(abs(a1 - a2) - Pi);

Ответ 6

Для пользователей UnityEngine проще всего использовать Mathf.DeltaAngle.

Ответ 7

Нет необходимости вычислять тригонометрические функции. Простым кодом на языке C является:

#include <math.h>
#define PIV2 M_PI+M_PI
#define C360 360.0000000000000000000
double difangrad(double x, double y)
{
double arg;

arg = fmod(y-x, PIV2);
if (arg < 0 )  arg  = arg + PIV2;
if (arg > M_PI) arg  = arg - PIV2;

return (-arg);
}
double difangdeg(double x, double y)
{
double arg;
arg = fmod(y-x, C360);
if (arg < 0 )  arg  = arg + C360;
if (arg > 180) arg  = arg - C360;
return (-arg);
}

let dif = a - b, в радианах

dif = difangrad(a,b);

пусть di = a - b, в градусах

dif = difangdeg(a,b);

difangdeg(180.000000 , -180.000000) = 0.000000
difangdeg(-180.000000 , 180.000000) = -0.000000
difangdeg(359.000000 , 1.000000) = -2.000000
difangdeg(1.000000 , 359.000000) = 2.000000

Нет греха, нет соз, нет загар,... только геометрия!!!!

Ответ 8

Эффективный код в C++:

inline double getAbsoluteDiff2Angles(const double x, const double y, const double c)
{
    // c can be PI or 180;
    return c - fabs(fmod(fabs(x - y), 2*c) - c);
}