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.atan(math.rad(ang)))
print(math.atan2(ang))
print(math.atan2(math.deg(ang)))
print(math.atan2(math.rad(ang)))
end
@Bri_G Or something like this.
function setup()
print(math.tan(math.rad(45)))
print(math.atan2(1)*180/math.pi)
end

math.atan(y/x)
returns the angle from 0 to pi of the line with gradienty/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 isy,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(math.atan(5,5)*180/math.pi)  1st quadrant
print(math.atan(5,5)*180/math.pi)  2nd quadrant
print(math.atan(5,5)*180/math.pi)  3rd quadrant
print(math.atan(5,5)*180/math.pi)  4th quadrant
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[1]")
parameter.watch("ypos[1]")
parameter.watch("xpos[19]")
parameter.watch("ypos[19]")
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, #xpos1, 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 
@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.
(source https://www.lua.org/manual/5.3/manual.html#pdfmath.atan )
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,#x1 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,HEIGHT50)
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.xx
dy=CurrentTouch.yy
h=math.sqrt(dx*dx+dy*dy)
sx=dx/100
sy=dy/100
end
function touched(t)
getDirection()
end