• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Help with angles (0/360) - real comparison

Status
Not open for further replies.
Level 7
Joined
Nov 19, 2015
Messages
283
This is a issue I've had with backstab and other similar triggers before in the past. I just played around with the numbers before until it worked but I didn;t really understand them.

So I have a conditions which are real comparisons.
I check whether it is greater than X_angle but less than Y_angle
What I don't get is when its around the 0 degrees/ 360 degrees.

Say I compared an angle which is less than X+90 and greater than X-90.
If X was in the 300s. Angle 350 would be less than X+90 but angle 10 would not be.

Can someone please explain to me how angles work in WE and if a real comparison is the correct thing to do.

Currently I am doing a homing missile trigger. It checks whether the unit is on the left or right of the missile and will change the angle to face it, taking the shortest turn (I don't want to make the unit have an order with a low turn rate).
 

Dr Super Good

Spell Reviewer
Level 63
Joined
Jan 18, 2005
Messages
27,191
You do not compare angles, you compare cosine or sine of angles.

For example the cosine of the angle is greater than 0. This gives you a 180 degree arc centred to the positive side of the x axis.

You get the angle between victim and the source and then subtract it by the facing of the victim. You then push it through cos. You can then compare that cos value if it is less than some cutoff cos value. For example a cutoff cos value of Cos(10 degrees) will give you a range of 10 degrees from the back of the unit.
 
Level 7
Joined
Nov 19, 2015
Messages
283
You do not compare angles, you compare cosine or sine of angles.

For example the cosine of the angle is greater than 0. This gives you a 180 degree arc centred to the positive side of the x axis.

You get the angle between victim and the source and then subtract it by the facing of the victim. You then push it through cos. You can then compare that cos value if it is less than some cutoff cos value. For example a cutoff cos value of Cos(10 degrees) will give you a range of 10 degrees from the back of the unit.

  • Angle test
    • Events
      • Time - Every 0.10 seconds of game time
    • Conditions
    • Actions
      • Set TempLoc[0] = (Position of Hero 0001 <gen>)
      • Set TempLoc[1] = (Position of Hero 0002 <gen>)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Cos(((Angle from TempLoc[0] to TempLoc[1]) - (Facing of Hero 0001 <gen>)))) Less than or equal to Cos(90.00)
        • Then - Actions
          • Floating Text - Create floating text that reads (String((Angle from TempLoc[0] to TempLoc[1]))) above Hero 0001 <gen> with Z offset 0.00, using font size 10.00, color (0.00%, 100.00%, 0.00%), and 0.00% transparency
        • Else - Actions
          • Floating Text - Create floating text that reads (String((Angle from TempLoc[0] to TempLoc[1]))) above Hero 0001 <gen> with Z offset 0.00, using font size 10.00, color (100.00%, 0.00%, 0.00%), and 0.00% transparency
      • Floating Text - Change (Last created floating text): Disable permanence
      • Floating Text - Change the lifespan of (Last created floating text) to 0.11 seconds
      • Floating Text - Change the fading age of (Last created floating text) to 0.10 seconds
      • Custom script: call RemoveLocation(udg_TempLoc[0])
      • Custom script: call RemoveLocation(udg_TempLoc[1])

This is what I have but it's not really working. Its been a while since I've had tto use maths so I'm a bit rusty and can't really picture it in my head.

EDIT!! Don't worry, I got it. Thanks heaps. That Cos was really helpful
 
Last edited:
Level 24
Joined
Aug 1, 2013
Messages
4,657
I prefer to substract angle X from angle Y and check if the result is both greater than -Z and lower than Z. (Where Z is the maximum angle difference allowed to both sides... for example a Z of 90 will result in half a circle.)
To make this work, the result of X - Y has to be between -180 and 180 for which I use a custom function.

I don't know about efficiency between 3 cosines but both should be pretty high performance solutions.
 
Level 7
Joined
Nov 19, 2015
Messages
283
I prefer to substract angle X from angle Y and check if the result is both greater than -Z and lower than Z. (Where Z is the maximum angle difference allowed to both sides... for example a Z of 90 will result in half a circle.)
To make this work, the result of X - Y has to be between -180 and 180 for which I use a custom function.

I don't know about efficiency between 3 cosines but both should be pretty high performance solutions.

I used to do that too but the problem I had was that when going towards 360, it shifts from being a big number (360) to a small number (0). Thats why I think the real comparisons might have trouble.
 
Level 7
Joined
Nov 19, 2015
Messages
283
Ahhh ... sorry, my bad. I get what you mean now. What did you mean about the efficiency of three cosines? Does it take a while to calculate?
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
It is still a calculation... 1+1 takes some processing time, 1*1 takes some processing time, 1%1 takes a bit more because of how it works, 1^1 takes a bit more than the first 2, etc.
Everything cost some processing time, but how much, I don't really know at this point and cosine may or may not be faster, but the differences are negligible.
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
JASS:
    function NormalizeAngle takes real angle returns real
        loop
            if angle < 0 then
                set angle = angle + 360
            elseif angle >= 360 then
                set angle = angle - 360
            else
                return angle
            endif
        endloop
        return 0.
    endfunction
    
    function DeNormalizeAngle takes real angle returns real
        loop
            if angle <= -180 then
                set angle = angle + 360
            elseif angle > 180 then
                set angle = angle - 360
            else
                return angle
            endif
        endloop
        return 0.
    endfunction

My custom function :D
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
ModuloReal does -180 -> 180 ?

ModuloReal(angle, 360) - 180 would work though.

Wait... does Modulo return negative values out of negative parameters? Cause in that case it would be "ModuloReal(Max(angle, -angle), 360) - 180".

I considered making my function with ModuloReal, but I guess this will do just fine... dunno about efficiency between 'em.
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
The second function isn't really more interesting than the first.
I didn't use modulo because I didn't think about it at that moment... I could use it, but I don't really care so much about which is faster than the other.

ModuloInteger and ModuloReal can return negative values when used: "call ModuloReal(-450, 360)" for example.
It is a rare occurence but the fact still remains that it will break the maths.
 

Zwiebelchen

Hosted Project GR
Level 35
Joined
Sep 17, 2009
Messages
7,236
@Zwieb, And if the angle is less than -360 or greater than 720, the check fails.
This only happens if you add more than 360 or less than -360 in an arithmetic operation, as none of the trigonometric functions will return an angle larger than 2*pi.

If you normalize every value individually when retrieved, there is no way you can have more than 720 or less than -360.
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
Look at my nice style:
KWTVSKc.png

(Source: TimerUtils)
 

Zwiebelchen

Hosted Project GR
Level 35
Joined
Sep 17, 2009
Messages
7,236
Or you could avoid hacky and lenghier solutions and just call that function. I hate that every BJ function is red even if it's completely fine.
How is that hacky or lenghty?
When do you ever add/substract more than 360 degrees?

And yes, Modulo is a good BJ. But if it's not needed, why add a pointless loop?
 
Level 7
Joined
Nov 19, 2015
Messages
283
I've been using the sine and cosine so far and I understand it better.

So can someone tell me if I should be using modulo or the sin/cos? I want to learn the most effective method.
 

Dr Super Good

Spell Reviewer
Level 63
Joined
Jan 18, 2005
Messages
27,191
Most efficient is probably sine/cosine approach because of how JASS works. Specifically there is no native modulo method (instead it is emulated) and the normal complexities of Sine/Cosine get drowned out so much by the JASS overhead that ultimately the time cost is mostly the function call.
 
Status
Not open for further replies.
Top