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

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

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

пример:

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

8 ответов


это дает подписанный угол для любых углов:

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

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


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

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

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


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

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

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


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

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

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

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

для пользователей UnityEngine простой способ-просто использовать Mathf.Дельтаангль.


нет необходимости вычислять тригонометрические функции. Простой код на языке 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);
}

пусть dif = a-b , в радианах

dif = difangrad(a,b);

пусть dif = 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

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


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

double getAbsoluteDiff2Angles(const double x, const double y)
{
    return 180.0 - fabs(fmod(fabs(x - y), 360.0) - 180.0);
}