Làm thế nào tôi có thể biết liệu một đối tượng đang di chuyển CW hoặc CCW xung quanh một đường dẫn được kết nối?


19

Hãy nói rằng chúng ta có một hình dạng lởm chởm:

hình dạng0

Và hai sinh vật di chuyển dọc theo nó.

Sau đó, chúng tôi làm mịn hình dạng hoàn toàn bằng cách kéo các góc ra.

Chúng tôi nhận được điều này:

trơn tru

Bây giờ dễ dàng nhận thấy rằng Orange đang di chuyển CW và CCW xanh. Làm thế nào tôi có thể biết họ đang di chuyển theo hướng nào mà không làm phẳng hình dạng?

Hình ảnh mới

nhập mô tả hình ảnh ở đây


Đây là 2 xu của tôi: i.imgur.com/zrBdw.png
Kendall Frey

Câu trả lời:


27

Vẽ một đường thẳng đến vô cực và đếm số lần bạn vượt qua hình dạng (chẵn hoặc lẻ), không tính phân đoạn nơi sinh vật nằm. Sau đó kiểm tra xem sinh vật đang đi sang trái hay phải của dòng đó.

thí dụ

Trong ví dụ này, chúng ta vượt qua hình hai lần (chẵn) và chúng ta đi bên trái. Kết quả là ngay lập tức từ bảng này:

   # Crosses | even  | odd
  Direction  |       |
-------------+-------+------
    left     | CCW   |  CW
    right    |  CW   | CCW

Trong mã giả:

x, y = position of creature
vx, vy = direction of creature movement
crossings = 0
for each x1, y1, x2, y2 in shape segments:
    if (x1 < x and x <= x2) or (x2 < x and x <= x1):
        if y - y1 > (x - x1) * (y2 - y1) / (x2 - x1):
            ++crossings
if (crossings & 1) == (vx < 0):
    return CW
else
    return CCW

Bạn có bao gồm các sinh vật dòng di chuyển trên?
Ali1S 232

@Gajoo: không, do đó> thay vì> = ở dòng 6. Tôi sẽ thêm một lưu ý về điều này. Nhưng lưu ý rằng bạn có thể bao gồm dòng và chỉ cần đảo ngược nội dung bảng.
sam hocevar

1
Tôi đã đưa ra giữa việc đưa ra một câu trả lời dựa trên phương pháp này và câu trả lời mà tôi đã đưa ra. Tôi rất vui vì chúng ta có cả hai cách tiếp cận được trình bày ở đây. Đây là một khái niệm đơn giản và rất thanh lịch, nhưng đòi hỏi phải thực hiện các thử nghiệm giao cắt phân khúc dòng, có thể khó khăn để làm cho mạnh mẽ.
Trevor Powell

@TrevorPowell Đúng. Tìm cạnh xa nhất có thể gây nhầm lẫn. Trước tiên, tôi đã kiểm tra dựa trên đỉnh xa nhất của cạnh và sau đó tôi bằng cách vẽ một đường thẳng từ tâm của hình và qua tâm của hai cạnh (hai đường có chung đỉnh) và xem liệu một trong các đường đó có vượt qua một cạnh khác trên đường tới không vô cùng sau khi vượt qua một trong những cạnh này. Nó hoạt động ổn định
sói

5

Nó phụ thuộc vào thông tin bạn có sẵn từ cấu trúc dữ liệu hình dạng của bạn, nhưng một sinh vật di chuyển CW dọc theo đường viền của hình dạng sẽ luôn có bên trong hình bên phải và một sinh vật di chuyển CCW sẽ có bên trong hình dạng nó bên trái


Một giải pháp đơn giản hơn nhiều, và cũng là suy nghĩ đầu tiên của tôi.
Amplify91

Làm thế nào để bạn biết hướng nào là bên trong của hình dạng? Tôi có nghĩa là di chuyển dọc theo một cạnh bên trong hình dạng là bên trái hoặc bên phải của bạn. Làm thế nào để bạn biết nó là cách nào?
Ali1S232

Một giải pháp rất thanh lịch, nhưng nói chung không đúng. Hãy tưởng tượng một chiếc bánh rán, dẹt trên bàn để tạo hình hai chiều. Bạn có thể đi dọc theo cạnh của hình này, giữ bên trong hình bên trái của bạn và tạo một vòng theo chiều kim đồng hồ hoặc ngược chiều kim đồng hồ tùy thuộc vào nơi bạn bắt đầu.
Marcks Thomas

4
  1. Tính điểm trung tâm của hình dạng của bạn.
  2. Chọn cạnh xa nhất của hình dạng của bạn từ trung tâm.
    • (Chọn cạnh xa nhất đảm bảo rằng bạn không bắt đầu từ một phần đảo ngược, lõm của hình dạng, điều này sẽ dẫn đến việc xác định ngược chiều kim đồng hồ / ngược chiều kim đồng hồ cho toàn bộ hình dạng)
  3. Xác định hướng nào dọc theo cạnh đó theo chiều kim đồng hồ
    • (Việc thực hiện đơn giản này sẽ liên quan đến việc so sánh các góc từ tâm của hình với mỗi đầu của cạnh đã chọn. Dấu hiệu của sự khác biệt giữa các góc sẽ cho biết chiều kim đồng hồ của bạn so với ngược chiều kim đồng hồ)
  4. Lặp lại trên tất cả các cạnh của hình, bắt đầu từ cạnh bạn đã chọn trong bước 2, xây dựng một danh sách các cạnh. Đối với mỗi cạnh, lưu hai đỉnh của nó theo thứ tự theo chiều kim đồng hồ.
    • (Nếu hình dạng của bạn không thay đổi theo thời gian, thì bạn có thể lưu trữ danh sách cạnh này để sử dụng sau, vì vậy bạn không phải thực hiện bốn bước đầu tiên cho mỗi khung hình)
    • (bạn có thể đã có một danh sách cạnh. Nếu vậy, bạn có thể lưu thứ tự đỉnh theo chiều kim đồng hồ này trong cùng danh sách đó.)
  5. Để xác định xem một thực thể đang di chuyển theo chiều kim đồng hồ hay ngược chiều kim đồng hồ:
    • Xác định cạnh nào mà thực thể đang di chuyển dọc.
    • Thực hiện một sản phẩm chấm theo hướng chuyển động của thực thể so với vectơ từ bắt đầu theo chiều kim đồng hồ của cạnh đó -> đỉnh kết thúc mà bạn xác định trở lại trong bước 4.
    • Nếu kết quả của sản phẩm chấm là giá trị lớn hơn 0, thực thể đang di chuyển theo chiều kim đồng hồ. Ít hơn 0 có nghĩa là ngược chiều kim đồng hồ.

Câu trả lời rất thông minh
sói

Tôi có một câu hỏi nhỏ? giả sử các đỉnh trong hình dạng của anh ta được đánh số bắt đầu từ điểm CWW bên trái nhất, dựa trên câu trả lời của bạn, làm thế nào tôi có thể biết nếu di chuyển từ 6-> 7 hoặc 9-> 10 (dựa trên số 0) đang di chuyển theo chiều kim đồng hồ?
Ali1S 232

Bạn bắt đầu với cạnh xa nhất và tìm ra đường nào theo chiều kim đồng hồ trên cạnh đó. Giả sử cạnh A theo chiều kim đồng hồ từ đỉnh 'a' đến 'b'. Sau đó, nếu chúng ta di chuyển đến cạnh B (có các đỉnh 'b' và 'c'), chúng ta biết rằng B theo chiều kim đồng hồ từ 'b' đến 'c'. Tương tự, cạnh C sẽ theo chiều kim đồng hồ từ 'c' đến 'd'. Khi chúng ta biết hướng chính xác theo chiều kim đồng hồ từ một cạnh (bước 1-3), bằng cách tiếp tục theo hướng theo chiều kim đồng hồ đó quanh các cạnh của hình dạng, chúng ta có thể suy ra hướng 'theo chiều kim đồng hồ' chính xác cho mọi cạnh, mà không thực sự nhìn vào vị trí của các cạnh của nó, vậy nên sự đồng tình là ok.
Trevor Powell

Làm thế nào bạn có thể biết nếu cạnh A theo chiều kim đồng hồ từ 'a' đến 'b' hoặc nếu nó theo chiều kim đồng hồ từ 'b' đến 'a'? Tôi nghĩ rằng bạn đã bỏ lỡ phần đó.
Ali1S 232

@Gajoo Đó là điểm chính trong bước 3. Có lẽ không nên mang tính cha mẹ, vì đó thực sự là bước quan trọng của toàn bộ quá trình.
Trevor Powell

2

Bạn cần biết đường tròn nào được xác định theo đường đa giác, đường nào các đỉnh đi vòng quanh nó.

Nếu bạn không biết điều này, bạn có thể giải quyết nó bằng cách tính diện tích của đa giác:

float Polygon::area() {
    float result = 0.0f;

    for(int a = 0; a < vertexCount; a ++) {
        int b = (a+1) % vertexCount;
        result += vertices[a].x * vertices[b].y;
        result -= vertices[a].y * vertices[b].x;
    }

    return result * .5f;
}

Các dấu hiệu của kết quả (tích cực hay tiêu cực) sẽ cho bạn biết cho dù đó là chiều kim đồng hồ hoặc ngược lại. Bạn cần thử cách này để xem nó phù hợp với bạn vì nó phụ thuộc vào hệ tọa độ của bạn.

Nếu hình dạng là chiều kim đồng hồ:

  • Một sinh vật đi về phía trước hình dạng đang đi theo chiều kim đồng hồ , và
  • Một sinh vật đi ngược vòng tròn hình dạng đang đi ngược chiều kim đồng hồ .

Nếu hình dạng ngược chiều kim đồng hồ:

  • Một sinh vật đi về phía trước hình dạng đang đi ngược chiều kim đồng hồ , và
  • Một sinh vật đi ngược vòng quanh hình đang đi theo chiều kim đồng hồ .

0

Có vẻ như Trevor đã bao gồm câu hỏi này, nhưng đây là giải pháp của tôi:

  1. tính diện tích bao phủ hình dạng của bạn, có nghĩa là

    area = 0
    foreach (edge in shape)
        area += edge.begin.x * edge.end.y - edge.begin.y * edge.end.x
  2. sử dụng diện tích được tính toán như trên bạn có thể dễ dàng biết được hình dạng có phải theo chiều kim đồng hồ hay không. nó chỉ theo chiều kim đồng hồ nếu diện tích dưới 0.

  3. kiểm tra xem (các) đối tượng có (đang) di chuyển giống như các đỉnh được sắp xếp theo hướng ngược lại hay không.


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.