Подтвердить что ты не робот

Работа с Angle Wrap в С++-коде

Есть ли способ безопасности и просто иметь дело с угловой упаковкой с минимальным количеством операторов case.

Угловая обертка возникает при использовании определенного представления для угла (0-360 градусов или -180 - 180 градусов (или эквивалент в радианах)), и вы обертываете угол. Например, скажем, что у вас есть угол -170, и вы вычитаете 50 град. Вы математически добавляете до -220, но на самом деле должны быть +140 град.

Очевидно, вы можете проверить это, используя:

if (deg < -180) { 180 - abs(deg + 180); }

или аналогичный. Но, во-первых, вам нужно множество проверок, а во-вторых, это не сработает, если вы дважды обернете.

Второй случай, когда это распространено, - это интерполяция между двумя углами.

Например, скажем, у меня есть угол -170 градусов и 160 градусов, и я хочу на полпути между ними. Общим способом сделать это является ang1 + 0.5(ang2-ang1), но в примере, который я предусмотрел, это приведет к тому, что угол будет -5 град, если он должен быть равен 175.

Есть ли общий способ обработки углового переноса в этих сценариях?

4b9b3361

Ответ 1

Для полноты я включу как нормальные [0, 360), так и [-180, 180).

Вам понадобится #include <math.h>.


Нормализовать до [0,360):

double constrainAngle(double x){
    x = fmod(x,360);
    if (x < 0)
        x += 360;
    return x;
}

Нормализовать до [-180,180):

double constrainAngle(double x){
    x = fmod(x + 180,360);
    if (x < 0)
        x += 360;
    return x - 180;
}

Шаблон должен быть достаточно прост, чтобы распознать его для радианов.


Угол бисекции:

double angleDiff(double a,double b){
    double dif = fmod(b - a + 180,360);
    if (dif < 0)
        dif += 360;
    return dif - 180;
}
double bisectAngle(double a,double b){
    return constrainAngle(a + angleDiff(a,b) * 0.5);
}

Это должно делить пополам угол на "меньшей" стороне. (предупреждение: не полностью протестировано)

Ответ 2

Я считаю, что использование remainder() из математической библиотеки удобно. Учитывая угол a, чтобы ограничить его -180 180, вы можете просто сделать:

remainder(a, 360.0);

и измените 360.0 на 2.0 * M_PI для радиан

Ответ 3

Итак, если вы выяснили, как эффективно делать то, что я хочу, используя мистический подход к ограничению угла. Вот он:

enter image description here

Это похоже на любой пример, о котором я могу думать.

Ответ 4

Нормализовать угол до диапазона [-180, 180)

deg -= 360. * std::floor((deg + 180.) * (1. / 360.));

Нормализовать угол до диапазона [0, 360)

deg -= 360. * std::floor(deg * (1. / 360.));

Примеры:

deg = -90[0, 360):

deg -= 360. * std::floor(-90 / 360.);
deg -= 360. * -1;
deg = 270

deg = 270[-180, 180):

deg -= 360. * std::floor((deg + 180.) / 360.);
deg -= 360. * std::floor(480. / 360.);
deg -= 360. * 1.;
deg = -90;

Смотрите: http://en.cppreference.com/w/cpp/numeric/math/floor

Ответ 5

Редактировать.. о, я прочитал ваш вопрос неправильно..

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

Ответ 6

Угол карты (+ PI ~ -PI) до значенного значения int (или короткого значения):

angle_signed_short = angle_float / PI * 0x7FFFF;

Затем вы можете добавить или добавить значение как обычно. Затем верните карту:

angle_float = angle_signed_short * PI / 0x7FFFF;