标准化0到360之间的方向

Jun*_*per 21 c# angle rotation

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

tva*_*son 44

使用模运算:

this.orientation += degrees;

this.orientation = this.orientation % 360;

if (this.orientation < 0)
{
    this.orientation += 360;
}
Run Code Online (Sandbox Code Playgroud)

  • 你能从模数中得到负结果吗?浮点问题? (3认同)
  • 哦。所以你可以。-1 % 360 是负数 1。我期望 359。愚蠢的我。你每天都会学到一些东西。 (3认同)
  • (angle+3600) %360(它允许 10 个完整的负旋转作为输入) (2认同)

QBz*_*ziZ 31

这是规范化到任何范围的.用于在[-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
}

对于整数

//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
}

所以基本相同,但没有底线.我个人使用的版本是适用于所有数字类型的通用版本,它还使用重新定义的版本,在整数类型的情况下不执行任何操作.

  • 这个功能很棒,一劳永逸地解决了"正常化角度问题"!:)导致,如果你只想在[0; 2*PI [角度:角度 - = Math.Floor(角度/(2*Math.PI))*2*Math.PI; (3认同)

pax*_*blo 18

这可以简化为以下内容.

public void Rotate (int degrees) {
    this.orientation = (this.orientation + degrees) % 360;
    if (this.orientation < 0) this.orientation += 360;
}
Run Code Online (Sandbox Code Playgroud)

C#遵循相同的规则C和C++,并i % 360会给你之间的值-359359为任何整数,则第二线是确保它通过359包容的取值范围为0.

如果你想要狡猾,你可以把它降到一行:

    this.orientation = (this.orientation + (degrees % 360) + 360) % 360;
Run Code Online (Sandbox Code Playgroud)

这会在所有情况下保持积极,但这是一个讨厌的黑客,以保存一行代码,所以我不会这样做,但我解释它.

degrees % 360你那里得到一个-359和之间的数字359.添加360将修改范围到1和之间719.如果orientation已经是肯定的,添加此将保证它仍然是,最后% 360将其带回范围内0通过359.

在裸露的最低限度,你可以简化你的代码,因为ifS和whileS可结合.例如,这两行中的条件结果:

if (this.orientation < 0)
while (this.orientation < 0)
Run Code Online (Sandbox Code Playgroud)

总是一样的,因此你不需要周围if.

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

public void Rotate (int degrees) {
    this.orientation += degrees;
    while (this.orientation <   0) this.orientation += 360;
    while (this.orientation > 359) this.orientation -= 360;
}
Run Code Online (Sandbox Code Playgroud)

但我仍然会去模数版,因为它避免了循环.这将是重要的,当一个用户在旋转进入3600亿(他们做到这一点,相信我),然后发现他们有,而你的代码研磨掉:-)采取早午餐

  • @jensgram,那个问题是它可以*仍然* 给你一个-359到-1范围内的数字,例如,如果方向是0,度数是-719,给出-359。您必须先标准化度数,然后将其强制为正数。 (4认同)

Ron*_*rby 15

我更喜欢避免循环、条件、任意偏移量 (3600) 和Math.____()调用:

var degrees = -123;
degrees = (degrees % 360 + 360) % 360;
// degrees: 237
Run Code Online (Sandbox Code Playgroud)


Saa*_*med 10

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

angle + Math.ceil( -angle / 360 ) * 360
Run Code Online (Sandbox Code Playgroud)

换角方向的广义公式可以是:

angle + Math.ceil( (-angle+shift) / 360 ) * 360
Run Code Online (Sandbox Code Playgroud)

其中shift的值表示循环移位,例如我想要-179到180的值然后它可以表示为:angle + Math.ceil((-angle-179)/ 360)*360


enz*_*uri 8

我在AS3中很快就嘲笑了这个,但是应该可以工作(你可能需要+=从角度来看)

private Number clampAngle(Number angle)
{
    return (angle % 360) + (angle < 0 ? 360 : 0);
}
Run Code Online (Sandbox Code Playgroud)