2009-09-17 13 views
5

Tôi có một loạt các vectơ thông thường với các bề mặt cửa sổ trong phần mềm tạo mô hình 3D. Dự kiến ​​sẽ XY-Plane, tôi muốn biết trong đó hướng họ đang phải đối mặt, dịch sang 8 la bàn phối (Bắc, Đông Bắc, Đông, Đông Nam, Nam, Nam-Tây, TâyNorth-West).Làm thế nào để "chụp" một véc-tơ (2D) định hướng đến một la bàn (N, NE, E, SE, S, SW, W, NW)?

Các vectơ làm việc như thế này:

  • các trục X đại diện cho Đông-Tây (với Đông là dương tính)
  • trục y đại diện cho Bắc-Nam (với Bắc là dương tính)
  • do đó
    • (0, 1) == Bắc
    • (1, 0) == Đông
    • (0, -1) == Nam
    • (-1,0) == Tây

Cho một vector (x, y) Tôi đang tìm kiếm gần nhất của 8 tọa độ la bàn. Bất kỳ ý tưởng về cách làm điều này một cách thanh lịch?

+0

bất kỳ ý tưởng nào về cách gắn thẻ chính xác? cảm thấy tự do ... –

+1

Không, trong câu trả lời của tôi (1, 0) là về phía đông và nó sẽ chống ngược chiều kim đồng hồ, vì tôi đang làm những điều toán học ở đây. Đây là tỷ lệ cược với việc sử dụng tiêu chuẩn của góc trong điều hướng (0 = phía bắc, theo chiều kim đồng hồ). Bạn có thể điều chỉnh nó bằng cách thêm một offset thích hợp cho +8 và sử dụng a - ở phía trước của atan2. – starblue

+0

Cảm ơn bạn đã chỉ ra rằng starblue, tôi đang bối rối với bản phác thảo của tôi ở đây - câu trả lời của bạn là tại chỗ! –

Trả lời

7

này hoạt động bằng Java, tính toán một giá trị 0 ... 7 trong tám hướng:

import static java.lang.Math.*;  

int compass = (((int) round(atan2(y, x)/(2 * PI/8))) + 8) % 8; 

Các bản đồ kết quả để la bàn như sau:

0 => E 
1 => NE 
2 => N 
3 => NW 
4 => W 
5 => SW 
6 => S 
7 => SE 
6

Tôi có thể chỉ cần thực hiện một cuộc gọi đến atan2() để tìm ra góc tiêu đề ("yaw"), sau đó sử dụng một chuỗi if: s hoặc một số phép toán để "chụp" nó tới bội số của 90 độ.

+0

cảm ơn, có vẻ đầy hứa hẹn, sẽ kiểm tra nó sau bữa trưa! –

4

không cần phải làm một hàm atan.

nếu bạn làm: y/x bạn sẽ nhận được độ dốc của đường kẻ. Đánh giá bằng số bạn nhận được, bạn có thể xác định góc/octant.

cho của x dương (x> 0)

  • (y/x)> 2.4 - => 90 độ (hướng bắc)
  • 2.4> (y/x)> 0,4 ​​- => 45 độ (phía tây bắc)
  • 0,4> (y/x)> -0.4 - => 0 độ (phía tây)
  • -0.4> (y/x)> -2,4 - => -45 độ (tây nam)
  • -2.4> (y/x) - => 90 độ (phía nam)

và một danh sách tương tự cho x tiêu cực của

và cuối cùng là trường hợp ngoại lệ:

  • (x == 0 & & y> 0) - => -90 độ (phía nam)
  • (x == 0 & & y < 0) - => 90 độ (phía nam)

phụ lục: Tôi chỉ báo cáo phương pháp này khi tính toán một atan là không đi (ví dụ trên một hệ thống nhúng))

Tôi phải đào một chút. Đây là một thói quen tối ưu hóa cao mà tôi sử dụng (được sử dụng trong trò chơi di động).

đầu vào: x1, y1 = startpoint của vector x2, y2 = điểm cuối của vector đầu ra (0-7) = 0 = bắc, 1 = tây bắc, 2 = tây, ... vv

int CalcDir(int x1, int y1, int x2, int y2) 
{ 
     int dx = x2 - x1, dy = y2 - y1; 
     int adx = (dx<0)?-dx:dx, ady = (dy<0)?-dy:dy, r; 
     r=(dy>0?4:0)+(dx>0?2:0)+(adx>ady?1:0); 
     r=(int []){2,3,1,0,5,4,6,7}[r]; 
     return r; 
} 

void CalcDirTest(){ 
     int t = CalcDir(0, 0, 10, 1); 
     printf("t = %d",t); 
     t = CalcDir(0, 0, 9, 10); 
     printf("t = %d",t); 
     t = CalcDir(0, 0, -1, 10); 
     printf("t = %d",t); 
     t = CalcDir(0, 0, -10, 9); 
     printf("t = %d",t); 
     t = CalcDir(0, 0, -10, -1); 
     printf("t = %d",t); 
     t = CalcDir(0, 0, -9, -10); 
     printf("t = %d",t); 
     t = CalcDir(0, 0, 1, -10); 
     printf("t = %d",t); 
     t = CalcDir(0, 0, 10, -9); 
     printf("t = %d",t); 
} 

này sẽ dẫn đến kết quả như sau:

t = 7 
t = 6 
t = 5 
t = 4 
t = 3 
t = 2 
t = 1 
t = 0 

(các vectơ cho kỳ thi này có thể nhìn kỳ quặc chọn, nhưng tôi tinh chỉnh tất cả chúng một chút để được rõ ràng trong một chòm sao bát nhân và không trên biên giới chính xác)

+0

Tôi không thấy cách thức tối ưu hóa cuối cùng có thể hoạt động vì giá trị r có thể dễ dàng vượt quá kích thước mảng ẩn danh. – GregM

+0

Cũng được phát hiện. Sửa lỗi – Toad

3

Điều này không sử dụng atan2, và hiện tại 4 so sánh tồi tệ nhất và 2 sản phẩm cho mỗi cuộc gọi. So sánh x với y trong 4 khối bên trong (tôi đã chỉnh sửa nó trong khối đầu tiên), nó có thể được giảm xuống chính xác 4 so sánh và 1 sản phẩm cho mỗi cuộc gọi.

int compass(double x,double y) 
{ 
    double t = 0.392699082; // tan(M_PI/8.0); 

    if (x>=0) 
    { 
    if (y>=0) 
    { 
     if (x>y) { if (y<t*x) return E_COMPASS; } 
     else { if (x<t*y) return N_COMPASS; } 
     return NE_COMPASS; 
    } 
    else 
    { 
     if (-y<t*x) return E_COMPASS; 
     if (x<-t*y) return S_COMPASS; 
     return SE_COMPASS; 
    } 
    } 
    else 
    { 
    if (y>=0) 
    { 
     if (y<-t*x) return W_COMPASS; 
     if (-x<t*y) return N_COMPASS; 
     return NW_COMPASS; 
    } 
    else 
    { 
     if (-y<-t*x) return W_COMPASS; 
     if (-x<-t*y) return S_COMPASS; 
     return SW_COMPASS; 
    } 
    } 
    return E_COMPASS; 
}