2010-04-03 26 views
12

Giả sử tôi có hai vectơ 2D, một cho một vị trí hiện tại của đối tượng và một cho các đối tượng đó trước đó. Làm thế nào tôi có thể làm việc ra hướng góc của du lịch?Tính góc hướng từ hai vectơ?

Hình ảnh này có thể giúp hiểu được những gì tôi sau:

(image) http://files.me.com/james.ingham/crcvmy

+0

Bạn có thể giải thích thêm một chút không? Đây có phải là không gian 2D hoặc 3D, bạn có thể đưa ra một ví dụ về mã và ma trận của bạn trông như thế nào không? Các ma trận này có lưu trữ dữ liệu luân phiên (có lẽ nó phải là một quaternion sau đó) hay là chúng mô tả các phép biến đổi? –

+0

http://en.wikipedia.org/wiki/Slope_formula? – Ross

+0

Cảm ơn ross, tôi hiện đang cố gắng đưa câu trả lời vào thực tế. Sẽ cho bạn biết làm thế nào tôi nhận được trong một giây ... –

Trả lời

10

Các vector hướng đi sẽ là sự khác biệt của hai vectơ vị trí,

d = (x1, y1) - (x, y) = (x1 - x, y1 - y) 

Bây giờ khi bạn yêu cầu góc hướng, điều đó phụ thuộc những gì hướng bạn muốn đo góc chống lại. Là nó chống lại trục x? Đi với câu trả lời của Radu. Đối với một vector tùy ý? Xem câu trả lời của justjeff.

Edit: Để có được góc so với trục y:

tan (theta) = (x1 -x)/(y1 - y)   

tang của góc là tỷ số của tọa độ x của vector khác biệt cho y phối hợp của vector khác biệt.

Vì vậy

theta = arctan[(x1 - x)/(y1 - y)] 

đâu arctan nghĩa nghịch đảo tang. Không được nhầm lẫn với nghịch đảo của tang, mà nhiều người làm, vì chúng thường được biểu thị là tan^-1. Và chắc chắn rằng bạn biết liệu bạn đang làm việc ở độ hoặc radian.

+0

Thực ra nó chống lại trục Y Tôi đang tìm kiếm –

+0

@ james.ingham: hy vọng rằng sẽ giúp. –

+0

Cảm ơn Đó là arctan tôi đã tìm kiếm! :) –

2

Vẫn không chắc chắn những gì bạn có nghĩa là bởi ma trận xoay vòng, nhưng đây là một trường hợp đơn giản của nhận được một góc phương vị từ một vector hướng.

Câu trả lời phức tạp:

Thông thường bạn nên đóng gói một vài chức năng chuyển đổi/tiện ích với vectơ 2D của bạn: một để chuyển đổi từ X, Y (carthesian) để Theta, R (tọa độ cực). Bạn cũng nên hỗ trợ các hoạt động vector cơ bản như bổ sung, chất nền và sản phẩm chấm. câu trả lời của bạn trong trường hợp này sẽ là:

double azimuth = (P2 - P1).ToPolarCoordinate().Azimuth; 

đâu ToPolarCoordinate() và ToCarhtesianCoordinate() là hai chức năng đối ứng chuyển từ một loại véc tơ khác.

Các đơn giản:

double azimuth = acos ((x2-x1)/sqrt((x2-x1) * (x2-x1) + (y2-y1) * (y2-y1)); 
//then do a quadrant resolution based on the +/- sign of (y2-y1) and (x2-x1) 
if (x2-x1)>0 { 
    if (y2-y1)<0 { azimuth = Pi-azimuth; } //quadrant 2 
} else 
{ if (y2-y1)> 0 { azimuth = 2*Pi-azimuth;} //quadrant 4 
    else { azimuth = Pi + azimuth;} //quadrant 3 
} 
+0

Xin lỗi, tôi đã cập nhật câu hỏi nhưng không phải là tiêu đề liên quan đến ma trận ... –

9

Nếu bạn đang ở C (hoặc ngôn ngữ khác sử dụng cùng một bộ chức năng) thì có thể bạn đang tìm kiếm hàm atan2(). Từ sơ đồ của bạn:

double theta = atan2(x1-x, y1-y); 

góc Đó sẽ là từ trục dọc, như bạn đánh dấu, và sẽ được đo bằng radian (đơn vị góc riêng của Thiên Chúa).

5

Hãy cẩn thận sử dụng atan2 để tránh các vấn đề về góc phần tư và chia cho số không. Đó là những gì nó có cho.

float getAngle(CGPoint ptA, CGPoint ptOrigin, CGPoint ptB) 
{ 
    CGPoint A = makeVec(ptOrigin, ptA); 
    CGPoint B = makeVec(ptOrigin, ptB); 

    // angle with +ve x-axis, in the range (−π, π] 
    float thetaA = atan2(A.x, A.y); 
    float thetaB = atan2(B.x, B.y); 

    float thetaAB = thetaB - thetaA; 

    // get in range (−π, π] 
    while (thetaAB <= - M_PI) 
     thetaAB += 2 * M_PI; 

    while (thetaAB > M_PI) 
     thetaAB -= 2 * M_PI; 

    return thetaAB; 
} 

Tuy nhiên, nếu bạn không quan tâm đến dù đó là một ve hoặc góc-ve, chỉ cần sử dụng quy tắc chấm sản phẩm (ít CPU load):

float dotProduct(CGPoint p1, CGPoint p2) { return p1.x * p2.x + p1.y * p2.y; } 

float getAngle(CGPoint A, CGPoint O, CGPoint B) 
{ 
    CGPoint U = makeVec(O, A); 
    CGPoint V = makeVec(O, B); 

    float magU = vecGetMag(U); 
    float magV = vecGetMag(V); 
    float magUmagV = magU * magV; assert (ABS(magUmagV) > 0.00001); 

    // U.V = |U| |V| cos t 
    float cosT = dotProduct(U, V)/magUmagV; 
    float theta = acos(cosT); 
    return theta; 
} 

Lưu ý rằng trong cả hai đang ở trên, nếu một (hoặc cả hai) vectơ ở gần 0 thì điều này sẽ thất bại. Vì vậy, bạn có thể muốn bẫy bằng cách nào đó.

Các vấn đề liên quan