Работа с 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.
Есть ли общий способ обработки углового переноса в этих сценариях?
Ответы
Ответ 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;