본문으로 건너뛰기

버그 제보

이상한 점을 알려 주시면 고칠게요. 지금 보고 있는 페이지와 브라우저 정보가 함께 담겨요.

페이지:

Algorithm

벡터 내적·외적과 거리

작성 2026. 10. 30.추가
목차10개 항목
출처와 참고

팔만코딩경(42Seoul 커뮤니티 위키)의 「점과 평면 사이의 거리」, 「Sweeping on plane.」, 「삼각형 내 점이 있는지 구별하는 법」을 바탕으로 재구성한 노트다. 「자주 쓰는 판정」은 Tech Interview Handbook의 「Geometry cheatsheet」를 바탕으로 보강했다.

내적: 같은 방향 성분

n차원 벡터 u = (u₁, …, uₙ), v = (v₁, …, vₙ)의 내적(dot product)은

u · v = u₁v₁ + u₂v₂ + … + uₙvₙ = |u||v|cos θ
내적 값의미
u · v > 0사이각이 예각, 대체로 같은 방향
u · v = 0수직 (영벡터가 아닐 때)
u · v < 0둔각, 반대 방향

(u · v) / |v|는 u를 v 방향으로 내린 정사영(projection)의 길이다. "v 방향으로 얼마나 가 있나"를 재는 자로 쓸 수 있다.

점과 초평면 사이의 거리

n차원 공간에서 a₁x₁ + … + aₙxₙ + d = 0을 만족하는 점들의 집합을 초평면(hyperplane) 이라 한다. 2차원에서는 직선, 3차원에서는 평면이다. 계수를 모은 벡터 n = (a₁, …, aₙ)으로 쓰면 초평면은 n · x + d = 0이다.

계수 벡터는 법선이다

초평면 위의 두 점 p, q는 모두 n · p + d = 0, n · q + d = 0을 만족한다. 빼면 n · (q − p) = 0. 평면 위의 어떤 방향 벡터와도 내적이 0이므로 n은 초평면에 수직인 법선 벡터다. 예: 평면 z = 0(xy 평면)의 법선은 (0, 0, 1)이다.

거리 공식

점 P에서 초평면까지의 거리는 초평면 위의 아무 점 Q에서 P로 가는 벡터 P − Q를 법선 방향으로 정사영한 길이다. 평면과 평행한 성분은 거리에 기여하지 않는다.

dist = |n · (P − Q)| / |n|
     = |n · P − n · Q| / |n|
     = |n · P + d| / |n|            (Q가 평면 위의 점이라 n · Q = −d)
 
3차원:  |a·x₀ + b·y₀ + c·z₀ + d| / √(a² + b² + c²)
2차원 (점과 직선):  |a·x₀ + b·y₀ + c| / √(a² + b²)

학교에서 외우는 두 공식은 차원만 다른 같은 식이다. 절댓값을 떼면 부호가 점이 법선 쪽에 있는지 반대쪽에 있는지를 알려 준다. 선형 분류기(퍼셉트론, SVM)가 w · x + b의 부호로 클래스를 가르고 크기로 확신도를 재는 것도 같은 원리다.

2차원 외적: 방향과 넓이

2차원 벡터 u = (u₁, u₂), v = (v₁, v₂)의 외적(cross product)은 스칼라 하나로 쓴다. 3차원 외적의 z 성분이다.

u × v = u₁v₂ − u₂v₁ = |u||v|sin θ
외적 값의미
u × v > 0v가 u의 반시계 방향(왼쪽)에 있다
u × v = 0평행(한 직선 위)
u × v < 0v가 u의 시계 방향(오른쪽)에 있다

|u × v|는 u, v가 만드는 평행사변형의 넓이다. 그래서 외적은 계산 기하의 기본 연산이 된다.

CCW (세 점의 방향)

def ccw(a, b, c):
    # a→b 벡터와 a→c 벡터의 외적: 양수면 반시계, 음수면 시계, 0이면 일직선
    return (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0])
쓰임방법
선분 교차 판정두 선분 AB, CD에 대해 ccw(A,B,C)·ccw(A,B,D) ≤ 0이고 ccw(C,D,A)·ccw(C,D,B) ≤ 0 (일직선이면 범위 겹침을 따로 확인)
다각형 넓이꼭짓점을 순서대로 돌며 외적을 더해 절반: 신발끈 공식
볼록 껍질점을 정렬하고 CCW로 오목하게 꺾이는 점을 버린다
점과 직선 거리`

점이 삼각형 안에 있는가

삼각형 ABC와 점 P에 대해 d1 = ccw(A, B, P), d2 = ccw(B, C, P), d3 = ccw(C, A, P)를 구한다. P가 안쪽이면 세 변을 같은 방향으로 돌 때 P가 늘 같은 쪽에 있으므로 세 값의 부호가 모두 같다. 양수와 음수가 섞이면 바깥이다. 0이 있으면 변 위다.

def in_triangle(a, b, c, p):
    d = [ccw(a, b, p), ccw(b, c, p), ccw(c, a, p)]
    has_neg = any(x < 0 for x in d)
    has_pos = any(x > 0 for x in d)
    return not (has_neg and has_pos)        # 변 위도 안쪽으로 친다 (제외하려면 0도 검사)

같은 판정을 넓이로도 할 수 있다. P로 삼각형을 셋으로 나눈 넓이(외적의 절댓값의 절반)의 합이 원래 넓이와 같으면 안쪽, 크면 바깥이다. 부호 있는 넓이를 그대로 더하면 P가 어디에 있든 합이 같아지므로 반드시 절댓값을 취한다. 세 작은 삼각형 넓이를 전체 넓이로 나눈 비율이 무게중심 좌표(barycentric coordinates) 이고, 세 값이 모두 0 이상이면 안쪽이다. 부호 비교 방식이 나눗셈이 없어 더 간단하고 정확하다.

직선 기준 정렬

방향 벡터 d를 가진 직선(기준점 p₀)에 대해 각 점 p를

  • cross(d, p − p₀)로 정렬하면 직선에서 떨어진 부호 있는 거리 순서,
  • dot(d, p − p₀)로 정렬하면 직선을 따라간 위치 순서가 된다.

두 값을 (외적, 내적) 순으로 비교하면 직선을 평행 이동하며 점을 하나씩 넘기는 스위핑의 순서가 된다. 실제 거리가 아니라 순서만 필요하므로 |d|로 나누지 않는다. 그래서 정수 좌표라면 정수 연산만으로 정확하게 비교할 수 있다. 부동소수점 거리를 쓰면 같은 줄 위의 점이 오차로 갈라질 수 있다.

자주 쓰는 판정

기하는 대개 문제의 주제가 아니라 다른 알고리즘의 부품이다. 2차원에서 자주 쓰는 판정은 제곱근과 나눗셈 없이 할 수 있다.

판정방법
두 점의 거리 비교dx² + dy²끼리 비교한다. 제곱근은 단조 증가라 순서가 같으므로 계산할 필요가 없다. 원점에서 가장 가까운 k개 점은 이 값으로 크기 k 힙을 쓴다
두 원이 겹치는가중심 사이 거리의 제곱이 반지름 합의 제곱보다 작으면 겹친다: dx² + dy² < (r1 + r2)²
축에 평행한 두 직사각형이 겹치는가x축과 y축에서 각각 구간이 겹쳐야 한다: a.left < b.right and b.left < a.right and a.bottom < b.top and b.bottom < a.top. 1차원 구간 겹침(스위핑)을 두 번 쓰는 셈이다

변의 길이·넓이·좌표가 0인 경우가 가장 자주 놓치는 경계 사례다. 넓이 0인 직사각형, 반지름 0인 원, 원점 위의 점, 모서리만 닿는 경우를 겹침으로 칠지 먼저 정한다. 등호를 넣느냐가 답을 가른다.

정리

  • 내적 = 같은 방향 성분. 0이면 수직, ÷|v|면 정사영 길이
  • 초평면 n · x + d = 0의 계수 벡터 n은 법선이고, 점과의 거리는 |n · P + d| / |n|
  • 2차원 외적 = 방향(부호)과 넓이(크기). CCW 하나로 교차·넓이·볼록 껍질·거리·삼각형 내부 판정을 처리한다.
  • 계산 기하에서는 나눗셈을 미루고 정수 외적·내적으로 비교해 오차를 피한다.

관련 노트: 벡터공간과 부분공간, 스위핑, 퍼셉트론과 다층 퍼셉트론

원본 기록4

댓글

GitHub 계정으로 댓글을 남길 수 있어요.