Atan2 function

I am trying to calculate the angle of the mouse pointer with respect to the center of the screen and I am having hard time figuring out how to do it.

I have seen that recently atan has been introduced and that is great, but it is still very painful (at least to me) to calculate the angle from the mouse x an y positions.

I have a triangle moving around the screen together with the mouse and would like to have the triangle rotating according to the angle given by momentary x and y of the mouse cursor. The triangle would always point outward from the center of the screen.

This could be achieved either by adding atan2 to the basic expressions, or equipping a field “angle” to the mouse plugin. In this latter case, it might be useful to also have a field to specify the 0 point from which the angle is calculated.

just a suggestion
thanks
ant

Hi Ant,

I can add atan2 to MWorks’ expression parser. In the meantime, you can use the following MWEL expression macro to emulate it:

%define atan2(y, x) atan(y / x) + pi() * (x < 0) * ((y >= 0) - (y < 0))

(I’m pretty sure I got that right, but you should double check my math.)

Cheers,
Chris

Thanks!

This is my solution based on your macro:
I added the conversion to go from radians to degrees and removed the logical checks, which I include later in the code:

%define atan2(y, x) ((atan(y / x) / (pi() / 180))) 

inside the protocol I then call the macro (y is flipped to make the unit circle rotating clockwise, according my my convention).

IO_mouse_theta = atan2(-IO_cursor_y, IO_cursor_x)
if (IO_cursor_x < 0) {
    IO_mouse_theta = IO_mouse_theta + 180 
}
if ((IO_cursor_x >= 0) #AND (IO_cursor_y < 0)) {
IO_mouse_theta = IO_mouse_theta + 360 
}
IO_mouse_theta = (round(IO_mouse_theta) + 90)%360

90, 180, or 360 is added according to x and y signs to have 0 in the upper position in the unit circle and to have a 360 mapping of the circle as opposed to a -/+180.

And it seems to work properly.

I have an additional question related to mwel macros: how would I write the if conditions I have in the code directly in the macro? I am confused a bit given that the macros do not behave exactly like a standard function (as far as I understand), so I do not really understand how to return values from the macro.

best
ant

Hi Ant,

I have an additional question related to mwel macros: how would I write the if conditions I have in the code directly in the macro? I am confused a bit given that the macros do not behave exactly like a standard function (as far as I understand), so I do not really understand how to return values from the macro.

If you compute IO_mouse_theta in multiple spots in your protocol, then you can turn the computation in to a statement macro. However, you’re correct that statement macros aren’t functions, and you can’t return values from them.

Expression macros aren’t functions, either, but they do act a bit more like them, in that they produce a value that can be used in other expressions. However, it’s awkward to implement conditional logic, as you need to do things like multiplying by (x < 0) * ((y >= 0) - (y < 0)) in my definition of atan2. That said, I think the following encapsulates your computation as an expression macro:

%define mouse_theta(cursor_x, cursor_y) fmod(atan(-cursor_y / cursor_x) / (pi() / 180) + 180 * (cursor_x < 0) + 360 * (cursor_x >= 0 && cursor_y < 0) + 90, 360)

I definitely recommend testing that before using it in your experiment!

Cheers,
Chris

Hi Ant,

The atan2 function is now in the MWorks nightly build.

Cheers,
Chris

sounds great, thanks!