Ответ 1
(x > 0 ? x : (2*PI + x)) * 360 / (2*PI)
Изменить: Ой, неправильный знак.
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;
}
(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 ° к ответу.
@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 градусов.
@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
Ваше третье предложение, однако, находится на месте.
У меня есть 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;
}
Альтернативное решение - использовать функцию 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);
}
angle = Math.atan2(x,y)*180/Math.PI;
Я сделал Формулу для ориентирования угла в 0 до 360
angle + Math.ceil( -angle / 360 ) * 360;
Геосфера 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)
double degree = fmodf((atan2(x, y) * (180.0 / M_PI)) + 360, 360);
Это вернет степень от 0 ° -360 ° против часовой стрелки, 0 ° - в 3 часа.
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 град
Это то, что я обычно делаю:
float rads = atan2(y, x);
if (y < 0) rads = M_PI*2.f + rads;
float degrees = rads*180.f/M_PI;