标准化0到360之间的方向

时间:2009-10-27 02:02:33

标签: c# rotation angle

我正在研究一个简单的旋转程序,它将物体旋转归一化到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;
            }
        }
    }

10 个答案:

答案 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会将范围修改为3601之间的范围。如果719已经是肯定的,那么添加此功能将保证它仍然是,并且最终的orientation会将其恢复到% 3600的范围。

最小时,您可以简化代码,因为可以合并359if。例如,这两行中的条件结果:

while

总是相同,因此您不需要周围的if (this.orientation < 0) while (this.orientation < 0)

所以,为此,你可以这样做:

if

但是我仍然仍然去模数版,因为它避免了循环。当用户输入360,000,000,000用于轮换时,这将非常重要(并且他们执行此操作,请相信我),然后发现他们必须在您的代码磨损时提早吃午餐: - )

答案 3 :(得分:9)

用于重新定向圆形值的公式,即保持0到359之间的角度是:

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。 希望这会有所帮助 杰西