• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

Capping angles

Status
Not open for further replies.
Hello everyone!

I have an object which uses pitch/yaw angles, and i want to cap them to a min anx max value (to limit turning area). Now, the thing is, the angle goes between 30 and -30, which when i use the modulo to get the actual angle, becomes 30 and 330. This is a problem, because the angle is supposed to be capped between larger than 330, but smaller than 30. How can i enforce this?
 
this is object editor problem, so I dont think he can use conditional statement

Isnt the maximum-minimum pitch in radians?


No, it is not an object editor problem. The pitch and yaw angles are real variables which are in radians.
Imagine the pitch angle as an arrow. When it is pointing forwards, the pitch angle is 0. If i rotate it with an angle of -PI*0.5, after using ModuloReal(angle, 2*PI), the new angle becomes 1.5*PI. Explain to me how this conditional statement would look.
 
It depends. If you know what the desired difference is (30 - (-30)) = 60 degree difference, then the conditional check would be:
JASS:
function IsApproximatelyEqual takes real A, real B, real margin returns boolean
    return (A-margin) < B and (A+margin) > B
endfunction

function IsBetweenAngles takes real angleToCheck, real lowerAngle, real upperAngle, real difference returns boolean
    if IsApproximatelyEqual(lowerAngle - upperAngle, difference, 0.1) then
    // this function just checks if they are close, within 0.1, ignoring floating point issues
        
        // the difference matches up, so the two angles are fine
        return angleToCheck >= lowerAngle and angleToCheck <= upperAngle
        
    endif

    // The difference is not equal, therefore you need a different comparison
    return angleToCheck >= upperAngle or angleToCheck <= lowerAngle
endfunction

Untested. Something along those lines though.

The function just checks if the angle "angleToCheck" is within "lowerAngle" and "upperAngle" (you may have to use RMin/RMax for that). The problem, though, is that it doesn't know whether to check if it is within lowerAngle and upperAngle (angleToCheck >= lowerAngle and angleToCheck <= upperAngle), or whether to check if it is above the upperAngle or below the lowerAngle.

There are many ways to determine that, but the computer obviously won't know which one you want. Thus, I just wrote a part that will check if the desired difference is equal to the one you want. e.g. in your case, you would input:
IsBetweenAngles(<some angle>, 30, 330, 60)
Then it will know that you want to have <some angle> below 30 or above 330, because 330 - 30 != 60. If you input "300" in place of 60, then it would just check if <some angle> is >= 30 and <= 330.
 
Thank you, but i feel like there must be a more intuitive solution to this. I perhaps the best would be if we were to get the angle within the span of -180 < a < 180. What if we were to substract 360 from the angle if it surpasses 180, then compare it, cap it to the min/max, and finally add the 360 again, if the result is lower than 0? Do you think that would work?
 
Level 37
Joined
Mar 6, 2006
Messages
9,243
I use Cos for checking angle differences. Cos(a-b) = angle differece, returns values between -1 and 1. You can convert that to radians if needed.


  • Test
    • Events
      • Time - Every 0.20 seconds of game time
    • Conditions
    • Actions
      • -------- -------------------------------------------------- --------
      • -------- Set unit variables --------
      • -------- -------------------------------------------------- --------
      • Set u1 = Paladin 0003 <gen>
      • Set u2 = Blood Mage 0000 <gen>
      • -------- -------------------------------------------------- --------
      • -------- Set location variables --------
      • -------- -------------------------------------------------- --------
      • Set p1 = (Position of u1)
      • Set p2 = (Position of u2)
      • -------- -------------------------------------------------- --------
      • Set r1 = (Cos(((Angle from p1 to p2) - (Facing of u1))))
      • Set r2 = (Cos(30.00)) // Cos works with degrees...
      • Custom script: set udg_r2 = Cos(30 * bj_DEGTORAD) // ..and radians, doesn't matter which is used
      • -------- -------------------------------------------------- --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • r1 Greater than r2
        • Then - Actions
          • Game - Display to Player Group - Player 1 (Red) for 0.20 seconds the text: Inside
        • Else - Actions
          • Game - Display to Player Group - Player 1 (Red) for 0.20 seconds the text: Outside
      • Custom script: call RemoveLocation(udg_p1)
      • Custom script: call RemoveLocation(udg_p2)
 

Attachments

  • Angle_Difference.w3x
    25 KB · Views: 45
Status
Not open for further replies.
Top