한양과학기술고등학교

에듀테크 프로젝트 대시보드

볼록 껍질 (Convex Hull)

볼록 껍질 (Convex Hull)

평면에 흩뿌려진 점들을 고무줄로 통째로 감싸서 놓으면 나오는 모양. 그 고무줄이 닿는 바깥쪽 점들을 순서대로 이은 것이 볼록 껍질이다. 모든 점을 포함하는 가장 작은 볼록 다각형이며, 내부 각이 전부 180°보다 작다.

어디에 쓰일까? — 두 물체의 충돌 판정(게임 물리), 지도에서 여러 지점을 아우르는 영역 표시, 로봇의 경로/파지 계획, 이미지 속 물체의 외곽선 근사, 데이터의 이상치 경계. "점 집합의 바깥 테두리"가 필요하면 거의 항상 등장한다.

1. 직접 그려 보기 — Andrew 모노톤 체인

캔버스를 클릭해 점을 추가하거나 「무작위」를 누른다. 「한 단계」를 누르면 알고리즘이 점을 하나씩 검사한다. 마지막에 추가된 두 점이 우회전(시계 방향)을 만들면, 가운데 점은 껍질이 될 수 없으므로 스택에서 빼낸다(pop). 왼쪽→오른쪽으로 아래쪽 껍질을 만든 뒤, 오른쪽→왼쪽으로 위쪽 껍질을 만들어 합친다.

일반 점 스택(현재 껍질 후보) 지금 검사 중인 점 확정된 볼록 껍질 방금 버려진 점(우회전)
단계
대기
점 개수 n
0
껍질 꼭짓점 h
0
외적(CCW)
–
캔버스를 클릭해 점을 찍거나 「무작위 12점」을 누르세요.

2. 핵심 도구 — 외적으로 방향 판정 (CCW test)

세 점 O → A → B가 왼쪽으로 꺾이는지(반시계, CCW) 오른쪽으로 꺾이는지(시계, CW)를 알아야 한다. 벡터 OA와 OB의 2D 외적(cross product) 부호가 답이다.

cross = (A.x − O.x)·(B.y − O.y) − (A.y − O.y)·(B.x − O.x)
외적의 절댓값 |cross| 는 세 점이 이루는 평행사변형의 넓이와 같다. 그래서 |cross| / 2 는 삼각형 OAB의 넓이 → 다각형 넓이 계산(신발끈 공식)에도 똑같은 식이 쓰인다. 나눗셈·삼각함수 없이 곱셈과 뺄셈만으로 방향을 판정하는 게 핵심이다.

3. 알고리즘 흐름 (Andrew's Monotone Chain)

  1. 정렬 — 모든 점을 x 좌표 기준(같으면 y)으로 정렬한다. O(n log n), 여기가 전체 비용의 대부분.
  2. 아래쪽 껍질 — 왼쪽 점부터 순서대로 스택에 넣는다. 새 점을 넣기 전, 스택 맨 위 두 점과 새 점이 우회전(≤0)이면 맨 위 점을 pop. 더 이상 우회전이 아닐 때까지 반복 후 push.
  3. 위쪽 껍질 — 오른쪽 점부터 거꾸로 같은 과정을 반복한다.
  4. 합치기 — 두 체인을 이어 붙이면(각 체인의 마지막 점은 중복이라 제외) 반시계 방향 볼록 다각형 완성.

정렬이 끝난 뒤의 스택 처리는 각 점이 많아야 한 번 push, 한 번 pop 되므로 O(n). 총 시간 복잡도는 정렬에 지배되어 O(n log n), 추가 메모리는 O(n).

4. 코드 (Python)

def cross(o, a, b):
    # >0: 좌회전(CCW), <0: 우회전(CW), 0: 일직선
    return (a[0]-o[0])*(b[1]-o[1]) - (a[1]-o[1])*(b[0]-o[0])

def convex_hull(points):
    pts = sorted(set(points))          # x, 그다음 y 로 정렬 + 중복 제거
    if len(pts) <= 2:
        return pts

    lower = []
    for p in pts:
        while len(lower) >= 2 and cross(lower[-2], lower[-1], p) <= 0:
            lower.pop()
        lower.append(p)

    upper = []
    for p in reversed(pts):
        while len(upper) >= 2 and cross(upper[-2], upper[-1], p) <= 0:
            upper.pop()
        upper.append(p)

    return lower[:-1] + upper[:-1]   # 각 체인 끝점은 중복 → 제외

5. 다른 볼록 껍질 알고리즘

알고리즘시간아이디어
선물 포장 (Jarvis March)O(n·h)가장 왼쪽 점부터, 나머지 점 중 "가장 바깥"인 점을 반복해 찾아 감싼다. 껍질이 작으면(h 작음) 빠르다.
그라함 스캔 (Graham Scan)O(n log n)한 기준점에서 본 각도로 정렬 후 스택으로 한 바퀴.
모노톤 체인 (Andrew)O(n log n)x 좌표로 정렬 후 아래·위 껍질을 따로. 각도·삼각함수 불필요, 구현이 깔끔.
퀵헐 (QuickHull)평균 O(n log n)
최악 O(n²)
가장 먼 점으로 삼각형을 만들고 바깥 점들을 재귀 분할. 퀵소트와 닮은꼴.
Chan's AlgorithmO(n log h)선물 포장과 그라함을 결합한 출력 민감 최적.

6. 실제 활용

충돌 감지 (GJK · SAT) — 복잡한 스프라이트를 볼록 껍질로 감싸면 충돌 검사가 훨씬 빨라진다. 물리 엔진의 "콜라이더"가 대부분 볼록 도형인 이유.

지리 정보 (GIS) — 배달 가능 구역, 산불 확산 범위, 특정 종의 서식지 경계를 점 데이터로부터 다각형으로 그린다.

로봇 파지 계획 — 물체의 볼록 껍질 위 꼭짓점이 안정적으로 집을 수 있는 후보 지점이 된다.

데이터 분석 — 산점도에서 한 그룹을 감싸는 최소 볼록 영역(convex hull peeling)으로 이상치를 벗겨 낸다.

다른 기하 문제의 부품 — 지름(가장 먼 두 점), 최소 외접 사각형, 델로네 삼각분할 등이 볼록 껍질을 먼저 구한다.

한 줄 요약 — 점들을 x로 정렬한 뒤, 외적 부호로 "우회전이면 버린다"를 반복하면 O(n log n)에 최소 볼록 다각형이 나온다. 관련: 그래프 탐색, 쿼드트리(공간 분할), 베지에 곡선, 몬테카를로(넓이 추정).