我正在研究一个简单的旋转程序,它将物体旋转归一化到0到360度之间。我的C#代码似乎正在运行,但我并不完全满意。任何人都可以改进下面的代码,使它更健壮吗?
public void Rotate(int degrees)
{
this.orientation += degrees;
if (this.orientation < 0)
{
while (this.orientation < 0)
{
this.orientation += 360;
}
}
else if (this.orientation >= 360)
{
while (this.orientation >= 360)
{
this.orientation -= 360;
}
}
}
答案 0 :(得分:43)
使用模运算:
this.orientation += degrees;
this.orientation = this.orientation % 360;
if (this.orientation < 0)
{
this.orientation += 360;
}
答案 1 :(得分:28)
这是规范化到任何范围的那个。 用于在[-180,180],[0,180]或[0,360]之间进行标准化。
(虽然它是用C ++编写的)
//Normalizes any number to an arbitrary range //by assuming the range wraps around when going below min or above max double normalise( const double value, const double start, const double end ) { const double width = end - start ; // const double offsetValue = value - start ; // value relative to 0 return ( offsetValue - ( floor( offsetValue / width ) * width ) ) + start ; // + start to reset back to start of original range }
对于ints
//Normalizes any number to an arbitrary range //by assuming the range wraps around when going below min or above max int normalise( const int value, const int start, const int end ) { const int width = end - start ; // const int offsetValue = value - start ; // value relative to 0 return ( offsetValue - ( ( offsetValue / width ) * width ) ) + start ; // + start to reset back to start of original range }
所以基本相同,但没有发言权。 我个人使用的版本是适用于所有数字类型的通用版本,它还使用重新定义的版本,在整数类型的情况下不执行任何操作。
答案 2 :(得分:18)
这可以简化为以下内容。
public void Rotate (int degrees) {
this.orientation = (this.orientation + degrees) % 360;
if (this.orientation < 0) this.orientation += 360;
}
C#遵循与C和C ++相同的规则,i % 360
将为{1}}和-359
之间的任何整数提供值,然后第二行是确保它在范围内0到359(含)。
如果你想变得狡猾,你可以把它归结为一行:
359
这会在所有情况下都保持正面,但这对于保存一行代码来说是一个讨厌的黑客,所以我不会这样做,但我将解释它。
从 this.orientation = (this.orientation + (degrees % 360) + 360) % 360;
开始,您将获得degrees % 360
和-359
之间的数字。添加359
会将范围修改为360
和1
之间的范围。如果719
已经是肯定的,那么添加此功能将保证它仍然是,并且最终的orientation
会将其恢复到% 360
到0
的范围。
在最小时,您可以简化代码,因为可以合并359
和if
。例如,这两行中的条件结果:
while
总是相同,因此您不需要周围的if (this.orientation < 0)
while (this.orientation < 0)
。
所以,为此,你可以这样做:
if
但是我仍然仍然去模数版,因为它避免了循环。当用户输入360,000,000,000用于轮换时,这将非常重要(并且他们将执行此操作,请相信我),然后发现他们必须在您的代码磨损时提早吃午餐: - )
答案 3 :(得分:9)
angle + Math.ceil( -angle / 360 ) * 360
偏移角度方向的广义公式可以是:
angle + Math.ceil( (-angle+shift) / 360 ) * 360
其中shift的值表示循环移位,例如我想要-179到180的值,那么它可以表示为: angle + Math.ceil((-angle-179)/ 360)* 360
答案 4 :(得分:8)
我在AS3中很快就嘲笑了这一点,但应该有效(你可能需要+=
角度)
private Number clampAngle(Number angle)
{
return (angle % 360) + (angle < 0 ? 360 : 0);
}
答案 5 :(得分:4)
我更喜欢避免循环,条件,任意偏移(3600)和Math.____()
调用:
var degrees = -123;
degrees = (degrees % 360 + 360) % 360;
// degrees: 237
答案 6 :(得分:1)
我建议创建单独的函数来标准化角度-这是一种更清洁的解决方案。
public static float NormalizeEulerAngle(float angle){
var normalized = angle % 360;
if(normalized < 0)
normalized += 360;
return normalized;
}
提琴证明该功能可以正常工作:https://dotnetfiddle.net/Vh4CUa
然后您可以在此处使用它:
public void Rotate(int degrees){
orientation = NormalizeEulerAngle(orientation + degrees);
}
答案 7 :(得分:0)
添加360度的任意倍数,在这些倍数之间可能存在可能的输入值(将其置于零以上),然后将剩余的带有%,如此
angle = 382;
normalized_angle = (angle+3600) %360;
//result = 22
上述情况可以将输入角度降至-3600。您可以添加任意数字(360的倍数),这将使输入值成为正值。
通常在动画期间,您之前的帧/步长值可能已经被上一步标准化,因此您只需添加360就可以了:
normalized_angle = (angle+360) %360;
答案 8 :(得分:0)
将角度(度)归一化为间隔[0,360>时有用的功能:
float normalize_angle(float angle)
{
float k = angle;
while(k < 0.0)
k += 360.0;
while(k >= 360.0)
k -= 360.0;
return k;
}
答案 9 :(得分:-2)
对于任何偶然发现这些神奇解决方案的人来说。 我已经测试了其中几个值的真实0-360值。 使用陀螺仪可以给出+/-数千范围内的值
enzuguri的解决方案实现了这一目标!
萨德·艾哈迈德(Saad Ahmed)和QBziZ的解决方案在输入-10时得出-10。不是我期望的350。 希望这会有所帮助 杰西