Как сопоставить atan2() с градусами 0-360

atan2 (y, x) имеет этот разрыв при 180 °, где он переключается на -180 °... 0 °, идущий по часовой стрелке.

Как отобразить диапазон значений до 0 °..360 °?

вот мой код:

CGSize deltaPoint = CGSizeMake(endPoint.x - startPoint.x, endPoint.y - startPoint.y);
float swipeBearing = atan2f(deltaPoint.height, deltaPoint.width);

Я вычисляю направление проверочного события касания, заданного startPoint и endPoint, обе структуры точек XY. Код для iPhone, но любой язык, поддерживающий atan2f(), будет делать.

Спасибо за помощь, ребята, с общим решением и кодом.

Обновление. Я включил функцию erikkallen в функцию с хорошими длинными именами переменных, поэтому я постиг ее через 6 месяцев. Может быть, это поможет другому iPhone noob.

float PointPairToBearingDegrees(CGPoint startingPoint, CGPoint endingPoint)
{
    CGPoint originPoint = CGPointMake(endingPoint.x - startingPoint.x, endingPoint.y - startingPoint.y); // get origin point to origin by subtracting end from start
    float bearingRadians = atan2f(originPoint.y, originPoint.x); // get bearing in radians
    float bearingDegrees = bearingRadians * (180.0 / M_PI); // convert to degrees
    bearingDegrees = (bearingDegrees > 0.0 ? bearingDegrees : (360.0 + bearingDegrees)); // correct discontinuity
    return bearingDegrees;
}

Ответ 1

(x > 0 ? x : (2*PI + x)) * 360 / (2*PI)

Изменить: Ой, неправильный знак.

Ответ 2

Решение с использованием модуля Modulo

Простое решение, которое ловит все случаи.

degrees = (degrees + 360) % 360;  // +360 for implementations where mod returns negative numbers

Описание

Положительный: от 1 до 180

Если вы измените любое положительное число от 1 до 180 на 360, вы получите тот же самый номер, который вы ввели. Мод здесь просто гарантирует, что эти положительные числа будут возвращены как одно и то же значение.

Отрицательный: от -180 до -1

Использование mod здесь вернет значения в диапазоне от 180 до 359 градусов.

Специальные случаи: 0 и 360

Использование mod означает, что возвращается 0, делая это безопасным решением 0-359 градусов.

Ответ 3

Просто добавьте 360 °, если ответ от atan2 меньше 0 °.

Ответ 4

Или, если вам не нравится ветвление, просто отрицайте два параметра и добавляйте 180 ° к ответу.

Ответ 5

@erikkallen близок, но не совсем прав.

theta_rad = atan2(y,x);
theta_deg = (theta_rad/M_PI*180) + (theta_rad > 0 ? 0 : 360);

Это должно работать в С++: (в зависимости от того, как реализована fmod, она может быть быстрее или медленнее условного выражения)

theta_deg = fmod(atan2(y,x)/M_PI*180,360);

В качестве альтернативы вы можете сделать это:

theta_deg = atan2(-y,-x)/M_PI*180 + 180;

так как (x, y) и (-x, -y) различаются по углам на 180 градусов.

Ответ 6

@Jason S: ваш вариант "fmod" не будет работать с реализацией, совместимой со стандартами. Стандарт C ясен и ясен (7.12.10.1, "функции fmod" ):

если y отличное от нуля, результат имеет тот же знак, что и x

Таким образом,

fmod(atan2(y,x)/M_PI*180,360)

на самом деле просто многословное переписывание:

atan2(y,x)/M_PI*180

Ваше третье предложение, однако, находится на месте.

Ответ 7

У меня есть 2 решения, которые, похоже, работают для всех комбинаций положительных и отрицательных x и y.

1) Злоупотребление atan2()

В соответствии с документами atan2 принимает параметры y и x в этом порядке. Однако, если вы их отмените, вы можете сделать следующее:

double radians = std::atan2(x, y);
double degrees = radians * 180 / M_PI;
if (radians < 0)
{
    degrees += 360; 
}

2) Правильно используйте atan2() и конвертируйте

double degrees = std::atan2(y, x) * 180 / M_PI;
if (degrees > 90)
{
    degrees = 450 - degrees;
}
else
{
    degrees = 90 - degrees;
}

Ответ 8

Альтернативное решение - использовать функцию mod(), определенную как:

function mod(a, b) {return a - Math.floor (a / b) * b;}

Затем со следующей функцией получается угол между точками ini (x, y) и end (x, y). Угол выражен в градусах, нормированных на [0, 360] град. и Север, ссылающийся на 360 градусов.

    function angleInDegrees(ini, end) {
        var radian = Math.atan2((end.y - ini.y), (end.x - ini.x));//radian [-PI,PI]
        return mod(radian * 180 / Math.PI + 90, 360);
    }

Ответ 9

angle = Math.atan2(x,y)*180/Math.PI;

Я сделал Формулу для ориентирования угла в 0 до 360

angle + Math.ceil( -angle / 360 ) * 360;

Ответ 10

Геосфера R пакетов будет вычислять опорную точку, которая является постоянной несущей линией, с учетом точки начала и востока/север. Восток и север должны быть в матрице или векторе. Происхождение точки ветровой розы составляет 0,0. Следующий код, похоже, с готовностью разрешает проблему:

windE<-wind$uasE
windN<-wind$vasN
wind_matrix<-cbind(windE, windN)
wind$wind_dir<-bearingRhumb(c(0,0), wind_matrix)
wind$wind_dir<-round(wind$wind_dir, 0)

Ответ 11

double degree = fmodf((atan2(x, y) * (180.0 / M_PI)) + 360, 360);

Это вернет степень от 0 ° -360 ° против часовой стрелки, 0 ° - в 3 часа.

Ответ 12

theta_rad = Math.Atan2(y,x);
if(theta_rad < 0)
  theta_rad = theta_rad + 2 * Math.PI;    //if neg., add 2 PI to it
theta_deg = (theta_rad/M_PI*180) ;        //convert from radian to degree

//or
theta_rad = Math.Atan2(y,x);
theta_rad = (theta_rad < 0) ? theta_rad + 2 * Math.PI : theta_rad;
theta_deg = (theta_rad/M_PI*180) ;

-1 deg становится (-1 + 360) = 359 градусов
-179 град становится (-179 + 360) = 181 град

Ответ 13

Это то, что я обычно делаю:

float rads = atan2(y, x);
if (y < 0) rads = M_PI*2.f + rads;
float degrees = rads*180.f/M_PI;