将角度固定为方向

本文关键字:方向 | 更新日期: 2023-09-27 18:07:21

我想确定一个角度

问题-视频:https://youtu.be/5LGbYguG4P0

例如:

我有一个角度90,我想把它固定为45度(所以它不能小于/大于(90 - 45)或(90 + 45)。

在过去的几个小时里,我尝试了多种方法,也在网上搜索了一下。

有些已经工作了,主要是因为它们"包装"错误,因为内置的角度包装(我认为它的包装是-Pi到Pi),所以当它达到-Pi或Pi,并超过,它包装,并做一个大的跳跃到相反的角度。

尝试(s):

    public static float AngleBound(float Angle, float BoundAngle, ushort Degrees)
    {
        float A = MathHelper.ToDegrees(Angle), BA = MathHelper.ToDegrees(BoundAngle), DMin = (BA - Degrees), DMax = (BA + Degrees);
        return MathHelper.ToRadians(MathHelper.Max(DMin, MathHelper.Min(DMax, A)));
    }
    public static float AngleBound(float Angle, float BoundAngle, ushort Degrees)
    {
        return MathHelper.ToRadians((float)Wrap((MathHelper.ToDegrees(Angle) + 180), ((MathHelper.ToDegrees(BoundAngle) + 180) + (Degrees / 2f)), ((MathHelper.ToDegrees(BoundAngle) + 180) - (Degrees / 2f))));
    }
    public static float AngleBound(float Angle, float BoundAngle, ushort Degrees)
    {
        return MathHelper.ToRadians((float)Wrap(MathHelper.ToDegrees(Angle), (MathHelper.ToDegrees(BoundAngle) + (Degrees * 1)), (MathHelper.ToDegrees(BoundAngle) - (Degrees * 1))));
    }

解释:

Angle = 60 (Passed in as Radians)
AngleBound = 90 (Passed in as Radians)
Degrees = 45 (Passed in as Degrees)
Wanted Result: Angle bound by (90 - 45) - (90 + 45)
Wanted Result: Angle bound by (AngleBound - Degrees) - (AngleBound + Degrees)

将角度固定为方向

到目前为止,所有的答案都没有考虑到如果你做Clamp(380, 300, 380 % 20)。角度变为20(这很好),但在下一次迭代中,Clamp(20, 300, 380)的角度变为300(这会导致奇怪的跳跃)。

让我们重新审视这个问题:

让我们首先定义一些术语,以确保我们都在同一页。(你的措辞让我有点困惑,但这应该不重要)。

TargetAngle,您不希望偏离的角度超过少量

Deviation,最小和最大角度(TargetAngle - Deviation, TargetAngle + Deviation)

InputAngle,算法应该固定的角度

那么有三种情况

  1. TargetAngle - Deviation >= 0 && TargetAngle + Deviation < 360

最简单的问题。解决方法是使用夹子。angle = MathHelper.Clamp(InputAngle, TargetAngle - Deviation, TargetAngle + Deviation);

  • TargetAngle - Deviation > 0 && TargetAngle + Deviation > 360
  • 让我们看看如果我们取TargetAngle = 350deviation = 20,可接受的范围现在是350-360和0-10。在代码中这是:

    // Fix the lower bound, angle might be larger than 360    
    if(angle >= TargetAngle - Deviation)
    {
        MathHelper.Clamp(angle, TargetAngle - Deviation, TargetAngle + Deviation);
    }
    // Wrap around, let angle be in the 0-360 range
    angle = angle % 360
    // If angle has become, or is smaller than the minimum value, check if
    // its in the lower range (0-10) in our example
    if(angle < TargetAngle - Deviation)
    {
        MathHelper.Clamp(angle, 0, (TargetAngle + Deviation) % 360);
    }
    
  • TargetAngle - Deviation < 0 && TargetAngle + Deviation < 360
  • 让我们以TargetAngle = 10deviation = 20为例。可接受的范围现在是0-30 350-360。你可以用我解决第二种情况的方法来解决这个问题。

    请注意,代码显然可以简化。但是首先覆盖所有的情况,然后测试它是否有效,然后开始简化:)。

    public static float AngleBound (float Angle, float BoundAngle, ushort Degrees)
    {
        var RadDegrees = Degrees * Math.PI / 180;
        var MinBound = BoundAngle - RadDegrees; 
        var MaxBound = BoundAngle + RadDegrees; 
        if (MinBound < 0)
            MinBound += 2*Math.PI;
        if (MaxBound > 2*Math.PI)
            MinBound -= 2*Math.PI;
        if (Angle <= MinBound)
            return MinBound;
        if (Angle >= MaxBound)
            return MaxBound;
        return Angle;
    }