user5183133
user5183133

Reputation:

Need help understanding direction formula

Math.round((((Math.atan2(y, x) * (180 / Math.PI)) + 180) / 90) + 3) % 4;

Hello,

This formula is supposed to take coordinates in an x y plane and return an integer from 0-3 that describes the location of the coordinates.

0:top, 1:right, 2:bottom, 3:left.

I understand that math.atan2 gets the angle and then the 180/pi converts it to degrees. The author said that he added 180 to get rid of negative numbers, but I don't see why there would be any negative numbers. Then he adds 3 and uses the modulo operator 4 (because 4 quadrants).

Does anyone understand why he adds 180 and then 3? What's even more confusing is that If I plugin an angle like pi/2 (which should return 0:top) I get 2.

Upvotes: 2

Views: 226

Answers (2)

trincot
trincot

Reputation: 350202

Indeed, an arctangent can return a negative angle. As mentioned in the MDN docs on atan2:

returns a numeric value between -π and π

For instance, for point (-1, -1), atan(y, x) returns -(3/4)π = -135°

console.log(Math.atan2(-1, -1));

So by adding 180, the formula will translate the range [-180, +180] to [0, 360].

The next step in the formula is to divide by 90, and round that result. So now the above range is reduced to values {0, 1, 2, 3, 4}. But since we added 180° those numbers are shifted:

Original angle range | After adding 180 | After dividing
---------------------+------------------+---------------
   -180...-135       |    0... 45       |      0
   -135... -45       |   45...135       |      1
    -45...  45       |  135...225       |      2
     45... 135       |  225...315       |      3
    135... 180       |  315...360       |      4

Three things remain to be done at this stage:

  • Values outside the range {0, 1, 2, 3} (like the 4) need to be mapped inside of it. This is what the modulo operator does (%)
  • The numbering needs to shift, as you want the top side to get number 0 (After the division by 90, the top side angles get number 3).
  • The numbering direction needs to be opposite, as you want right to be numbered 1, while currently the numbering is anti-clockwise.

You can achieve this by subtracting the intermediate result from 7 (instead of adding 3 to it) and then take the modulo:

Original angle range | After adding 180 | After dividing | Subtract from 7 | Modulo 4
---------------------+------------------+----------------+-----------------+---------
   -180...-135       |    0... 45       |      0         |     7           |    3
   -135... -45       |   45...135       |      1         |     6           |    2
    -45...  45       |  135...225       |      2         |     5           |    1
     45... 135       |  225...315       |      3         |     4           |    0
    135... 180       |  315...360       |      4         |     3           |    3

Expression to use in JavaScript:

(7 - Math.round(((Math.atan2(y, x) * (180 / Math.PI)) + 180) / 90)) % 4

Other numberings

There are in fact 8 ways to number sections consecutively from 0 to 3: there are 4 ways to choose which section will be 0, and 2 directions: clockwise or anti-clockwise.

Here are the modifications to bring at the start of the formula for each of those 8 possibilities:

(7 -  ...
(6 -  ...
(5 -  ...
(4 -  ...
(0 +  ...
(1 +  ...
(2 +  ...
(3 +  ...

Just pick the one that gives the desired results.

Upvotes: 0

MBo
MBo

Reputation: 80187

This formula is intended for coordinate system MM_TEXT, where zero angle is right direction and Pi/2 angle is down direction.

Step-by-step:

* (180 / Math.PI) translates angle range to -180..180 degrees
+ 180 translates angle range to 0..360 degrees, so right direction (old zero) becomes 180
/ 90 makes 0..4 range, so right direction (old zero) becomes 2
+ 3 shifts range to 3..7, so right direction (old zero) becomes 5
% 4 gets modulus, so right direction (old zero) becomes 1

Upvotes: 1

Related Questions