将角度固定为方向
Fix Angle into Direction
我想固定一个角度
问题 - 视频:https://youtu.be/5LGbYguG4P0
例如:
我有 90 度角,我想固定 45 度(所以它不能 less/more 比 (90 - 45) 或 (90 + 45)。
在过去的几个小时里,我尝试了多种方法,并在互联网上进行了搜索。
有些工作主要是因为它们 "wrap" 由于内置角度环绕(我认为它的环绕是 -Pi 到 Pi)而错误,所以当它达到 -Pi 或 Pi 并超过,它环绕,并大跳到相反的角度。
尝试次数:
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)
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;
}
到目前为止的所有答案都没有考虑到 Clamp(380, 300, 380 % 20)
。角度变为 20(这很好)但在下一次迭代中 Clamp(20, 300, 380)
角度变为 300(这导致了奇怪的跳跃)。
让我们重温一下这个问题:
让我们首先定义一些术语以确保我们都在同一页面上。 (你的措辞让我有点困惑,但应该不重要)。
TargetAngle
,你不希望偏离的角度多一点
Deviation
,最小和最大角度(TargetAngle - Deviation
,TargetAngle + Deviation
)
InputAngle
,算法应该固定的角度
那么就是三种情况
TargetAngle - Deviation >= 0 && TargetAngle + Deviation < 360
最简单的问题。解决方案是使用夹子。 angle = MathHelper.Clamp(InputAngle, TargetAngle - Deviation, TargetAngle + Deviation);
TargetAngle - Deviation > 0 && TargetAngle + Deviation > 360
让我们看看如果我们采用 TargetAngle = 350
和 deviation = 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 = 10
和 deviation = 20
。可接受的范围现在是 0-30 350-360。你可以用我解决第二种情况的方法解决这个问题。
请注意,代码显然可以简化。但首先覆盖所有情况,然后测试它是否有效,然后开始简化:).
我想固定一个角度
问题 - 视频:https://youtu.be/5LGbYguG4P0
例如:
我有 90 度角,我想固定 45 度(所以它不能 less/more 比 (90 - 45) 或 (90 + 45)。
在过去的几个小时里,我尝试了多种方法,并在互联网上进行了搜索。
有些工作主要是因为它们 "wrap" 由于内置角度环绕(我认为它的环绕是 -Pi 到 Pi)而错误,所以当它达到 -Pi 或 Pi 并超过,它环绕,并大跳到相反的角度。
尝试次数:
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)
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;
}
到目前为止的所有答案都没有考虑到 Clamp(380, 300, 380 % 20)
。角度变为 20(这很好)但在下一次迭代中 Clamp(20, 300, 380)
角度变为 300(这导致了奇怪的跳跃)。
让我们重温一下这个问题:
让我们首先定义一些术语以确保我们都在同一页面上。 (你的措辞让我有点困惑,但应该不重要)。
TargetAngle
,你不希望偏离的角度多一点
Deviation
,最小和最大角度(TargetAngle - Deviation
,TargetAngle + Deviation
)
InputAngle
,算法应该固定的角度
那么就是三种情况
TargetAngle - Deviation >= 0 && TargetAngle + Deviation < 360
最简单的问题。解决方案是使用夹子。 angle = MathHelper.Clamp(InputAngle, TargetAngle - Deviation, TargetAngle + Deviation);
TargetAngle - Deviation > 0 && TargetAngle + Deviation > 360
让我们看看如果我们采用 TargetAngle = 350
和 deviation = 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 = 10
和 deviation = 20
。可接受的范围现在是 0-30 350-360。你可以用我解决第二种情况的方法解决这个问题。
请注意,代码显然可以简化。但首先覆盖所有情况,然后测试它是否有效,然后开始简化:).