Post

CCW (Counter Clock Wise)

CCW (Counter Clock Wise)

이 글은 제 개인적인 공부를 위해 작성한 글입니다.
틀린 내용이 있을 수 있고, 피드백은 환영합니다.


개요


CCW는 Counter Clock Wise(반시계 방향)의 약자로, 평면 위에 세 점이 주어졌을 때 세 점의 방향성이 어느 쪽인가를 판별하는 알고리즘이다.

2차원 평면에 세 점 p1, p2, p3가 순서대로 주어졌을 때, 이 점들을 이은 경로의 방향은 딱 3가지 경우만 존재한다.

img

  • 반시계 방향 : p1 → p2 → p3로 이동할 때 왼쪽으로 꺾이는 경우
  • 시계 방향 : p1 → p2 → p3로 이동할 때 오른쪽으로 꺾이는 경우
  • 일직선 : 꺽이지 않고 곧게 뻗거나 왔던 길로 되돌아가는 경우


이 세 점이 어느 방향으로 꺾였는지 알 수 있는 방법은 벡터의 외적(Cross Product)이다.

세 점 p1(x1, y1), p2(x2, y2), p3(x3, y3)가 있을 때, p1을 시작점으로 하는 두 개의 벡터를 만들자.

  • u = p1p2 = (x2 - x1, y2 - y1)
  • v = p1p3 = (x3 - x1, y3 - y1)

두 2차원 벡터의 외적 수식은 행렬식으로 계산할 수 있다.

  • u * v = (x2 - x1)(y3 - y1) - (y2 - y1)(x3 - x1)

결과가 양수(> 0)인 경우, 세 점은 반시계 방향으로 꺾여있다.

결과가 음수(< 0)인 경우, 세 점은 시계 방향으로 꺾여있다.

결과가 0인 경우, 세 점은 일직선 상에 놓여있다.


C++ 코드 예시

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>

struct Point
{
    long long x, y;
};

int ccw(Point p1, Point p2, Point p3)
{
    long long result = (p2.x - p1.x) * (p3.y - p1.y) - (p2.y - p1.y) * (p3.x - p1.x);
    
    if (result > 0) return 1;   // 반시계
    if (result < 0) return -1;  // 시계
    return 0;                   // 일직선
}

int main()
{
    Point p1(0, 0), p2(5, 0), p3(5, 5);
    
    std::cout << ccw(p1, p2, p3); // 1
    
    return 0;
}


CCW를 응용한 선분 교차 판정


두 개의 선분 (A,B), (C,D)가 주어질 때, 이 선분들이 서로 교차하는지 판정하는 문제는 CCW 알고리즘을 활용하여 해결할 수 있다. 한 선분을 기준으로 다른 선분의 양 끝점이 서로 다른 방향에 있는지 확인하면 된다.

img

  1. (A,B) 선분을 기준으로 (C,D)의 양 끝점이 서로 다른 방향에 있는지 확인한다. (CCW(A,B,C)와 CCW(A,B,D) 계산)
  2. (C,D) 선분을 기준으로 (A,B)의 양 끝점이 서로 다른 방향에 있는지 확인한다. (CCW(C,D,A)와 CCW(C,D,B) 계산)
  3. 두 선분 모두 점검했을 때, 두 선분 모두 양 끝점이 반대 방향에 있다면 교차하는 것이다.
  4. 한 선분이라도 양 끝점이 한 쪽에 몰려 있다면, 두 선분은 교차하지 않는다.

단, 선분이 일직선 상에 놓여있는 경우(ccw의 결과가 0)에는 추가적인 처리가 필요하다. 이 경우, 두 선분이 겹치는지 확인해야 한다.

img

  1. 두 선분이 서로 겹치지 않음.
  2. 두 선분이 한 점에 닿음.
  3. 두 선분이 겹쳐짐.
  4. 한 선분이 다른 선분 안에 포함됨.

img

선분을 x축위로 투영해서 x 좌표만 비교하자.

  • A > B1 + B2라면, 만나지 않는다.
  • A = B1 + B2라면, 한 점에서 만난다.
  • A < B1 + B2라면, 겹쳐진다.
This post is licensed under CC BY 4.0 by the author.