시계 방향으로 포인트 배열 정렬


16

시계 방향으로 2D 포인트 배열을 정렬하는 알고리즘이 있습니까?
나는 특히 3 점 만 올바른 삼각형을 다루고 있습니다.

그러나 그러한 알고리즘이 존재하는지 알고 싶습니다. 내 삼각형의 3 점을 시계 방향으로 반환하는 간단한 방법은 무엇입니까?

편집 : 볼록한 다각형의 중심을 기준으로 시계 방향으로 점을 계산하려고합니다.

업데이트 : 이것은 선택한 답변을 기반으로 사용하여 구현 한 것입니다. 성능이 중요하지 않으며 한 번만 발생하므로 제대로 작동합니다.

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
return은 return angle1 <angle2? 일 수 있습니다. 1 : 각도 2> 각도 1? -1 : 0;
ademar111190

2
여러 가지 방법으로 표현할 수 있지만 특히 예제를 제공 할 때 중첩 삼항 연산자를 피하는 경향이 있습니다.
onedayitwillwill

@onedayitwillmake 사용한 코드를 답변으로 옮길 수 있습니까? 그것은 실제로 질문에 속하지 않지만 미래 독자들에게 매우 가치가 있습니다.
Anko

@Anko 나는 당신이 옳다고 생각하지만, 동시에 사람들이 이런 방식으로 그것을 찾는 것이 가장 쉽다고 생각합니다. 그것은 또한 내가 기반으로 삼고있는 samhocevar의 대답에서 벗어나지 않도록 도와줍니다.
onedayitwillmake가

답변:


19

귀하의 질문은 충분히 정확하지 않습니다. 포인트 배열은 참조 포인트를 기준으로«시계 방향»또는«시계 반대 방향»입니다. 그렇지 않으면 세 점의 배열은 항상 CW 또는 CCW 일 수 있습니다. 다음 그림을 참조하십시오. 왼쪽에서 포인트는 시계 방향으로 정렬됩니다. 오른쪽에는 시계 반대 방향으로 정확히 같은 점이 정렬됩니다.

시계 방향 또는 반 시계 방향

귀하의 경우, 포인트의 중심을 기준점으로 사용하는 것이 합리적이라고 생각합니다.

알려지지 않은 수의 포인트에 대한 좋은 방법은 다음과 같습니다.

  • 하자 P[0], P[1], ... P[n-1]일종의 포인트의 목록이 될
  • M을 모든 지점의 중심으로 두십시오
  • a[0], a[1], ... a[n-1]그런 계산a[i] = atan2(P[i].y - M.y, P[i].x - M.x);
  • 예를 들어 a값을 기준으로 점을 정렬 qsort합니다.

그러나 Ad-hoc 방법에 비해 세 가지 입력 값을 사용하면 올바른 정렬 알고리즘이 제대로 작동하지 않을 수 있습니다. 사용 atan2은 여전히 ​​유효하지만 사용하지 마십시오 qsort.


이것은 완벽하게 작동했습니다 :)
onedayitwillmake

1
이 방법에는 이름이 있습니까?
onedayitwillmake

1
나는 이것이 단순히«극각으로 정렬»이라고 믿습니다. 예를 들어 Graham Scan 의 구성 요소입니다 .
sam hocevar

qsort여기 의 성능 적중은에 비해 작습니다 atan2.

작은 경고 :이 잠재적 충돌 및 포인트 중 하나가 정확히로 발생하는 경우 (사용되는 프로그래밍 언어 및 라이브러리에 따라) 구울 에서 중심 (barycentre) (또는 방향의 어떤 다른 점 사용). 두 번째 단계와 세 번째 단계 사이에서 이러한 점을 제외 할 수 있습니다.
Martin Sojka

3

나는 당신이 실제로 여기에서 요구하는 것은 삼각형의 권선 순서이며, 실제로 테스트하기가 매우 간단하다고 생각합니다.

삼각형에는 세 개의 점만 있기 때문에 삼각형은 이미 시계 방향 또는 시계 반대 방향으로되어 있으므로 둘 중 어느 것을 확인하고 구부러지면 인덱스 순서를 바꾸면됩니다. 당신이 원하는 것이 아닙니다.

다음은 삼각형의 세 꼭짓점이 a , bc 이고 간단한 벡터 빼기 연산이 있다고 가정하는 일반적인 아이디어입니다 .

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.
}

+ y 축 방향 (위 또는 아래)의 방향에 따라 "샘플 방향"및 "시계 반대 방향"의 경우가이 샘플 코드의 주석에서 레이블이 지정된 방식과 반대 일 수 있습니다.


다각형을 만들려면이 점을 Box2D (Java 구현)에 전달해야합니다. 그것이 내가 요구 한 것이 아니지만, 아주 좋은 통찰력 :)
onedayitwillmake

2

더 많은 정보를 줄 수 있습니까? CCW 포인트 순서를 원하지만 주문의 중심이되는 포인트는 무엇입니까?

평면에 삼각형 (3 점) 만있는 경우 선이 점의 좌표 (3 번째 좌표는 1) 인 행렬에서 행렬식을 계산할 수 있습니다. 결정자가 0보다 크면 점은 CCW 순서입니다. 그렇지 않은 경우, 예를 들어 마지막 두 포인트를 사용하여 CCW 주문을받을 수 있습니다.

점 A, B, C가 있으면 행렬은 다음과 같습니다.

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

결정 요인은 xA * yB + xB * yC + xC * yA-yB * xC-yC * xA-yA * xB입니다. 그런 다음 0과 비교할 수 있습니다. 0보다 크면 A, B, C 지점을 반환하고, 그렇지 않으면 A, C, B를 반환합니다.

점 세트를 알고 알고 있으면 볼록 다각형 (모두 볼록 껍질의 일부 ​​임)을 만들고 순서를 얻으려면 Graham Scan 또는 Jarvis 's March을 사용할 수 있습니다 (이 점은 많은 점에서 볼록 껍질을 찾는 알고리즘입니다) 그것은 또한 여기에서 작동해야합니다 :))


특정 점을 기준으로 시계 방향으로 점을 정렬하려는 경우 zacharmarz가 말한 것을 완료하려면 부동 소수점과 점 쌍으로 배열을 만들고 해당 점의 코어 응답 각도로 모든 점을 저장 한 다음 정렬하십시오 그 배열.
Ali1S232
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.