2012-03-08 34 views
32

Tôi muốn có một giải pháp đơn giản để tính toán góc của một đường thẳng (giống như con trỏ của đồng hồ).Cách tính góc từ điểm?

tôi có 2 điểm:

cX, cY - the center of the line. 
eX, eY - the end of the line. 

The result is angle (0 <= a < 360). 

Những chức năng có thể cung cấp giá trị này?

+0

Bạn cần ít nhất ba điểm để tính toán một góc. Bạn là ai thứ 3? Trục x hoặc trục y? – Sirko

+2

Giả sử trục x –

+0

2 dòng được đánh số. – durumdara

Trả lời

72

Bạn muốn arctangent:

dy = ey - cy 
dx = ex - cx 
theta = arctan(dy/dx) 
theta *= 180/pi // rads to degs 

Erm, lưu ý rằng mã Javascript trên là rõ ràng không phải biên dịch. Bạn sẽ phải xem qua tài liệu cho hàm arctangent.

Edit: Sử dụng Math.atan2(y,x) sẽ xử lý tất cả các trường hợp đặc biệt và logic thêm cho bạn:

function angle(cx, cy, ex, ey) { 
    var dy = ey - cy; 
    var dx = ex - cx; 
    var theta = Math.atan2(dy, dx); // range (-PI, PI] 
    theta *= 180/Math.PI; // rads to degs, range (-180, 180] 
    //if (theta < 0) theta = 360 + theta; // range [0, 360) 
    return theta; 
} 
+5

Người đàn ông, tôi yêu lượng giác. – Purag

+5

Lưu ý rằng để tránh chia cho 0, bạn nên kiểm tra nếu 'dx == 0' trước; nếu có, sau đó quay lại 90 độ nếu 'dy> 0' và 270 độ nếu' dy <0'. –

+0

@EtiennePerot: Tôi nhớ một chức năng hữu ích khác và cập nhật câu trả lời của tôi để sử dụng thay thế. –

8

phiên bản Runnable của Christian's answer.

function angle(cx, cy, ex, ey) { 
 
    var dy = ey - cy; 
 
    var dx = ex - cx; 
 
    var theta = Math.atan2(dy, dx); // range (-PI, PI] 
 
    theta *= 180/Math.PI; // rads to degs, range (-180, 180] 
 
    return theta; 
 
} 
 
function angle360(cx, cy, ex, ey) { 
 
    var theta = angle(cx, cy, ex, ey); // range (-180, 180] 
 
    if (theta < 0) theta = 360 + theta; // range [0, 360) 
 
    return theta; 
 
} 
 

 
show("right", 0, 0, 1, 0); 
 
show("top right", 0, 0, 1, 1); 
 
show("top", 0, 0, 0, 1); 
 
show("top left", 0, 0, -1, 1); 
 
show("left", 0, 0, -1, 0); 
 
show("bottom left", 0, 0, -1, -1); 
 
show("bottom", 0, 0, 0, -1); 
 
show("bottom right", 0, 0, 1, -1); 
 

 
// IGNORE BELOW HERE (all presentational stuff)
table { 
 
    border-collapse: collapse; 
 
} 
 
table, th, td { 
 
    border: 1px solid black; 
 
    padding: 2px 4px; 
 
} 
 
tr > td:not(:first-child) { 
 
    text-align: center; 
 
} 
 
tfoot { 
 
    font-style: italic; 
 
}
<table> 
 
    <thead> 
 
    <tr><th>Direction*</th><th>Start</th><th>End</th><th>Angle</th><th>Angle 360</th></tr> 
 
    </thead> 
 
    <tfoot> 
 
    <tr><td colspan="5">* Cartesian coordinate system<br>positive x pointing right, and positive y pointing up.</td> 
 
    </tfoot> 
 
    <tbody id="angles"> 
 
    </tbody> 
 
</table> 
 
<script> 
 
function show(label, cx, cy, ex, ey) { 
 
    var row = "<tr>"; 
 
    row += "<td>" + label + "</td>"; 
 
    row += "<td>" + [cx, cy] + "</td>"; 
 
    row += "<td>" + [ex, ey] + "</td>"; 
 
    row += "<td>" + angle(cx, cy, ex, ey) + "</td>"; 
 
    row += "<td>" + angle360(cx, cy, ex, ey) + "</td>"; 
 
    row += "</tr>"; 
 
    document.getElementById("angles").innerHTML += row; 
 
} 
 
</script>

0

Một trong những vấn đề với việc góc giữa hai điểm hoặc bất kỳ góc độ là tài liệu tham khảo bạn sử dụng.

Trong toán học, chúng tôi sử dụng một vòng tròn lượng giác có nguồn gốc ở bên phải của vòng tròn (một điểm trong x = bán kính, y = 0) và đếm ngược chiều kim đồng hồ từ 0 đến 2PI.

Ở vị trí địa lý, nguồn gốc là miền Bắc ở 0 độ và chúng tôi đi theo chiều kim đồng hồ từ 360 độ.

Đoạn code dưới đây (trong C#) được góc trong radian sau đó chuyển thành một góc độ địa lý:

public double GetAngle() 
    { 
     var a = Math.Atan2(YEnd - YStart, XEnd - XStart); 
     if (a < 0) a += 2*Math.PI; //angle is now in radians 

     a -= (Math.PI/2); //shift by 90deg 
     //restore value in range 0-2pi instead of -pi/2-3pi/2 
     if (a < 0) a += 2*Math.PI; 
     if (a < 0) a += 2*Math.PI; 
     a = Math.Abs((Math.PI*2) - a); //invert rotation 
     a = a*180/Math.PI; //convert to deg 

     return a; 
    } 
0

Nếu bạn đang sử dụng canvas, bạn sẽ nhận thấy (nếu bạn chưa có) mà canvas sử dụng xoay theo chiều kim đồng hồ (MDN)y trục được lật. Để có được kết quả nhất quán, bạn cần tinh chỉnh hàm angle của mình.

Thỉnh thoảng, tôi cần phải viết chức năng này và mỗi lần tôi cần tra cứu, bởi vì tôi chưa bao giờ đến cuối tính toán.

Trong khi các giải pháp được đề xuất hoạt động, chúng không xem xét hệ thống tọa độ canvas. Kiểm tra các bản demo sau:

Calculate angle from points - JSFiddle

function angle(originX, originY, targetX, targetY) { 
    var dx = originX - targetX; 
    var dy = originY - targetY; 

    // var theta = Math.atan2(dy, dx); // [0, Ⲡ] then [-Ⲡ, 0]; clockwise; 0° = west 
    // theta *= 180/Math.PI;   // [0, 180] then [-180, 0]; clockwise; 0° = west 
    // if (theta < 0) theta += 360;  // [0, 360]; clockwise; 0° = west 

    // var theta = Math.atan2(-dy, dx); // [0, Ⲡ] then [-Ⲡ, 0]; anticlockwise; 0° = west 
    // theta *= 180/Math.PI;   // [0, 180] then [-180, 0]; anticlockwise; 0° = west 
    // if (theta < 0) theta += 360;  // [0, 360]; anticlockwise; 0° = west 

    // var theta = Math.atan2(dy, -dx); // [0, Ⲡ] then [-Ⲡ, 0]; anticlockwise; 0° = east 
    // theta *= 180/Math.PI;   // [0, 180] then [-180, 0]; anticlockwise; 0° = east 
    // if (theta < 0) theta += 360;  // [0, 360]; anticlockwise; 0° = east 

    var theta = Math.atan2(-dy, -dx); // [0, Ⲡ] then [-Ⲡ, 0]; clockwise; 0° = east 
    theta *= 180/Math.PI;   // [0, 180] then [-180, 0]; clockwise; 0° = east 
    if (theta < 0) theta += 360;  // [0, 360]; clockwise; 0° = east 

    return theta; 
} 
Các vấn đề liên quan