[英]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/
如果有人知道我如何修復我的角度函數以提供正確的結果,請幫助!
編輯:
這是問題的圖片:
根據您提供的照片樣本,為了使用當前的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 度到這條線而不改變deltaX
和deltaY
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.