Як зіставити atan2 () до градусів 0-360


108

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()буде робити.


Примітка. Опублікований метод оновлення не повертає нульових градусів, а значення від вище 0 до 360,0.
chux

2
> [Як отримати кут від 2 -й положень] [1] [1]: stackoverflow.com/questions/9457988 / ...
Манодж Sarnaik

Ця функція чудово працює, проте кут розрахунку "bearDegrees" перевернутий. наприклад, 45 градусів, як правило, по 1-му квадрату, однак це в 4-му квадранті. 135 градусів зазвичай буде у 2-му квадранті, але ця функція повертає його до 3-го квадранта. я можу просто взяти значення повернення функції x і заперечити це від 360, щоб отримати правильне значення кута, проте мені цікаво знати, чому це відбувається в першу чергу?
goelv

Відповіді:


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

6
Можливо, також потрібно x> = 0 для випадку x = 0.
bpw1621

13
Для тих, хто не відповідає цим позначенням, і без перетворення на вбудовані градуси: якщо (x> 0) {radians = x;} else {radians = 2 * PI + x;}, тому ми просто додаємо 2PI до результату, якщо це менше 0.
Девід Дорія

1
Або (x >= 0 ? x : (2*PI + x)) * 180/PIяк у(x < 0 ? 2*PI + x : x) * 180/PI
user3342816

97

Розчин за допомогою 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
дивовижні рішення :)
Кадір Хуссейн

5
Я не вірю, що потрібно додати 360. -1% 360 все ще 359 :)
ласкаmorebacon

11
Я не думаю, що це правильно всіма мовами. In Javascript-1 % 360 = -1
Startec

Також не є життєздатним підходом на Яві
Халк

1
@pleasemorebacon Неправильно. У деяких мовах -1% 360 - -1.
Фарап

40

Просто додайте 360 °, якщо відповідь від atan2 менше 0 °.


6
Це те саме, що "просто додати 2 * PI", якщо у вас є один із цих днів.
Кріс О

33

Або якщо вам не подобається розгалуження, просто заперечте два параметри та додайте до відповіді 180 °.

(Додавання 180 ° до зворотного значення ставить його непогано в діапазон 0-360, але повертає кут. Нехтування обома вхідними параметрами повертає його назад.)


2
Дякую, це саме те, що я шукав.
Джеремі Геррман

2
Я вважаю за краще змінити свій код, щоб використовувати деннормалізовані кути (<0,> = 360), але завжди здається, що хтось прагне до цього підробленого "оптимізованого" відчуття; тому я хотів додати це. (Чи це тому , що це був швидкий шлях навколо деякого тимчасового коду налагодження я використовував ммм?)
AIB

1
Безумовно, це не просто, коли я можу погодитися після 2+ років. Отже: Додавання 180 ° до поверненого значення добре ставить його в діапазон 0-360, але перевертає кут. Заперечення обох вхідних параметрів повертає її назад.
аїб

Це може мати деякі проблеми, коли $ x = 0 $ і $ y> 0 $ iirc
Тринідад

22

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


якщо я вас правильно зрозумів у Fortran, це atan2 (-y, -x) * 180 / PI + 180. Це правильно?
gansub

вибачте, я не знаю FORTRAN. Але ваша математика виглядає правильно.
Jason S

11

У мене є 2 рішення, які, здається, працюють для всіх комбінацій позитивного і негативного х і у.

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

Ви, пане, рятувальник життя. Щойно використаний такий підхід в Unity і працює як шарм.
porfiriopartida

7

@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

Однак ваша третя пропозиція є місцем.


5

Це те, що я зазвичай роблю:

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

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

Я склав формулу для орієнтування кута на 0 до 360

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

2

Альтернативним рішенням є використання функції mod (), визначеної як:

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

1

Геосфера пакетів 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)

1
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 град


Що Math.PI? Це те саме, що M_PI?
Панг

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

Це поверне градус від 0 ° -360 ° проти годинникової стрілки, 0 ° - в 3 години.


1

Формула, щоб мати діапазон значень від 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)))

Чи можете ви пояснити, як це стосується питання?
Клаус Гюттер

1

Ось деякі JavaScript. Просто введіть значення x і y.

var angle = (Math.atan2(x,y) * (180/Math.PI) + 360) % 360;
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.