get_ procs

by Bravo1
A helpful set of procs for angular and positional data!
The code's pretty much the same, yours is more compact though. I'm crap with formatting.
It's probably because BYOND uses a truncated version of Pi.

Magnun2k's is pretty much the same, but highers factors of Pi.

His is more accurate, but a bit slower as a result.

Or at least that's what it seems to be.

I'm gonna be updating the library soon to include get_angle_nums() which is the same as get_angle() but you can use four numeric values instead of atoms, in case you prefer that.

Ultimately I'll cut the proc down to be universal and take any kind of entry. Ex: (num,num,atom)/(atom,num,num)/(atom,atom)/(num,num,num,num)

But I'm lazy so that'll come later XD
Actually, I made a mistake. Forget the 180 / PI since Lummox's atan2() returns an angle in degrees.
Do they return the same results?
Also I think mine would be a bit faster without the call for round() and the checks to make sure the returned angle is between 0 and 360.

I figured I'd include that stuff for the sake or convenience.
Weird.

Smiley face
Give a few examples of what they return. It could be the same angle but in a different format..

Ex: 345 degrees = -15 degrees
Another re-vamped version.
proc

// Credit to Lummox JR for the atan2()
fatan2(x, y)
if(!x && !y)
return 0
. = arccos(x / sqrt(x * x + y * y))
return y >= 0 ? . : -.

fget_angle(atom/a, atom/b)
return fatan2(b.y - a.y, b.x - a.x)


Smiley face
Ok, I got some more implementations, and all of them are returning the same values (I prefer North to be 0, South to be 180, East to be 90, and West to be 270).

Here's code and results:

proc

// Credit to Lummox JR for the atan2()
atan2(x, y)
if(!(x || y))
return 0
. = arccos(x / sqrt(x * x + y * y))
return y >= 0 ? . : -.

more_mem_get_angle(atom/a, atom/b)
var/dx = b.x - a.x
var/dy = b.y - a.y
var/val = sqrt(dx * dx + dy * dy)
if(!val) return 0
var/ar = arccos(dx / val)
var/deg = round(360 - (dy >= 0 ? ar : -ar), 1)
deg -= 270
while(deg > 360) deg -= 360
while(deg < 0) deg += 360
return deg

get_angle(atom/a, atom/b)
var/val = sqrt((b.x - a.x) * (b.x - a.x) + (b.y - a.y) * (b.y - a.y))
if(!val) return 0
var/ar = arccos((b.x - a.x) / val)
var/deg = round(360 - (b.y - a.y >= 0 ? ar : -ar), 1)
deg -= 270
while(deg > 360) deg -= 360
while(deg < 0) deg += 360
return deg

other_get_angle(atom/a, atom/b)
var/res = atan2(b.y - a.y, b.x - a.x)
while(res > 360) res -= 360
while(res < 0) res += 360
return res

mob
verb/test()
for(var/n = 1 to 10)
for(var/nn = 1 to 1000)
var/obj/a = new(locate(rand(1,64), rand(1, 64), 1))
var/obj/b = new(locate(rand(1,64), rand(1, 64), 1))
world << "get_angle returns [get_angle(a, b)]"
world << "other_get_angle returns [other_get_angle(a, b)]"
world << "more_mem_get_angle returns [more_mem_get_angle(a, b)]"


Ok, I got some more implementations, and all of them are returning the same values (I prefer North to be 0, South to be 180, East to be 90, and West to be 270).

Unfortunately BYOND and trigonometry doesn't like that. You'll be making a -270 adjustment to every input.

*shrugs* If that's how you prefer it though...
In response to Bravo1
Bravo1 wrote:
Ok, I got some more implementations, and all of them are returning the same values (I prefer North to be 0, South to be 180, East to be 90, and West to be 270).

Unfortunately BYOND and trigonometry doesn't like that. You'll be making a -270 adjustment to every input.

*shrugs* If that's how you prefer it though...

Yeah, which isn't a big deal.
You can also optimize Lummox's algorithm a bit further. I did some testing and the snippet below is a bit faster, though the speed increase is negligible.

proc

// Original atan2() by Lummox R
atan2(x, y)
if(!x && !y)
return 0
. = arccos(x / sqrt(x * x + y * y))
return y >= 0 ? . : -.

// Modified atan2() by Magnum2k
atan3(x, y)
if(isnull(x || y))
return 0
return y >= 0 ? arccos(x / sqrt(x * x + y * y)) : \
-arccos(x / sqrt(x * x + y * y))


Result:


EDIT: Lummox JR's atan2() seems to get more exhausted as more calls are made to it.
It doesn't look like atan3 is getting called in that profile. o_o
It is. I forgot to change the name in the snippet. Haha.
so atan3 would be f_atan2?
Page: 1 2