簡體   English   中英

如何計算兩點之間的角度?

[英]How do I calculate the angle between two points?

我正在嘗試用 Javascript 創建一個基於 2d 瓷磚的游戲,我需要能夠計算兩點之間的角度。 我正在使用 atan2 函數來查找兩點之間的角度,如下所示:

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;
  }

但是,這並沒有為我提供正確的結果。 我檢查了代碼中的邏輯或數學錯誤,但找不到任何錯誤。 無論我向這個函數輸入什么點,結果都會有很大的偏差。

我創建了一個 JS 小提琴來可視化問題:

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

如果有人知道我如何修復我的角度函數以提供正確的結果,請幫助!

編輯:

這是問題的圖片:

https://imgur.com/a/OXDCOux

根據您提供的照片樣本,為了使用當前的Math.atan()函數獲得所需的角度,您需要先reverse然后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;
}

或者簡單地 + 90 度到這條線而不改變deltaXdeltaY

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

注意:我還沒有測試出所有可能的邊緣情況

 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>

您的代碼工作正常,只是您的坐標系有些混亂。

兩點之間的角度與您測量的位置有關。 通過從 P1 中減去 P2,您可以制作相對於起點的角度。 因此, atan2為您提供了相對於 X 軸的順時針角度。

傳統上,X 軸是旋轉的起點,因此水平線的角度為 0:

x = 1;
y = 0;
angle = atan2(y, x) // Equals 0

你已經得到了Y+向下的網格,所以當 Y 變為正值時,你將從 x 軸獲得順時針角度。

x = 0;
y = 1;
angle = atan2(y, x) // Equals PI/2, or 90deg

如果這與 Y+ 下降混淆,您可能需要重新考慮您的網格,以便 Y+ 上升。

PS:祝你游戲順利!

DeltaX toX 和 fromX 需要交換,DeltaY 也是如此。 另外,我已經減去了 90 到角度,以便使 0 度成為北。

% (mod) 運算符與您的 2 x while 循環執行相同的工作。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM