Как отобразить 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);


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



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



обновление: я сделал ответ эриккаллена в функцию с хорошими длинными именами переменных, поэтому я пойму это через 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;
}
1088   13  

13 ответов:

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

Edit: ой, неверный знак.

решение, используя по модулю

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

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

объяснение

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

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

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

используя мод здесь будут возвращены значения в диапазоне 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);

Это должно работать в 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 градусов.

@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;
}
angle = Math.atan2(x,y)*180/Math.PI;

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

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

альтернативным решением является использование 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);
    }

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

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

геосфера пакетов 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 часа.

Comments

    Ничего не найдено.