# Maths query

Hi All - anyone know of a conversion of atan() to atan2() ? Apparently atan2() of an angle calculation returns -pi < 0 < pi.

@Bri_G Does one of there work for you.

``````function setup()
ang=25

print(math.atan(ang))
print(math.atan(math.deg(ang)))

print(math.atan2(ang))
print(math.atan2(math.deg(ang)))
end
``````

@Bri_G Or something like this.

``````function setup()
print(math.atan2(1)*180/math.pi)
end
``````
• `math.atan(y/x)` returns the angle from 0 to pi of the line with gradient `y/x`, so `(x,y)` and `(-x,-y)` return the same angle.
• `math.atan2(y,x)` returns the angle from -pi to pi of the ray through the point `(x,y)` so `(x,y)` and `(-x,-y)` return angles that differ by pi. (Note the order of the arguments is `y,x`.)

@dave1707 - thanks for the feedback, tried using them and slight improvement with the following line of code :

``````
angle = math.deg(math.atan(dy,dx))

``````

Didn’t produce the effect I wanted - now beginning to think it is language problem javascript to Lua. Just trying to duplicate some demo code and my Javascript is a little rusty - but I think it represents angles in a different form to Lua. Now investigating this. Will most what I am doing once I resolve it.

@LoopSpace - thanks for the feedback that’s the best definition I’ve seen so far and fits what I am trying to do.

p.s. Is atan2() in the reference section for Lua in the Codea reference? Didn’t see it.

@Bri_G If you describe what you’re trying to do, I can advise better on which to use (though the answer is most likely to be `atan2`). I know a little javascript so if you post the original code, I may be able to help translate it. The `atan`/`atan2` issue is different to radians vs degrees, but it may be that the latter is muddying the waters a bit (Codea isn’t consistent on when it uses degrees and when radians).

@Bri_G Run this. I don’t see a difference between atan and atan2.

``````function setup()
print("atan functions")

print("atan2 functions")
print(math.atan2(5,5)*180/math.pi)
print(math.atan2(-5,5)*180/math.pi)
print(math.atan2(-5,-5)*180/math.pi)
print(math.atan2(5,-5)*180/math.pi)
end
``````

@LoopSpace - no problem with that but an entry in the reference reflecting this would be useful and highlight the importance of the number of parameters.

@Bri_G Point taken on the reference. Tagging @Simeon on this.

With regard to your code, I recommand that you replace:

``````    dx = xin - xpos[sn]
dy = yin - ypos[sn]
angle = math.atan2(dy, dx)
xpos[sn] = xin - math.cos(angle) * segLength
ypos[sn] = yin - math.sin(angle) * segLength
``````

with

``````    dir = vec2(xin - xpos[sn], yin - ypos[sn])
dir = dir:normalize() * segLength
xpos[sn] = xin - dir.x
ypos[sn] = yin - dir.y
``````

Calculating the inverse tangent is expensive, computationally speaking, and if you’re only going to take its cosine and sine afterwards then there’s no need. Normalising a vector is much cheaper.

@dave1707 @LoopSpace - my code above tries to imitate Follow3.html - I have a number of parameters set up to view a few of the variables involved some seem to change rapidly whilst others don’t appear to change suggesting I haven’t got the correct logic. Also each segment is either overwriting the previous one or is not drawn at all and the vertical y properties seem to be ignored with the exception of the touch position.

The answer is probably very simple and obvious - but at the moment I can not see it.

@dave1707 - would you expect that?

OK, I’ll post my code - it’s trying to duplicate an example which I think is Javascript as it runs in a `PC window. My Codea post is below and the link to the demo is below it. I was hoping to use this to enable drawing of random strings on the screen - like scribbling across the screen, so I was interested in the curve and linking code to see if I could reproduce and modify to my needs:

``````
displayMode(FULLSCREEN)
function setup()
--
parameter.watch("xpos")
parameter.watch("ypos")
parameter.watch("xpos")
parameter.watch("ypos")
parameter.watch("angle")
xpos = {} -- 20
ypos = {} -- 20
for loop = 1, 20, 1 do
xpos[loop] = 0
ypos[loop] = 0
end
segLength = 32
angle = 0
xin, yin = 0,0
skip = false
end

function draw()
background(0)
dragSegment(1,xin,yin)
if not skip then
for i = 1, #xpos-1, 1 do
dragSegment(i, xpos[i], ypos[i])
end
end
end

function touched(t)
--
if t.state == BEGAN then
xin,yin = t.x, t.y
skip = true
elseif t.state == MOVING then
xin,yin = t.x, t.y
skip = true
elseif t.state == ENDED then
xin,yin = 0,0
skip = true
end
end

function dragSegment(sn, xin, yin)
--
dx = xin - xpos[sn]
dy = yin - ypos[sn]
angle = math.atan2(dy, dx)
xpos[sn] = xin - math.cos(angle) * segLength
ypos[sn] = yin - math.sin(angle) * segLength
segment(xpos[sn], ypos[sn], angle)
end

function segment( x,  y,  a)
--
pushMatrix()
strokeWidth(9)
stroke(140, 143, 160, 100)
translate(x, y)
rotate(a)
line(0, 0, segLength, 0)
popMatrix()
end

``````

and here is the link -

follow3

@dave1707 In lua5.3 it seems that they’ve made a very sensible decision regarding `math.atan` and `math.atan2`:

math.atan (y [, x])

Returns the arc tangent of y/x (in radians), but uses the signs of both arguments to find the quadrant of the result. (It also handles correctly the case of x being zero.)

The default value for x is 1, so that the call math.atan(y) returns the arc tangent of y.

I’m presuming that @Simeon has made `math.atan2` an alias of `math.atan` for backwards compatibility.

So `math.atan()` with a single argument computes the inverse tangent of its argument, while `math.atan()` with two arguments takes into account the quadrant.

This means that the crucial difference between the two is in the number of arguments that are supplied.

@Bri_G Try this. The simple answer was that angle expects to be in degrees but all the atan2 values are in radians. Multiplying the angle by 180/pi converts radians to degrees.

``````displayMode(FULLSCREEN)

function setup()
x,y={},{}
for z=1,20 do
x[z]=0
y[z]=0
end
segLength = 18
strokeWidth(9);
stroke(255, 100);
tx,ty=0,0
end

function draw()
background(0);
dragSegment(1, tx, ty);
for i=1,#x-1 do
dragSegment(i+1, x[i], y[i]);
end
end

function touched(t)
if t.state==BEGAN or t.state==MOVING then
tx=t.x
ty=t.y
end
end

function dragSegment(i,xin,yin)
dx = xin - x[i]
dy = yin - y[i];
angle = math.atan2(dy, dx)
x[i] = xin - math.cos(angle) * segLength;
y[i] = yin - math.sin(angle) * segLength;
segment(x[i], y[i], angle);
end

function segment(x,y,a)
pushMatrix()
translate(x,y)
rotate(a*180/math.pi)
line(0,0,segLength,0)
popMatrix()
end
``````

@dave1707 - thanks for the correction, interesting how such a subtle change can make or break it. Thought it was down to format initially but struggled to resolve.

Also interesting that code with a terminal ; on lines is accepted?

Thanks again

@Bri_G After I got your example working and I was playing with it, I thought it looked familar. I looked thru my code and found this. I’ll see if I can find when I first posted this. It must have been early in my coding years because I have displayMode inside of setup. I did that in my earlier years of Codea. Now I put it before setup.

``````--snake1

function setup()
displayMode(FULLSCREEN)
tab={}
x=WIDTH/2
y=HEIGHT/2
sx=0
sy=0
length=150
end

function draw()
background(40,40,50)
fill(255,0,0)
text("Drag your finger around the screen",WIDTH/2,HEIGHT-50)
x = x + sx
y = y + sy
if #tab<length then
table.insert(tab,1,vec2(x,y))
else
table.insert(tab,1,vec2(x,y))
table.remove(tab,#tab)
end
for a,b in pairs(tab) do
if a==1 then
ellipse(b.x,b.y,20,20)
else
ellipse(b.x,b.y,10,10)
end
end
end

function getDirection()
dx=CurrentTouch.x-x
dy=CurrentTouch.y-y
h=math.sqrt(dx*dx+dy*dy)
sx=dx/100
sy=dy/100
end

function touched(t)
getDirection()
end
``````