Вопрос

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);

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

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

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

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;
}
Это было полезно?

Решение

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

Другие советы

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

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

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 градусов.

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

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

(Добавление 180 ° к возвращаемому значению переводит его в диапазон 0-360, но изменяет угол.Отрицание обоих входных параметров возвращает его обратно.)

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

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

Это должно работать на C ++:(в зависимости от того, как реализован 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 градусов.

У меня есть 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;
}

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

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

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

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

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

atan2(y,x)/M_PI*180

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

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

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

Я вывел формулу для определения угла ориентации от 0 до 360

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

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

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

Затем, с помощью следующей функции, угол между ini(x,y) и конец (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);
    }

Геосфера пакетов R вычислит BEARINGRUMB, который является постоянной линией азимута с учетом исходной точки и направления на восток / север.Направление на восток и север должно быть в виде матрицы или вектора.Исходная точка розы ветров равна 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)
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 град становится (-1 + 360) = 359 град
-179 град становится (-179 + 360) = 181 град

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

Это вернет градус от 0 ° до 360 ° против часовой стрелки, 0 ° находится в положении "3 часа".

Формула, которая должна иметь диапазон значений от 0 до 360 градусов.

f (x, y) = 180-90 * (1+ знак (x))* (1-знак (y^ 2))-45* (2+ знак (x))* знак (y)

     -(180/pi())*sign(x*y)*atan((abs(x)-abs(y))/(abs(x)+abs(y)))
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top