Cách 'thích hợp' để có được các vectơ đơn vị là gì?


7

Tôi xin lỗi nếu tôi hiểu nhầm thuật ngữ 'vectơ đơn vị' hoặc áp dụng sai nó trong khái niệm, nhưng tôi nghĩ đó là thuật ngữ cho tiêu đề của một đối tượng khi được biểu thị là [x, y]khi xylà một giá trị giữa -1 và 1; vì vậy nếu một vật thể di chuyển 'nam' trên màn hình máy tính, nó sẽ có một vectơ đơn vị là

[0, 1]

...đúng?

Dù sao, tôi đã sử dụng khái niệm này để di chuyển các đối tượng của mình và xoay hình ảnh của chúng (khi cần), nhưng tôi nghĩ toán học mà tôi đang sử dụng để xác định vectơ đơn vị là ... tối ưu.

def set_heading(self, goal):
    """Uses a 'goal' (x, y) to set the object's heading.
    Returns list of 0s and 1s for 'straight' headings.
    Diagonal headings are + and/or - math.sqrt(2)/2.
    """
    vals = [a - b for a, b in zip(goal, self.pos)]
    self.heading = [i / abs(i) if i != 0 else 0 for i in vals]
    if 0 not in self.heading:
        self.heading = [i * (sqrt(2)/2) for i in self.heading]

(Nếu bạn không quen với cú pháp tạm thời của Python, dòng thứ hai chứa i / abs(i) if i != 0 else 0cách nói của Python x if Condition else ytrái ngược với Condition? x : else ycú pháp thông thường trong các ngôn ngữ khác. Về cơ bản, tôi chỉ đang cố gắng tránh chia cho số 0!)

Vì vậy, như bạn có thể thấy, phương pháp thực hiện loại 'khóa' đối tượng này thành tám hướng; nếu 0 không có trong tiêu đề, phương thức giả định rằng chúng ta đang di chuyển theo đường chéo và nhân các giá trị đó sqrt(2) / 2để đảm bảo rằng đối tượng không di chuyển nhanh hơn so với khi di chuyển theo đường chéo. Theo cách này, tôi có thể di chuyển đối tượng bằng cách thêm kết quả của vectơ đơn vị nhân với tốc độ của nó vào tọa độ x và y hiện tại của nó.

def move(self):
    """Moves the object by changing self.pos."""
    self.pos = [a + (b * self.speed) for a, b in zip(self.pos, self.heading)]

Tôi không thể không cảm thấy như phương pháp để lấy vectơ đơn vị (nếu đó là cách gọi chính xác) là ngụy biện. Đặc biệt là vì nó bị khóa thành tám hướng - hiện tại nó rất tốt cho dự án nhỏ mà tôi đang làm việc, nhưng tôi không chắc phương pháp phù hợp để có được một vectơ đơn vị chính xác hơn. Phương pháp chính xác để làm như vậy là gì - và nó có hiệu quả hơn hay ít hơn so với sự kỳ lạ mà tôi đã đưa ra một cách độc lập?


Tôi không có thời gian để viết một câu trả lời hoàn chỉnh, nhưng về cơ bản, những gì bạn phải làm là tự trừ đi các vectơ mục tiêu, cung cấp cho bạn vectơ giữa hai điểm đó. Sau đó, bạn bình thường hóa nó (tức là chia cho độ lớn của nó), kết quả là vector đơn vị bạn muốn. Vectơ đơn vị (hay thường là "vectơ chuẩn hóa") không được xác định bằng cách có các giá trị từ 0 đến 1, nhưng bằng cách có độ dài chính xác là 1 đơn vị - rằng cả hai giá trị cuối cùng nằm trong khoảng từ 0 đến 1.
Christian

đúng. xin lỗi, tôi đoán tôi nghĩ rằng sự hiểu biết đã được thể hiện trong kết quả của phương pháp. Một phương thức trả về một đường chéo (chẳng hạn như 'phía đông nam' chẳng hạn) sẽ trả về [.707, .707], được làm tròn cho sự tỉnh táo ở đây vì tôi không gõ ra hơn 15 chữ số của sqrt (2) / 2. Nhưng nó sẽ trả về các tọa độ cách xa [0, 0] có thể được nhân với thuộc tính tốc độ của đối tượng để đặt nó ở vị trí mà nó hướng đến
Dán

Câu trả lời:


12

Một Vector đơn vị có độ dài 1.

Một vectơ đã cho có thể được chuyển đổi thành một vectơ đơn vị bằng cách chia nó cho độ lớn của nó. (Tất nhiên ngoại trừ không thể chuyển đổi vectơ có độ dài bằng 0).

Lưu ý rằng cường độ có thể được tính bằng định lý Pythagore

Ví dụ: nếu một vectơ có các thành phần: ( x, y, z)

magnitude = sqrt( x2+ y2+ z2)

unit vector = ( x / magnitude , y / magnitude, z / magnitude )


Annan đưa ra một điểm thú vị là đối với các vectơ có cường độ lớn hơn math.sqrt(sys.float_info.max)(khoảng 1,3e + 154 trên máy của tôi) thì điều này sẽ thất bại khi sử dụng phao theo cách thông thường. Trong trường hợp này, một cách giải quyết sử dụng lâu dài để giữ các giá trị làm việc và sau đó tìm căn bậc hai bằng tay sẽ có chức năng nhưng tương đối chậm.

def isqrt(n):
    x = n
    y = (x + 1) // 2
    while y < x:
        x = y
        y = (x + n // x) // 2
    return x

def large_magnitude(x, y, z):
    long_magnitude_squared = pow(long(x), 2) + pow(long(y), 2) + pow(long(z), 2)
    return float(isqrt(long_magnitude_squared))

Tín dụng cho việc triển khai Phương pháp này của Newton dành cho user448810 .


à, cái này hay đấy Sau đó không thể tránh khỏi việc theo dõi - tôi sẽ làm việc lý tưởng để đưa cuộc gọi sqrt()ra khỏi logic hoàn toàn (và do đó không còn hoạt động nghiêm ngặt với các vectơ đơn vị) hay đây có phải là cách sử dụng được chấp nhận cho nó hay không
Stick

2
Vì bạn đang làm việc với python, tôi đề nghị - chỉ cần sử dụng sqrt và đừng lo lắng về nó.
amitp

hah, tốt - điều đó cũng tốt, tôi có thể hỏi điều đó có nghĩa là gì không? Tôi mạo hiểm đoán; rằng Python chậm chạp và không có kết quả cuối cùng trong việc cố gắng vượt qua sqrt(). Điều đó là tốt - Tôi không mã hóa để kiếm sống hay bất cứ điều gì: D
Stick

1
@Stick Vì Python là ngôn ngữ được dịch, nên có một số chi phí gần tương đương với số lượng lệnh được thực thi. Python bên trong sử dụng mã máy được tối ưu hóa tốt, vì vậy quá trình tính toán căn bậc hai không phải chịu chi phí này.
aaaaaaaaaaaa

1
@Annan Tôi đã thêm một cách giải quyết sẽ xử lý cường độ lên tới sys.float_info.max(khoảng 1,7e + 308 trên máy của tôi) ngoài ra bạn có thể sẽ muốn sử dụng một vectơ dài dựa trên mọi cách.
Kelly Thomas
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.