C++ 确定角度是否位于其他两个角度之间

C++ 确定角度是否位于其他两个角度之间,c++,math,trigonometry,C++,Math,Trigonometry,我试图弄清楚一个角是否位于另外两个角之间。我一直在尝试创建一个简单的函数来执行此操作,但我的任何技术都不能适用于所有可能的角度值 您能帮我编辑我的函数以正确确定一个角度是否位于其他两个角度之间吗? 在上图中;我使用绿点作为中心点,然后确定每条线与绿点的角度。然后计算黑点与绿点的夹角。我试图检查黑点的角度是否在两条线的角度之间 注:就我而言;如果两个角度之间的差值小于180度且目标角度位于由这两个角度形成的空腔中,则称角度(目标角度)位于其他两个角度之间 以下代码应该可以工作,但对于这些(位于角

我试图弄清楚一个角是否位于另外两个角之间。我一直在尝试创建一个简单的函数来执行此操作,但我的任何技术都不能适用于所有可能的角度值

您能帮我编辑我的函数以正确确定一个角度是否位于其他两个角度之间吗?

在上图中;我使用绿点作为中心点,然后确定每条线与绿点的角度。然后计算黑点与绿点的夹角。我试图检查黑点的角度是否在两条线的角度之间

注:就我而言;如果两个角度之间的差值小于180度且目标角度位于由这两个角度形成的空腔中,则称角度(目标角度)位于其他两个角度之间

以下代码应该可以工作,但对于这些(位于角度之间的)代码失败:
-角度是否介于(150、190、110)
-角度在(3,41,345)之间

bool是(int-target,int-angle1,int-angle2)之间的角度
{  
int rAngle1=((iTarget-iAngle1)%360+360)%360;
int rAngle2=((iAngle2-iAngle1)%360+360)%360;

return(0我从线程中找到了以下引用:

如果点p在三角形ABC内,则

区域PAB+区域PBC+区域PAC=区域ABC

请注意,如果p位于AB、BC或CA的边缘,则上述值保持不变 实际上,PAB、PBC、PAC中的一个区域是0(所以请确保 检查一下)

如果p在外,上述等式不成立

如何确定面积?你有两个选择:1)Heron定理, 涉及sqrt,速度较慢2)交叉积的方法越有效 (或有效地,绝对值的一半 产品减去产品总和)

例如,如果A=(x1,y1)B=(x2,y2),C=(x3,y3)面积= abs(x1*y2+x2*y3+x3*y1-x1*y3-x3*y2-x2*y1)/2

另外,您可能需要小心浮点错误。。。 检查abs(b-a),而不是检查严格的不等式
如果angle2始终为0,angle1始终在0和180之间,希望这会有所帮助,这将很容易:

return angle1 < 180 && 0 < target && target < angle1;
返回角度1<180&&0
如果我正确阅读了需求

但到那里并不难

int reduced1 = (angle1 - angle2 + 360) % 360; // and imagine reduced2 = 0
if (180 < reduced1) { angle2 = angle1; reduced1 = 360 - reduced1; } // swap if backwards
int reducedTarget = (target - angle2 + 360) % 360;
return reduced1 < 180 && 0 < reducedTarget && reducedTarget < reduced1;
int reduced1=(angle1-angle2+360)%360;//想象reduced2=0
if(180
bool是(内部目标、内部角度1、内部角度2)之间的角度
{
//使从角度1到角度2的角度等于180)
标准:交换(角度1,角度2);
//检查是否通过零点

如果(angle1=angle1&&target=angle1 | | target

在上面的草图中,当且仅当

angle BAD + angle CAD == angle BAC
由于浮点不准确,我先将数值四舍五入到小数点后5位,然后比较数值

所以它归结为在两个向量
p
q
之间有一个角度算法,简单地说如下:

double a = p.DotProduct(q);
double b = p.Length() * q.Length();
return acos(a / b); // radians
我将把矢量点积和长度计算留作谷歌搜索练习,只需将一个终端的坐标减去另一个终端的坐标即可得到矢量


当然,您应该首先检查AB和AC是平行的还是反平行的。

使用与您的问题类似的函数样式,我很幸运地使用了以下方法:

    public static bool IsInsideRange(double testAngle, double startAngle, double endAngle)
    {
        var a1 = System.Math.Abs(AngleBetween(startAngle, testAngle));
        var a2 = System.Math.Abs(AngleBetween(testAngle, endAngle));
        var a3 = System.Math.Abs(AngleBetween(startAngle, endAngle));
        return a1 + a2 == a3;
    }

    public static double AngleBetween(double start, double end)
    {
        return (end - start) % 360;
    }

我知道这篇文章很老,但似乎没有一个被接受的答案,我发现下面的方法非常可靠。虽然它可能比你需要的要多。它支持大于180度的角度范围(以及大于360度和负角度)。它还支持十进制精度

该方法使用此
normalize()
helper函数将角度转换为正确的空间:

float normalize( float degrees )
{
  //-- Converts the specified angle to an angle between 0 and 360 degrees
  float circleCount = (degrees / 360.0f);
  degrees -= (int)circleCount * 360;
  if( 0.0f > degrees )
  {
    degrees += 360.0f;
  }
  return degrees;
}
以下是解决方案:

bool isWithinRange( float start, float end, float angle )
{
  if( fabsf( end - start ) >= 360.0f )
  {
    //-- Ranges greater or equal to 360 degrees cover everything
    return true;
  }

  //-- Put our angle between 0 and 360 degrees
  float degrees = normalize( angle );

  //-- Resolve degree value for the start angle; make sure it's
  //   smaller than our angle.
  float startDegrees = normalize( start );
  if( startDegrees > degrees )
  {
    startDegrees -= 360.0f;
  }

  //-- Resolve degree value for the end angle to be within the
  //   same 360 degree range as the start angle and make sure it
  //   comes after the start angle.
  float endDegrees = normalize( end );
  if( endDegrees < startDegrees )
  {
    endDegrees += 360.0f;
  }
  else if( (endDegrees - startDegrees) >= 360.0f )
  {
    endDegrees -= 360.0f;
  }

  //-- All that remains is to validate that our angle is between
  //   the start and the end.
  if( (degrees < startDegrees) || (degrees > endDegrees) )
  {
    return false;
  }

  return true;
}
bool在范围内(浮动开始、浮动结束、浮动角度)
{
如果(fabsf(结束-开始)>=360.0f)
{
//--大于或等于360度的范围涵盖一切
返回true;
}
//--把我们的角度放在0到360度之间
浮动度=标准化(角度);
//--解析起始角度的度数值;确保
//比我们的角度小。
浮动开始度=正常化(开始);
如果(起始角度>度)
{
起始角度-=360.0华氏度;
}
//--解析端点角度的度值,使其在
//与起始角度相同的360度范围,并确保
//在起始角之后。
浮动结束度=标准化(结束);
if(端度<起始度)
{
端度+=360.0f;
}
如果((端度-起始度)>=360.0f,则为else
{
端度-=360.0f;
}
//--剩下的就是确认我们的角度在
//开始和结束。
如果((度<开始度)| |(度>结束度))
{
返回false;
}
返回true;
}
希望这对其他人有所帮助。

void normalize(浮动和角度)
void normalize( float& angle ) 
{
    while ( angle < -180 ) angle += 360;
    while ( angle >  180 ) angle -= 360;
}

bool isWithinRange( float testAngle, float a, float b )
{
    a -= testAngle;
    b -= testAngle;
    normalize( a );
    normalize( b );
    if ( a * b >= 0 )
        return false;
    return fabs( a - b ) < 180;
}
{ 而(角度<-180)角度+=360; 而(角度>180)角度-=360; } 布尔值在范围内(浮动测试角、浮动a、浮动b) { a-=测试角; b-=测试角; 正常化(a); 正常化(b); 如果(a*b>=0) 返回false; 返回晶圆厂(a-b)<180; }
灵感来自一篇关于:


如果您有角度$$a$和$b$,并且不想查看角度
x
是否在这些角度之间

您可以计算
a->x
a->b
之间的角度。 如果
∠a->x
小于
∠a->b
x
必须介于
a
b
之间

距离
float normalize( float degrees )
{
  //-- Converts the specified angle to an angle between 0 and 360 degrees
  float circleCount = (degrees / 360.0f);
  degrees -= (int)circleCount * 360;
  if( 0.0f > degrees )
  {
    degrees += 360.0f;
  }
  return degrees;
}
bool isWithinRange( float start, float end, float angle )
{
  if( fabsf( end - start ) >= 360.0f )
  {
    //-- Ranges greater or equal to 360 degrees cover everything
    return true;
  }

  //-- Put our angle between 0 and 360 degrees
  float degrees = normalize( angle );

  //-- Resolve degree value for the start angle; make sure it's
  //   smaller than our angle.
  float startDegrees = normalize( start );
  if( startDegrees > degrees )
  {
    startDegrees -= 360.0f;
  }

  //-- Resolve degree value for the end angle to be within the
  //   same 360 degree range as the start angle and make sure it
  //   comes after the start angle.
  float endDegrees = normalize( end );
  if( endDegrees < startDegrees )
  {
    endDegrees += 360.0f;
  }
  else if( (endDegrees - startDegrees) >= 360.0f )
  {
    endDegrees -= 360.0f;
  }

  //-- All that remains is to validate that our angle is between
  //   the start and the end.
  if( (degrees < startDegrees) || (degrees > endDegrees) )
  {
    return false;
  }

  return true;
}
void normalize( float& angle ) 
{
    while ( angle < -180 ) angle += 360;
    while ( angle >  180 ) angle -= 360;
}

bool isWithinRange( float testAngle, float a, float b )
{
    a -= testAngle;
    b -= testAngle;
    normalize( a );
    normalize( b );
    if ( a * b >= 0 )
        return false;
    return fabs( a - b ) < 180;
}
static bool is_angle_between(int x, int a, int b) {
    b = modN(b - a);
    x = modN(x - a);

    if (b < 180) {
        return x < b;
    } else {
        return b < x;
    }
}
// modN(x) is assumed to calculate Euclidean (=non-negative) x % N.
static int modN(int x) {
    const int N = 360;
    int m = x % N;
    if (m < 0) {
        m += N;
    } 
    return m;
}
function distanceBetweenAngles(a, b) {
    distance = b - a;
    if (a > b) {
       distance += 2*pi;
    }
    return distance;
}
// Checks if angle 'x' is between angle 'a' and 'b'
function isAngleBetween(x, a, b) {
    return distanceBetweenAngles(a, b) >= distanceBetweenAngles(a, x);
}
bool isAngleBetweenNormalizedSmallSweepRange(int test, int a, int b) {
    int a_adjust = ((((a - test + 180)) % 360) + 360) % 360 - 180;
    int b_adjust = ((((b - test + 180)) % 360) + 360) % 360 - 180;
    return ((a_adjust ^ b_adjust) < 0) && ((a_adjust - b_adjust) < 180) && ((a_adjust - b_adjust) > -180);
}
int normalized(int a, int test) {
    int n = a - test + 180;
    if ((n > 360) || (n < -360)) n %= 360;
    return (n > 0)? n - 180: n + 180;
}

bool isAngleBetweenNormalizedSmallSweepRange(int test, int a, int b) {
    int a_adjust = normalized(a,test);
    int b_adjust = normalized(b,test);
    return ((a_adjust ^ b_adjust) < 0) &&
            ((a_adjust > b_adjust)? a_adjust-b_adjust: b_adjust-a_adjust) < 180;
}
bool isAngleBetweenNormalizedSmallSweepRange(int test, int a, int b) {
    int dA = a - test + 180;
    if (dA > 360) {
        dA -= 360;
    }
    int a_adjust = (dA > 0) ? dA - 180 : dA + 180;
    int dB = b - test + 180;
    if (dB > 360) {
        dB -= 360;
    }
    int b_adjust = (dB > 0) ? dB - 180 : dB + 180;
    return ((a_adjust ^ b_adjust) < 0)
            && ((a_adjust > b_adjust) ? a_adjust - b_adjust : b_adjust - a_adjust) < 180;
}
if(angle1 <= angle2) {
    if(angle2 - angle1 <= PI) {
        return angle1 <= target && target <= angle2;
    } else {
        return angle2 <= target || target <= angle1;
    }
} else {
    if(angle1 - angle2 <= PI) {
        return angle2 <= target && target <= angle1;
    } else {
        return angle1 <= target || target <= angle2;
    }
}
angle1 <= angle2 ?
(angle2 - angle1 <= PI && angle1 <= target && target <= angle2) || (angle2 - angle1 > PI && (angle2 <= target || target <= angle1)) :
(angle1 - angle2 <= PI && angle2 <= target && target <= angle1) || (angle1 - angle2 > PI && (angle1 <= target || target <= angle2))