2013-08-01 39 views
7

Tôi cần tính góc giữa 3 điểm. Đối với điều này, tôi làm như sau:Góc sai, mặt sai được tính

  1. Grab 3 điểm (trước đây, hiện tại và tiếp theo, đó là trong một vòng lặp)
  2. Tính khoảng cách giữa các điểm với Pythagoras
  3. Tính góc bằng Math.acos

Điều này có vẻ hoạt động tốt đối với hình dạng không có thiên thần trên 180 độ, tuy nhiên nếu hình dạng có góc như vậy, nó tính toán cạnh ngắn. Dưới đây là một minh họa để hiển thị những gì tôi có nghĩa là (các giá trị màu đỏ là sai):

A scatch illustrating what goes wrong with the calculations

Đây là mã mà không được tính toán:

// Pythagoras for calculating distance between two points (2D) 
pointDistance = function (p1x, p1y, p2x, p2y) { 
    return Math.sqrt((p1x - p2x)*(p1x - p2x) + (p1y - p2y)*(p1y - p2y)); 
}; 

// Get the distance between the previous, current and next points 
// vprev, vcur and vnext are objects that look like this: 
//  { x:float, y:float, z:float } 
lcn = pointDistance(vcur.x, vcur.z, vnext.x, vnext.z); 
lnp = pointDistance(vnext.x, vnext.z, vprev.x, vprev.z); 
lpc = pointDistance(vprev.x, vprev.z, vcur.x, vcur.z); 

// Calculate and print the angle 
Math.acos((lcn*lcn + lpc*lpc - lnp*lnp)/(2*lcn*lpc))*180/Math.PI 

Có điều gì sai trong các mã, đã làm Tôi quên làm một cái gì đó, hoặc nó nên được thực hiện một cách hoàn toàn khác nhau?

+2

Bạn có thể sử dụng [ 'Math.atan2()'] (https://developer.mozilla.org/en-US/docs/Web/ JavaScript/Reference/Global_Objects/Math/atan2) để tính toán góc từ tọa độ, nó sẽ làm cho việc tính toán đơn giản hơn. Bạn có thể thấy một ví dụ làm việc [trong fiddle] này (http://jsfiddle.net/92jWG/6/). – Teemu

+0

Làm thế nào một tam giác có một góc trên 180 độ?Tổng số góc là 180 độ ..... – Jiminion

+1

Vấn đề là 'cos (90)' và 'cos (270)' đều là 0 vì vậy khi thực hiện acos (0) nó sẽ phải chọn cái để cho bạn và rõ ràng chọn 90 làm tùy chọn. Một cách để sửa lỗi này có thể sử dụng atan2 như Teemu gợi ý và tính toán các góc của mỗi đoạn đường và trừ chúng. Tôi nghĩ rằng nếu bạn làm điều đó theo đúng thứ tự, điều này sẽ cung cấp cho bạn thông tin đầy đủ (mặc dù có thể cần bình thường hóa vì nó có thể nằm trong khoảng từ -360 đến 360). – Chris

Trả lời

4

HI có toán và tính toán của bạn là hoàn hảo. Việc bạn chạy vào cùng một vấn đề mà hầu hết mọi người làm trên máy tính, đó là định hướng. Những gì tôi sẽ làm là tìm hiểu xem điểm nằm ở bên trái hoặc bên phải của véc tơ do hai điểm đầu tiên sử dụng mã này, mà tôi tìm thấy từ

Determine which side of a line a point lies

isLeft = function(ax,ay,bx,by,cx,cy){ 
return ((bx - ax)*(cy - ay) - (by - ay)*(cx - ax)) > 0; 
} 

đâu ax và ay làm lên điểm bx đầu tiên của bạn bằng thứ hai và cx cy thứ ba của bạn.

chỉ nếu nó là sang trái thêm 180 đến góc của bạn

+1

Tôi nghĩ bạn có nghĩa là 'angle =! IfLeft (....)? 360 - angle: angle; 'thay vì' angle + 180'. – Broxzier

+0

Tôi đoán vì vậy tôi đã không đi qua câu hỏi đầy đủ nhưng tìm ra nếu nó là trái hoặc phải của dòng là chìa khóa. Tôi hy vọng rằng bit code đã giúp may mắn! – ZJS

0

Bạn cần kiểm tra các điều kiện biên (rõ ràng, nếu các điểm là colinear) và áp dụng phép tính thích hợp để tìm góc. Ngoài ra, một hình tam giác không thể có bất kỳ góc (bên trong) nào lớn hơn 180 degress. Tổng góc của tam giác là 180 độ.

+0

Một khởi đầu tốt có thể là tìm ra khoảng cách dài nhất. – Jiminion

+0

Ranh giới luôn ở bên trái nếu bạn đi bộ từ trước qua dòng hiện tại tới bước tiếp theo, nhưng làm cách nào để sử dụng tính năng này, tôi cần phải tính toán những gì? – Broxzier

+1

@Jim: Tôi không chắc rằng việc tìm kiếm dài nhất có liên quan không? – Chris

1

Tôi đã có một công việc nhưng không nhất thiết phải ngắn gọn ví dụ về cách này có thể làm việc:

var point1x = 0, point1y = 0, 
    point2x = 10, point2y = 10, 
    point3x = 20, point3y = 10, 
    point4x = 10, point4y = 20; 

var slope1 = Math.atan2(point2y-point1y,point2x-point1x)*180/Math.PI; 
var slope2 = Math.atan2(point3y-point2y,point3x-point2x)*180/Math.PI; 
var slope3 = Math.atan2(point4y-point3y,point4x-point3x)*180/Math.PI; 
alert(slope1); 
alert(slope2); 
alert(slope3); 
var Angle1 = slope1-slope2; 
var Angle2 = slope2-slope3; 
alert(180-Angle1); 
alert(180-Angle2); 

(thấy http://jsfiddle.net/ZUESt/1/)

Để giải thích nhiều bước các slopeN biến là các sườn núi của cá nhân các đoạn thẳng. AngleN là số lượng được quay tại mỗi điểm giao nhau (tức là điểm N + 1). Một góc dương là rẽ phải và góc âm sẽ rẽ trái.

Sau đó, bạn có thể trừ góc này từ 180 để có được góc bên trong thực tế mà bạn muốn. Cần lưu ý rằng mã này tất nhiên có thể được nén và năm dòng chỉ đơn thuần là xuất các biến để xem điều gì đang diễn ra. Tôi sẽ cho bạn lo lắng về việc tối ưu hóa nó cho việc sử dụng của riêng bạn với điều này là một bằng chứng về khái niệm.

+0

Và bây giờ tôi tự hỏi nếu sử dụng sản phẩm chấm có thể là cách tốt hơn để làm điều này anyway ... – Chris

+1

Không. Dot sản phẩm có cùng một vấn đề hiệu quả chỉ cho bạn cosin của góc mà sau đó bị cùng một vấn đề như trước. – Chris