ID:156298
 
I'm trying to check if my Vector/Angle is between two other Vectors/Angles, but I'm having problem around -180/+180 point, since function returns values between -180 and 180.

My atan2 function:
proc
arctan(x)
var/y=arcsin(x/sqrt(1+x*x))
if(x>=0)
return y
return -y

arctan2(dy, dx)
if(dy == 0)
if(dx > 0)
return 0
else if(dx == 0)
return 0
else
return 180
if(dx == 0)
if(dy > 0)
return 90
else if(dy == 0)
return 0
else
return -90
else
var/angle = arctan(dy/dx)
if(dx < 0)
angle = 180 - angle
if(dy < 0)
angle = -angle
return angle


Here's small visualization what values it returns:


I'll refer to this image:

Red vector (named direction) is direction
Two blue vectors represent range where I want to do something
α (alpha) is "falloff" of direction
Purple vector (v) is the vector which I need to check if it's between two blues.
In other words, I need to check if (v) is between (direction-α) and (direction+α)

Here's what I have atm:
            for(var/L in b)
var
dirX = (x + oX + 0.125) - (L.x + 0.5)
dirY = (y + oY + 0.125) - (L.y + 0.5)
var
angle = arctan2(dirX, dirY)
if(angle < L.direction - L.angle/2 || angle > L.direction + L.angle/2)
continue

In this piece of code, dirX and dirY are x/y values of (v), 'angle' is angle in degrees of my (v), (L.direction - L.angle/2) and (L.direction + L.angle/2) are (direction-α) and (direction+α).

Code works fine, unless my direction is 180 degree (the -y direction). It checks correctly when (v) is <180, but makes mistake when (v) > -180.

I'm sorry if I failed to explain.

Thank you in advance.
EDIT: Ignore this, Garthor's suggestion is better.

Let a1 be the angle of the alpha vector on the left (- alpha) side of d, a2 be the angle of the alpha vector on the right (+ alpha) side.

Let v be the angle of the vector you're testing.

var/x = v - a1
while(x > 180) x -= 360
while(x < -180) x += 360

return x < (a2 - a1)


That should work (completely untested) assuming that alpha < 90, also assuming angles are in degrees. Conversion to radians is easy enough.

Basically it works by making a1 the zero point and then checking if we're within a2. Angles are fiddled with such that being pushed past -180 or 180 flips sign appropriately. The reason it doesn't work for cases where alpha is >= 90 is because it ends up taking the smaller angle.

Not at all sure if this is the fastest or most correct way to do it, but it feels functional. If you need alpha >= 90, comment again and I'll think about it some more.
All you should need is arccos(dot(v,d)), where dot() is the dot product (v.x*d.x + v.y*d.y). The range is only 0 to 180 degrees, but you don't seem to care about left or right so that's not much of an issue.
In response to Jp (#1)
Thank you both. After some testing figured I could simply find angle between direction and v, then simply check: if angle between direction and v is higher than alpha, it's not inside.
angle3 = arccos(cos(angle)*cos(L.direction) + sin(angle)*sin(L.direction)) //dot product method, thanks to Garthor
if(angle3 > L.angle/2) //if true then not inside
continue


Tested with 30, 90, 120, 140, 300 degree angles and it's all correct.