한양과학기술고등학교

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

코헨–서덜랜드 선분 클리핑

코헨–서덜랜드 선분 클리핑

게임이나 지도를 그릴 때, 선분의 일부가 화면(뷰포트) 밖으로 삐져나가는 경우가 많다. 밖으로 나간 부분까지 그리려 하면 낭비이고, 좌표가 너무 크면 오버플로도 난다. 그래서 화면 경계에서 선분을 잘라내(clip) 안쪽 조각만 남긴다. 코헨–서덜랜드 알고리즘은 평면을 경계선 연장으로 9개 영역으로 나누고, 각 끝점에 TBRL 4비트 아웃코드를 매겨 대부분의 선분을 비트 연산만으로 즉시 통과·기각시킨다. 애매한 것만 경계와의 교점을 실제로 계산한다.

끝점을 드래그해 보기

파란 사각형이 클리핑 윈도우(화면). 노란 점 P0·P1을 마우스나 손가락으로 끌어 옮기세요. 각 끝점 옆의 4자리 숫자가 아웃코드입니다. 다음 단계를 눌러 잘리는 과정을 한 단계씩 보세요.

0000
P0 아웃코드 (T B R L)
0000
P1 아웃코드 (T B R L)
0000
AND (기각 판정)
0
반복 횟수
끝점을 옮기거나 다음 단계를 누르세요

9개 영역과 아웃코드 (T B R L)

1001
위+왼쪽
1000
위 (TOP)
1010
위+오른쪽
0001
왼쪽 (LEFT)
0000
화면 안 (INSIDE)
0010
오른쪽 (RIGHT)
0101
아래+왼쪽
0100
아래 (BOTTOM)
0110
아래+오른쪽

각 비트는 "그 방향으로 경계를 벗어났는가"를 뜻한다 — T: y가 위 경계 위, B: 아래 경계 아래, R: 오른쪽 경계 밖, L: 왼쪽 경계 밖. 두 끝점 코드가 둘 다 0000이면 완전히 안쪽 → 그대로 통과. 두 코드를 AND 했을 때 0이 아니면 같은 쪽 바깥이라 선분 전체가 화면 밖 → 기각. 그 외에는 1인 비트가 가리키는 경계와의 교점을 구해 끝점을 당기고, 코드를 다시 계산한다.

핵심 코드

# 윈도우: xmin, ymin, xmax, ymax  (화면 좌표, y는 아래로 증가)
INSIDE, LEFT, RIGHT, BOTTOM, TOP = 0, 1, 2, 4, 8

def outcode(x, y):
    code = INSIDE
    if   x < xmin: code |= LEFT
    elif x > xmax: code |= RIGHT
    if   y < ymin: code |= TOP
    elif y > ymax: code |= BOTTOM
    return code

def cohen_sutherland(x0, y0, x1, y1):
    c0, c1 = outcode(x0, y0), outcode(x1, y1)
    while True:
        if c0 == 0 and c1 == 0: return (x0, y0, x1, y1)   # 둘 다 안 → 통과
        if c0 & c1:                  return None              # 같은 쪽 밖 → 기각

        out = c0 or c1              # 밖에 있는 끝점 하나 고름
        if out & TOP:    x = x0 + (x1-x0)*(ymin-y0)/(y1-y0); y = ymin
        elif out & BOTTOM: x = x0 + (x1-x0)*(ymax-y0)/(y1-y0); y = ymax
        elif out & RIGHT: y = y0 + (y1-y0)*(xmax-x0)/(x1-x0); x = xmax
        else:            y = y0 + (y1-y0)*(xmin-x0)/(x1-x0); x = xmin

        if out == c0: x0, y0, c0 = x, y, outcode(x, y)   # 그 끝점을 교점으로 당김
        else:         x1, y1, c1 = x, y, outcode(x, y)

한 번의 반복은 경계 하나만 처리한다. 대각선으로 두 경계를 걸친 선분은 2~4번 반복하며 점점 화면 안쪽으로 끌려 들어온다. 매 반복마다 아웃코드의 1비트가 최소 하나씩 사라지므로 최대 4번이면 끝난다.

다른 방법과 비교

알고리즘아이디어특징
코헨–서덜랜드 영역 아웃코드로 대부분 즉시 통과/기각, 나머지는 경계마다 교점 계산 이해가 쉽고 화면 안팎이 뚜렷할 때 빠름 · 애매하면 교점을 여러 번 계산
리앙–바스키 (Liang–Barsky) 선분을 P = P0 + t·(P1−P0) 로 두고 네 경계의 t 구간을 좁힘 교점을 한 번에 계산해 더 효율적 · 파라메트릭 수식이 다소 추상적
서덜랜드–호지먼 다각형을 경계마다 순서대로 잘라 나감 선분이 아닌 다각형(면) 클리핑용 · 볼록 윈도우 전제

어디에 쓰일까 · 함정

실전 사용처
  • GPU 래스터화 전 뷰 프러스텀 클리핑(3D는 6개 평면으로 확장)
  • 2D 게임 카메라·미니맵에서 보이는 부분만 그리기
  • 지도(GIS)에서 화면 밖 도로·경계선 잘라내기
  • CAD·벡터 그래픽의 확대/축소 뷰포트
  • <svg>·캔버스의 clip 영역 계산
자주 하는 실수
  • 기각 조건 c0 & c1 ≠ 0 을 c0 | c1 로 착각
  • y축 방향 혼동 — 화면은 y가 아래로 증가, 수학은 위로
  • 수직·수평 선분에서 0으로 나누기 (해당 경계는 검사할 필요 없음)
  • 교점 계산 후 아웃코드 재계산 누락 → 무한 루프
  • 부동소수 오차로 교점이 경계에서 미세하게 벗어남

비트 하나로 "어느 쪽 밖인가"를 답하고, 확실한 것부터 걸러낸다 — 그게 클리핑의 요령이다.