본문으로 건너뛰기
김신건의 로그

Geometry Basic: 벡터, CCW, 외적, 내적

· 수정 · 📖 약 2분 · 762자/단어 #algorithm #geometry #vector #ccw #cross-product
Geometry Basic, 기하 기본, vector, vector operations, dot product, cross product, 내적, 외적, CCW, counterclockwise, orientation test, signed area

정의

기하 알고리즘의 밑바탕. 대부분의 2D/3D 기하 문제는 벡터 연산, 내적/외적, CCW 판정 세 가지의 조합으로 풀립니다.

벡터

2D 벡터: 두 점 사이의 방향/거리 표현.

struct Vec { long long x, y; };

Vec sub(Vec a, Vec b) { return {a.x - b.x, a.y - b.y}; }
Vec add(Vec a, Vec b) { return {a.x + b.x, a.y + b.y}; }

long long dot(Vec a, Vec b)   { return a.x*b.x + a.y*b.y; }
long long cross(Vec a, Vec b) { return a.x*b.y - a.y*b.x; }

TIP

정수 좌표라면 반드시 long long 을 씁니다. 외적은 곱셈 두 개의 뺄셈이라 오버플로 위험이 큽니다.

내적 (Dot Product)

용도:

  • 각도: \cos\theta = \frac\{\vec{a} \cdot \vec{b}\}\{|\vec{a}||\vec{b}|\}
  • 직교 판정: ⟺ 수직
  • 투영: 방향으로 투영한 길이 = \frac\{\vec{a} \cdot \vec{b}\}\{|\vec{b}|\}

외적 (Cross Product), 핵심 도구

2D 에서 외적은 스칼라 (z 성분만):

부호 의미:

의미
반시계 (counterclockwise, CCW) 방향
시계 (clockwise, CW) 방향
두 벡터 평행

절댓값 의미: , 가 이루는 평행사변형의 넓이. 삼각형이면 이의 절반.

CCW (Counterclockwise Test)

세 점 의 방향 관계 판정. 알고리즘 기하의 만능 도구입니다.

int ccw(Vec a, Vec b, Vec c) {
    long long v = cross(sub(b, a), sub(c, a));
    return (v > 0) - (v < 0);  // 1, -1, 0
}

해석:

반환배치
+1A → B → C 가 반시계 (좌회전)
-1A → B → C 가 시계 (우회전)
0세 점이 일직선

응용은 광범위: convex hull, 선분 교차, 다각형 내부 판정, 회전 캘리퍼스 등 거의 모든 기하 알고리즘의 기본 연산.

CCW 시각화

graph LR
    subgraph CCW["CCW = +1 (반시계)"]
        A1[A] --> B1[B]
        B1 --> C1[C]
        C1 -.-> A1
    end
    subgraph CW["CCW = -1 (시계)"]
        A2[A] --> B2[B]
        B2 --> C2[C]
        C2 -.-> A2
    end
    subgraph Colinear["CCW = 0 (일직선)"]
        A3[A] --- B3[B] --- C3[C]
    end

선분 교차

두 선분 가 교차하는지 판정:

bool segments_intersect(Vec a, Vec b, Vec c, Vec d) {
    int d1 = ccw(a, b, c);
    int d2 = ccw(a, b, d);
    int d3 = ccw(c, d, a);
    int d4 = ccw(c, d, b);

    if (d1 != d2 && d3 != d4) return true;  // 일반 교차

    // 특수: 한 선분이 다른 선분의 끝점을 지나는 경우
    if (d1 == 0 && on_segment(a, b, c)) return true;
    if (d2 == 0 && on_segment(a, b, d)) return true;
    if (d3 == 0 && on_segment(c, d, a)) return true;
    if (d4 == 0 && on_segment(c, d, b)) return true;
    return false;
}

bool on_segment(Vec a, Vec b, Vec c) {
    return min(a.x, b.x) <= c.x && c.x <= max(a.x, b.x)
        && min(a.y, b.y) <= c.y && c.y <= max(a.y, b.y);
}

삼각형/다각형 넓이

삼각형 의 넓이:

다각형 (Shoelace formula): 정점 에 대해

다각형 내부 점 판정

Ray casting: 점에서 임의 방향으로 반직선을 그어 다각형 변과 몇 번 교차하는지 세기.

  • 홀수 → 내부
  • 짝수 → 외부

또는 winding number: 모든 변에서 CCW 부호를 세어 총합을 봄. 이쪽이 볼록 다각형에서 더 간단.

함정

  • 정밀도: double 로 외적 계산은 위험. 정수 좌표 → long long 이 원칙.
  • 오버플로: 좌표가 이상이면 곱셈 후 넘을 수 있음. __int128 또는 좌표 축소.
  • 일직선 케이스: CCW=0 일 때 하위 로직 (on-segment 등) 을 반드시 처리해야 함. 잊으면 교차 판정 등이 오동작.
  • 각도 비교: atan2 는 double, 정밀도 문제 있음. 정수 좌표에서 각도 정렬은 사분면 + 외적으로 처리.

참고

이 글의 용어 (3개)
다각형 넓이 (Polygon Area)algorithm
정의 다각형 넓이 (Polygon Area) 는 2D 평면 위 단순다각형 (non-self-intersecting polygon) 의 면적을 신발끈 공식 (Shoelace For…
볼록 껍질 (Convex Hull)algorithm
정의 볼록 껍질 (Convex Hull) 은 주어진 점 집합 P 를 모두 포함하는 최소 크기의 볼록 다각형. 즉 P 의 어떤 점도 다각형 외부에 있지 않고, 다각형의 꼭짓점은 P…
회전 캘리퍼스 (Rotating Calipers)algorithm
정의 회전 캘리퍼스 (Rotating Calipers) 는 볼록 다각형 위에서 서로 마주보는 두 평행선 (겹지름, antipodal pair) 을 회전시키며 다각형의 최장 거리,…

💬 댓글

사이트 검색 / 명령어

검색

스크롤 = 확대/축소 · 드래그 = 이동 · 0 = 원래 크기 · ESC = 닫기