夹角到任意范围
Clamp angle to arbitrary range
我需要一个函数来将角度(以度为单位)限制在任意范围内 [min,max]
。这里有些例子:
彩色区域代表有效角度范围。
- 在图像 #1 中,ang 应被限制为 max (-90)
- 在图像 #2 中,ang 应被限制在 min (135)
- 在图像 #3 中,ang 应该被限制在 min (135)
这是我目前拥有的:
static float clamp_angle(float ang,float min,float max)
{
ang = normalize_angle(ang); // normalize_angle transforms angle into [-180,180) range
min = normalize_angle(min);
max = normalize_angle(max);
if(angle_in_range(ang,min,max) == false)
{
if(abs(get_angle_difference(ang,min)) < abs(get_angle_difference(ang,max))
ang = min; // Clamp to min if we're closer to min than max
else
ang = max;
}
return ang;
}
我缺少的是函数 angle_in_range
(true
如果角度在范围内,否则 false
)。
确定角度是否在范围内的最简单方法是什么?
假设您使用顺时针顺序。
cw顺序的min和max的距离为dist(min, max) = (max - min)mod N
假设点在区域内。然后 dist(min,A) + dist(A,max) = dist(min,max)。现在您可以测量点 A、最小值和最大值之间的距离:dist(min, A)= (A - min)modN
距离(A,最大值)=(max-A)modN。如果在外部区域,则距离之和应为 N+dist(min, max),如果在内部则应等于 dist(min,max)
在你的情况下 N = 360,所有值都在 [0,360)
编辑:在大多数语言中,(-x)modX 的行为是未定义的,因此您应该手动将 -x 转换为正数,例如(-x + X)modX 其中 x 位于 [0,X)
您可以将角度归一化为 ang 变为 0,min 和 max 映射到 [-180; 180)。然后你可以像这样检查角度是否在提供的范围内:
float clamp_angle(const float ang, const float min, const float max)
{
float n_min = normalize180(min-ang);
float n_max = normalize180(max-ang);
if (n_min <= 0 && n_max >= 0)
{
return ang;
}
if (abs(n_min) < abs(n_max))
return min;
return max;
}
如果你想限制角度,使其保持在范围内,但当它达到最大值或最小值时环绕(而不是限制到极限),那么你可以使用这个相当简单的函数,我使用 python:
def clamp_to_range(value, min, max):
return (value % (max - min)) + min
它的行为是这样的:
>>> for i in range(0, 30): print("|{:<30}|{:<30}|".format(" "*(clamp_to_range(i, 4, 15)) + "♥", " "*i + "♥"))
...
| ♥ |♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥|
正如我提到的,它环绕。如果您想将值限制在指定范围内,则可以使用此函数:
def clip_to_range(value, min_, max_): # underscores added to avoid name collisions
return min(max_, max(value, min_))
在这种情况下会发生:
>>> for i in range(0, 30): print("|{:<30}|{:<30}|".format(" "*clip_to_range(i, 4, 15) + "♥", " "*i + "♥"))
...
| ♥ |♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥|
clamp_to_range
函数的 C 模拟如下所示:
#include <math.h>
float clampInRange(float value, float min, float max)
{
return fmod(value, max - min) + min;
}
我需要一个函数来将角度(以度为单位)限制在任意范围内 [min,max]
。这里有些例子:
彩色区域代表有效角度范围。
- 在图像 #1 中,ang 应被限制为 max (-90)
- 在图像 #2 中,ang 应被限制在 min (135)
- 在图像 #3 中,ang 应该被限制在 min (135)
这是我目前拥有的:
static float clamp_angle(float ang,float min,float max)
{
ang = normalize_angle(ang); // normalize_angle transforms angle into [-180,180) range
min = normalize_angle(min);
max = normalize_angle(max);
if(angle_in_range(ang,min,max) == false)
{
if(abs(get_angle_difference(ang,min)) < abs(get_angle_difference(ang,max))
ang = min; // Clamp to min if we're closer to min than max
else
ang = max;
}
return ang;
}
我缺少的是函数 angle_in_range
(true
如果角度在范围内,否则 false
)。
确定角度是否在范围内的最简单方法是什么?
假设您使用顺时针顺序。 cw顺序的min和max的距离为dist(min, max) = (max - min)mod N 假设点在区域内。然后 dist(min,A) + dist(A,max) = dist(min,max)。现在您可以测量点 A、最小值和最大值之间的距离:dist(min, A)= (A - min)modN 距离(A,最大值)=(max-A)modN。如果在外部区域,则距离之和应为 N+dist(min, max),如果在内部则应等于 dist(min,max)
在你的情况下 N = 360,所有值都在 [0,360)
编辑:在大多数语言中,(-x)modX 的行为是未定义的,因此您应该手动将 -x 转换为正数,例如(-x + X)modX 其中 x 位于 [0,X)
您可以将角度归一化为 ang 变为 0,min 和 max 映射到 [-180; 180)。然后你可以像这样检查角度是否在提供的范围内:
float clamp_angle(const float ang, const float min, const float max)
{
float n_min = normalize180(min-ang);
float n_max = normalize180(max-ang);
if (n_min <= 0 && n_max >= 0)
{
return ang;
}
if (abs(n_min) < abs(n_max))
return min;
return max;
}
如果你想限制角度,使其保持在范围内,但当它达到最大值或最小值时环绕(而不是限制到极限),那么你可以使用这个相当简单的函数,我使用 python:
def clamp_to_range(value, min, max):
return (value % (max - min)) + min
它的行为是这样的:
>>> for i in range(0, 30): print("|{:<30}|{:<30}|".format(" "*(clamp_to_range(i, 4, 15)) + "♥", " "*i + "♥"))
...
| ♥ |♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥|
正如我提到的,它环绕。如果您想将值限制在指定范围内,则可以使用此函数:
def clip_to_range(value, min_, max_): # underscores added to avoid name collisions
return min(max_, max(value, min_))
在这种情况下会发生:
>>> for i in range(0, 30): print("|{:<30}|{:<30}|".format(" "*clip_to_range(i, 4, 15) + "♥", " "*i + "♥"))
...
| ♥ |♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥ |
| ♥ | ♥|
clamp_to_range
函数的 C 模拟如下所示:
#include <math.h>
float clampInRange(float value, float min, float max)
{
return fmod(value, max - min) + min;
}