Sắp xếp mảng các điểm theo thứ tự chiều kim đồng hồ


16

Có một thuật toán như vậy để sắp xếp một mảng các điểm 2D theo thứ tự chiều kim đồng hồ không?
Tôi đặc biệt xử lý tam giác vuông trong trường hợp của tôi để chỉ có 3 điểm.

Tuy nhiên, tôi muốn biết liệu thuật toán đó có tồn tại không, nếu không thì cách đơn giản để trả về 3 điểm của tam giác theo thứ tự theo chiều kim đồng hồ là gì?

Chỉnh sửa: Tôi đang cố gắng tính các điểm theo chiều kim đồng hồ so với tâm của đa giác, đó là lồi.

Cập nhật: Đây là triển khai tôi đã kết thúc bằng cách sử dụng dựa trên câu trả lời đã chọn, nó không phải là hiệu suất quan trọng và chỉ xảy ra một lần trong một thời gian để nó hoạt động.

ArrayList<PVector> pointList = new ArrayList<PVector>();
pointList.add(A);
pointList.add(B);
pointList.add(C);
Collections.sort( pointList, new TriangleVectorComparator(origin) );

return pointList;

// Comparator
package triangleeditor;

import java.util.Comparator;

import processing.core.PVector;

public class TriangleVectorComparator implements Comparator<PVector>  {
    private PVector M; 
    public TriangleVectorComparator(PVector origin) {
        M = origin;
    }

    public int compare(PVector o1, PVector o2) {
        double angle1 = Math.atan2(o1.y - M.y, o1.x - M.x);
        double angle2 = Math.atan2(o2.y - M.y, o2.x - M.x);

        //For counter-clockwise, just reverse the signs of the return values
        if(angle1 < angle2) return 1;
        else if (angle2 < angle1) return -1;
        return 0;
    }

}

1
trở lại có thể được trả lại angle1 <angle2? 1: angle2> angle1? -1: 0;
ademar111190

2
Nó có thể được thể hiện bằng nhiều cách, nhưng tôi có xu hướng tránh các toán tử ternary lồng nhau đặc biệt là khi đưa ra các ví dụ.
onedayitwillmake

@encedayitwillmake Bạn có thể chuyển mã mà bạn đã sử dụng thành câu trả lời không? Nó không thực sự thuộc về câu hỏi, nhưng nó rất có giá trị với những độc giả tương lai.
Anko

@Anko Tôi nghĩ bạn đúng, nhưng đồng thời tôi nghĩ mọi người sẽ dễ dàng tìm thấy nó theo cách này. Nó cũng giúp đảm bảo rằng tôi không lấy đi câu trả lời của samhocevar mà tôi chỉ đơn giản dựa vào.
onedayitwillmake

Câu trả lời:


19

Câu hỏi của bạn không đủ chính xác. Một mảng các điểm chỉ «theo chiều kim đồng hồ» hoặc «ngược chiều kim đồng hồ» so với điểm tham chiếu. Mặt khác, bất kỳ mảng ba điểm nào luôn có thể là CW hoặc CCW. Xem hình sau: bên trái, các điểm được sắp xếp theo chiều kim đồng hồ; ở bên phải, các điểm chính xác giống nhau được sắp xếp ngược chiều kim đồng hồ.

chiều kim đồng hồ hoặc ngược chiều kim đồng hồ

Trong trường hợp của bạn, tôi tin rằng sử dụng barycenter của các điểm làm điểm tham chiếu là hợp lý.

Một phương pháp tốt cho một số điểm chưa biết có thể là một trong những điểm sau:

  • hãy để P[0], P[1], ... P[n-1]danh sách các điểm cần sắp xếp
  • Đặt M là barycenter của tất cả các điểm
  • tính toán a[0], a[1], ... a[n-1]như vậya[i] = atan2(P[i].y - M.y, P[i].x - M.x);
  • sắp xếp các điểm liên quan đến agiá trị của chúng , qsortví dụ sử dụng .

Tuy nhiên, bạn có thể chắc chắn rằng một thuật toán sắp xếp tốt sẽ hoạt động kém với ba giá trị đầu vào so với phương pháp đặc biệt. Sử dụng atan2vẫn còn hiệu lực, nhưng chỉ không sử dụng qsort.


Điều này hoạt động hoàn hảo :)
onedayitwillmake

1
Liệu phương pháp này có một tên?
onedayitwillmake

1
Tôi tin rằng điều này được gọi đơn giản là «sắp xếp theo góc cực». Nó là một thành phần của Graham Scan chẳng hạn.
sam hocevar

Các hit hiệu suất qsortở đây là nhỏ so với atan2.

Cảnh báo nhỏ: Điều này sẽ có khả năng sụp đổ & ghi (tùy thuộc vào ngôn ngữ lập trình và thư viện được sử dụng) nếu bất kỳ điểm nào xảy ra chính xác tại barycentre (hoặc bất kỳ điểm định hướng nào khác bạn sử dụng). Bạn có thể muốn loại trừ các điểm như vậy giữa bước thứ hai và thứ ba.
Martin Sojka

3

Tôi tin rằng những gì bạn thực sự hỏi về đây là thứ tự quanh co của tam giác, điều này thực sự khá đơn giản để kiểm tra.

Vì chỉ có ba điểm trong tam giác của bạn, nên tam giác của bạn đã theo thứ tự theo chiều kim đồng hồ hoặc ngược chiều kim đồng hồ, và vì vậy tất cả những gì bạn cần làm là kiểm tra xem đó là hai điểm nào và đảo ngược thứ tự các chỉ số nếu cuộn dây không phải là người bạn muốn.

Đây là ý tưởng chung, giả sử rằng ba đỉnh của một tam giác là a , bc và bạn có một phép toán trừ vector đơn giản:

Vector2 AToB = b - a;
Vector2 BToC = c - b;
float crossz = AToB.x * BToC.y - AToB.y * BToC.x;
if ( crossz > 0.0f )
{
  // clockwise
}
else
{
  // counter-clockwise.  Need to reverse the order of our vertices.
}

Lưu ý rằng tùy thuộc vào cách bạn định hướng trục + y (lên hoặc xuống), các trường hợp "theo chiều kim đồng hồ" và "ngược chiều kim đồng hồ" có thể được đảo ngược so với cách tôi đã gắn nhãn chúng trong các nhận xét trong mã mẫu này.


Tôi cần chuyển các điểm này cho Box2D (triển khai java) để tạo đa giác. mặc dù đó không phải là những gì tôi đã hỏi, cái nhìn sâu sắc rất tốt :)
onedayitwillmake

2

Bạn có thể cho biết thêm thông tin? Bạn muốn thứ tự điểm CCW, nhưng điểm nào nên là trung tâm của thứ tự?

Nếu bạn chỉ có tam giác (3 điểm) trong mặt phẳng, bạn có thể tính toán xác định từ ma trận, trong đó các đường là tọa độ của các điểm (tọa độ thứ 3 là 1). Nếu xác định là> 0, các điểm theo thứ tự CCW. Nếu không, bạn có thể đổi ví dụ hai điểm cuối và bạn sẽ nhận được đơn hàng CCW.

Nếu bạn có các điểm A, B, C, thì ma trận của bạn sẽ giống như:

|xA, yA, 1|
|xB, yB, 1|
|xC, yC, 1|

Xác định là: xA * yB + xB * yC + xC * yA - yB * xC - yC * xA - yA * xB. Sau đó, bạn có thể so sánh nó với số không. Nếu nó> 0, trả về điểm A, B, C, nếu không, trả về A, C, B.

Nếu bạn đã tập hợp các điểm và biết, chúng tạo ra đa giác lồi (tất cả đều là một phần của thân lồi) và muốn nhận được thứ tự của chúng, bạn có thể sử dụng Graham Scan hoặc Jarvis's March (đây là những thuật toán để tìm vỏ lồi từ nhiều điểm, nhưng nó cũng nên hoạt động ở đây :))


để hoàn thành những gì zacharmarz đã nói nếu bạn chỉ muốn sắp xếp các điểm của mình theo thứ tự theo chiều kim đồng hồ xung quanh một điểm cụ thể, bạn có thể tạo một mảng từ các cặp số float và điểm trong đó bạn lưu trữ tất cả các điểm với góc cạnh của chúng từ điểm cụ thể đó, sau đó sắp xếp mảng đó.
Ali1S 232
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.