Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I calculate the angle between two points?

I am attempting to create a 2d tile based game in Javascript, and I need to be able to calculate the angle between two points. I am using the atan2 function to find the angle between two points like so:

function getAngleDegrees(fromX, fromY, toX, toY, force360 = true) {
    let deltaX = toX - fromX;
    let deltaY = toY - fromY;
    let radians = Math.atan2(deltaY, deltaX);
    let degrees = (radians * 180) / Math.PI;
    if (force360) {
      while (degrees >= 360) degrees -= 360;
      while (degrees < 0) degrees += 360;
    }
    return degrees;
  }

However, this isn't providing me with the correct result. I have checked the code for logic or math errors and can't find any. No matter what points I input to this function the result will be off by many degrees.

I have created a JS fiddle to visualize the problem:

https://jsfiddle.net/fa6o7wdy/40/

If anyone knows how I can fix my angle function to provide the correct result please help!

Edit:

Here is a picture of the problem:

https://i.sstatic.net/EpLXC.jpg

like image 333
Danby Avatar asked Jan 25 '26 04:01

Danby


1 Answers

Based on the photo sample you provide, for getting the desired angle you want with current Math.atan() function, you want to reverse first and then rotate the angle by 90 degrees couter clockwise

function getAngleDegrees(fromX,fromY,toX,toY,force360 = true) {
  let deltaX = fromX-toX; 
  let deltaY = fromY-toY; // reverse
  let radians = Math.atan2(deltaY, deltaX)
  let degrees = (radians * 180) / Math.PI - 90; // rotate
  if (force360) {
     while (degrees >= 360) degrees -= 360;
     while (degrees < 0) degrees += 360;
  }
  console.log('angle to degree:',{deltaX,deltaY,radians,degrees})
  return degrees;
}

or simply + 90 degrees to this line without changing deltaX and deltaY

let degrees = (radians * 180) / Math.PI + 90; // rotate

Note: I haven't test out all possible edge cases

const inBlk = document.createElement('i')
  ,   getXY = (p,xy) => Number(p.split('-')[xy==='x'?0:1])
  ;   
for(let i=0;i<100;i++)  // build Grid
  {
  let nI = inBlk.cloneNode()
    , u1 = i%10
    ;
  nI.textContent = u1+'-'+(i-u1)/10
  grid.appendChild(nI)
  }
let points = [ {x:0, y:0, old:null}, {x:0, y:0, old:null}]
  , pN     = 0
  ;
grid.onclick=e=>
  {
  if (!e.target.matches('i')) return

  let elm = e.target.textContent
  points[pN].x = getXY(elm, 'x')
  points[pN].y = getXY(elm, 'y')

  if (points[pN].old ) points[pN].old.classList.remove('color_0', 'color_1')

  points[pN].old = e.target
  points[pN].old.classList.add(`color_${pN}` )

  pN = ++pN %2
  if (pN==0) angle.textContent = ` angle: ${getAngleDegrees(points[0],points[1])}°`
  }

function getAngleDegrees( from, to, force360 =true)
  {
  let deltaX  = from.x - to.x 
    , deltaY  = from.y - to.y                  // reverse
    , radians = Math.atan2(deltaY, deltaX)
    , degrees = (radians * 180) / Math.PI - 90  // rotate
    ;
  if (force360)
    {
    while (degrees >= 360) degrees -= 360;
    while (degrees < 0)    degrees += 360;
    }
  return degrees.toFixed(2)
  }
:root { --sz-hw: 26px; }
#grid { 
  font-family: 'Courier New', Courier, monospace;
  font-size  : 10px;
  margin     : calc( var(--sz-hw) /2);
  }    
#grid i {
  display    : block;
  float      : left;
  width      : var(--sz-hw);
  height     : var(--sz-hw);
  border     : 1px solid grey;
  text-align : center;
  margin     : 2px;
  line-height: var(--sz-hw);
  cursor     : pointer;
  }
#grid i:nth-child(10n-9) {clear: both;   }
.color_0 { background-color: lightcoral; }
.color_1 { background-color: lightgreen; }
#angle   { padding: calc( var(--sz-hw) /2) 0 0 calc( var(--sz-hw) *13.4); }
<p id="grid"></p>

<h4 id="angle">angle: ?</h4>
like image 59
Yunhai Avatar answered Jan 27 '26 19:01

Yunhai



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!