Determine if angle lies between 2 other angles

后端 未结 12 1556
予麋鹿
予麋鹿 2020-12-15 05:47

I am trying to figure out whether a angle lies between 2 other angles. I have been trying to create a simple function to perform this but none of my techniques will work for

相关标签:
12条回答
  • 2020-12-15 06:38
    bool is_angle_between(int target, int angle1, int angle2) 
    {
      // make the angle from angle1 to angle2 to be <= 180 degrees
      int rAngle = ((angle2 - angle1) % 360 + 360) % 360;
      if (rAngle >= 180)
        std::swap(angle1, angle2);
    
      // check if it passes through zero
      if (angle1 <= angle2)
        return target >= angle1 && target <= angle2;
      else
        return target >= angle1 || target <= angle2;
    }  
    
    0 讨论(0)
  • 2020-12-15 06:38

    All the top answers here are wrong. As such I feel it is necessary for me to post an answer.

    I'm just reposting a portion of an answer which I posted here: https://stackoverflow.com/a/42424631/2642059 That answer also deals with the case where you already know which angle is the lefthand side and righthand side of the reflexive angle. But you also need to determine which side of the angle is which.


    1st to find the leftmost angle if either of these statements are true angle1 is your leftmost angle:

    1. angle1 <= angle2 && angle2 - angle1 <= PI
    2. angle1 > angle2 && angle1 - angle2 >= PI

    For simplicity let's say that your leftmost angle is l and your rightmost angle is r and you're trying to find if g is between them.

    The problem here is the seem. There are essentially 3 positive cases that we're looking for:

    1. l ≤ g ≤ r
    2. l ≤ g ∧ r < l
    3. g ≤ r ∧ r < l

    Since you're calculating the lefthand and righthand sides of the angle, you'll notice there is an optimization opportunity here in doing both processes at once. Your function will look like:

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

    Or if you need it you could expand into this nightmare condition:

    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))
    

    Note that all this math presumes that your input is in radians and in the range [0 : 2π].

    Live Example

    0 讨论(0)
  • 2020-12-15 06:40

    I've found this quote from this thread:

    if a point P is inside triangle ABC, then

    Area PAB+Area PBC +Area PAC=Area ABC

    notice that if P is on the edge of AB, BC, or CA, the above hold. But effectively, one of the area PAB, PBC, PAC is 0 (so just make sure you check that).

    if P is outside, the above equality does NOT hold...

    How to determine area? you have two options: 1) Heron's theorem, involves sqrt, slower 2) the more perferred way is the cross products (or effectively, the half of absolute value of (sum of the down products minus the sum of up products))

    for example, if A=(x1,y1) B=(x2,y2), C=(x3,y3) Area= abs(x1*y2+x2*y3+x3*y1-x1*y3-x3*y2-x2*y1)/2

    also you might want to be careful about floating point errors... instead of checking for strict inequality, check for abs(b-a)

    Hopefully that will help

    0 讨论(0)
  • 2020-12-15 06:40

    Using a similar style of function as in your question, I have had good luck with the following methods:

        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;
        }
    
    0 讨论(0)
  • 2020-12-15 06:42
    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;
    }
    
    0 讨论(0)
  • 2020-12-15 06:43

    If angle2 were always 0, and angle1 were always between 0 and 180, this would be easy:

    return angle1 < 180 && 0 < target && target < angle1;
    

    if I'm reading the requirements correctly.

    But it's not that hard to get there.

    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;
    
    0 讨论(0)
提交回复
热议问题