Compass Angle/Rotation Angle For Tracking Direction to X,Y Position In Javascript

Alteredorange

Say you have two x,y coordinates: Starting point of: (100, 100) and ending point of (96, 105). So I need to go left and up. I want to have an arrow point the way to the destination, rotated by the css rotate property, so I need the degree heading (from 0 to 360). 0 would mean go straight up, 180 would mean go straight down, 90 would be go right, etc.

Most posts say to get the bearing in degrees by using: (Math.atan2(105 - 100, 96 - 100) * 180) / Math.PI;. But I can't get that to work. With the above coordinates, I get 128.6598... which would be down and to the right. It also gives negative numbers which would throw it off as well. I've tried adding various degrees depending on if it's positive or negative, but haven't gotten anything to work.

Is there a way to get the correct heading (from 0 to 360) for the two points? Thanks!

FZs

I think this isn't the best way to do that, but this should work:

const getVectorAngle = ([x1, y1], [x2, y2]) => {
  const x = x2 - x1
  const y = y2 - y1
  return (((Math.acos(y / Math.sqrt(x * x + y * y)) * (Math.sign(x) || 1)) * 180 / Math.PI) + 360) % 360
}

console.log(getVectorAngle([100, 100], [96, 105])) //321.3401

console.log(getVectorAngle([100, 100], [100, 101])) //0
console.log(getVectorAngle([100, 100], [101, 101])) //45
console.log(getVectorAngle([100, 100], [101, 100])) //90
console.log(getVectorAngle([100, 100], [101,  99])) //135
console.log(getVectorAngle([100, 100], [100,  99])) //180
console.log(getVectorAngle([100, 100], [ 99,  99])) //225
console.log(getVectorAngle([100, 100], [ 99, 100])) //270
console.log(getVectorAngle([100, 100], [ 99, 101])) //315
console.log(getVectorAngle([100, 100], [100, 100])) //NaN, start and end values are the same


Here's how it works:

Visualisation Visalisation made by Geogebra Geometry

r is the displacement vector, which is given, and we're looking for α (alpha), the angle of that vector.

const getVectorAngle = ([x1, y1], [x2, y2]) => {
  const x = x2 - x1
  const y = y2 - y1
  return (
      (
        ( //Getting angle by `y = cos(alpha) * r` -> `alpha = cos^-1(y / r)`
          Math.acos(
            y / 
            Math.sqrt(x * x + y * y) //Pythagorean theorem to get the length of r, `r^2 = x^2 + y^2` -> `r = sqrt(x^2 + y^2)`
          ) //= angle in interval [0°; 180°] (in radians)
          * ( //Detect the direction of angle by changing its sign
            Math.sign(x) //Sign of x, +1 if positive, -1 if negative
            || 1         //Return +1 even if x is 0, to avoid cancelling out 180°
          )
        ) //= angle in interval ]-180°; 180°] (still in radians)
        * 180 / Math.PI //Convert angle from radians to degrees
      ) //= angle in degrees
      + 360 //Add 360° to avoid negative values
    ) //= angle in interval ]180°; 540°]
    % 360 //Modulo by 360° to simplify angles >=360°
  //= angle in degrees in interval [0°; 360°[
}

Edit

Somewhat later, I realized, that it can be made to work with Math.atan2 as well:

const getVectorAngle = ([x1, y1], [x2, y2]) => {
  const x = x2 - x1
  const y = y2 - y1
  return x || y
    ? ((Math.atan2(x, y) * 180 / Math.PI) + 360) % 360
    : NaN
}

console.log(getVectorAngle([100, 100], [96, 105])) //321.3401

console.log(getVectorAngle([100, 100], [100, 101])) //0
console.log(getVectorAngle([100, 100], [101, 101])) //45
console.log(getVectorAngle([100, 100], [101, 100])) //90
console.log(getVectorAngle([100, 100], [101,  99])) //135
console.log(getVectorAngle([100, 100], [100,  99])) //180
console.log(getVectorAngle([100, 100], [ 99,  99])) //225
console.log(getVectorAngle([100, 100], [ 99, 100])) //270
console.log(getVectorAngle([100, 100], [ 99, 101])) //315
console.log(getVectorAngle([100, 100], [100, 100])) //NaN, start and end values are the same

As you may notice, the outer shell of the calculation remained the same. That's because Math.atan2 already returns an angle in radians in the interval ]-180°;180°]; so it's functionally same as first my solution's inner part.

The only change is an additional check for a null vector: Math.atan2 doesn't return NaN in this case.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

Unity angle and position relative to direction

javascript draggable script tracking position

Transforming compass direction output

wind direction on a compass wunderground

Rotating MDRotatingPieChart changes x/y position instead of angle

How to get touch position/direction in javascript?

Calculating Displacement based on the compass direction

How to find direction with flutter compass?

Convert GPS latitude and longitude tracking data to a position x and position y on a football pitch?

Javascript SVG controlling X Y based on path direction

Raycast in angle direction

how to direct an arrow on top of compass to point towards specific direction. for e.g. current position to Saudi Arabia

Get X,Y position of element in Javascript

JavaScript get window X/Y position for scroll

SVG free pixel at position x,y in javascript

Moving a Sprite in the direction of an angle in Pygame

The angle of direction without using GPS

Getting the angle from a direction vector?

Change compass-position in Map

Tracking document position changes

Tracking the mouse position on the QGraphicsItem

How to convert a vector (X,Y) position to a latitude/longitude coordinate? Javascript

Convert x and y to angle in radians

STM32 Gyroscope angle tracking

How to get to an angle choosing the shortest rotation direction

Detect image orientation angle based on text direction

How do we convert a direction vector to an angle?

check if angle is between angles `from` and `to` with clockwise direction

How to add force in up direction at an angle in Unity