점과 벡터: 계산기하학의 출발점

계산기하학의 기초인 점과 벡터를 코드로 다루는 법을 정리합니다. 벡터의 덧셈·뺄셈·스칼라곱, 크기와 정규화, 내적의 기하학적 의미와 부호 판정, 정수 좌표를 쓰는 이유와 부동소수점 오차 관리까지 실전 관점으로 살펴봅니다.

· 6 min read · PALDYN Team

지난 글에서 정수론 파트를 마무리했습니다. 이번 글부터는 새로운 영역인 계산기하학(computational geometry)을 시작합니다. 화면 위의 점들이 어느 쪽으로 꺾이는지, 두 선분이 만나는지, 점들을 감싸는 가장 작은 다각형은 무엇인지 — 이런 질문들은 모두 가장 기본적인 도구인 (point)과 벡터(vector) 위에서 풀립니다. 이 글에서는 좌표를 코드로 다루는 토대를 단단히 다집니다.

점과 벡터는 무엇이 다른가

점은 평면 위의 위치이고, 벡터는 방향과 크기입니다. 둘 다 (x, y) 쌍으로 표현되지만 의미가 다릅니다. 점 A에서 점 B로 가는 방향 벡터는 단순한 뺄셈으로 얻습니다.

v = B − A = (B.x − A.x, B.y − A.y)

이 한 줄이 계산기하 코드의 거의 모든 출발점입니다. “두 점을 잇는 변”, “한 점에서 다른 점을 보는 방향” 같은 표현이 전부 이 뺄셈으로 환원됩니다.

벡터 정의와 덧셈

벡터끼리의 덧셈은 두 이동을 이어붙이는 것이고, 기하학적으로는 평행사변형의 대각선으로 나타납니다. 스칼라곱은 벡터를 늘이거나 줄입니다.

기본 연산 구현

파이썬에서는 튜플로 가볍게 다룰 수 있습니다. 명확함을 위해 작은 헬퍼 함수들을 정의합니다.

def sub(b, a):                     # 방향 벡터 a→b
    return (b[0] - a[0], b[1] - a[1])

def add(a, b):
    return (a[0] + b[0], a[1] + b[1])

def scale(v, k):                   # 스칼라곱
    return (v[0] * k, v[1] * k)

def norm2(v):                      # 크기의 제곱
    return v[0] * v[0] + v[1] * v[1]

여기서 주목할 점은 norm2크기의 제곱을 반환한다는 것입니다. 실제 크기 √(x²+y²)는 무리수라 부동소수점 오차를 부릅니다. 두 거리를 비교하는 대부분의 상황에서는 제곱한 값끼리 비교하면 충분하고, 정수 좌표라면 오차 없이 정확합니다.

내적: 각도를 부호로 읽다

내적(dot product)은 두 벡터의 대응 성분을 곱해 더한 값입니다.

a·b = a.x·b.x + a.y·b.y = |a||b| cos θ

두 번째 등식이 핵심입니다. 내적은 두 벡터 사이 각 θ의 코사인에 비례합니다. cos은 0°에서 90°까지 양수, 90°에서 음수가 되므로, 내적의 부호만으로 두 벡터가 이루는 각이 예각인지 둔각인지 직각인지 판정할 수 있습니다.

내적의 부호와 각도

def dot(a, b):
    return a[0] * b[0] + a[1] * b[1]

# a·b > 0  예각  /  = 0  직각  /  < 0  둔각

cos이나 arccos을 호출하지 않고 정수 곱셈만으로 각도 관계를 알아낸다는 점이 중요합니다. 부동소수점 삼각함수는 느리고 오차가 있어, 정수 내적으로 대체할 수 있으면 그렇게 하는 것이 정석입니다.

사영: 한 벡터를 다른 벡터에 투영

내적의 또 다른 쓰임은 사영(projection)입니다. 벡터 b를 a 방향으로 투영한 길이는 dot(a,b) / |a|입니다. 점과 직선 사이 거리, 가장 가까운 점 찾기 같은 문제가 모두 사영으로 풀립니다.

def project_len(a, b):
    # b를 a 위에 사영한 (부호 있는) 길이
    return dot(a, b) / (norm2(a) ** 0.5)

이 단계에서야 비로소 제곱근이 등장합니다. 실제 거리 값이 필요할 때만 √를 쓰고, 그전까지는 정수 영역에 머무는 것이 좋은 습관입니다.

정수 좌표 vs 부동소수점

계산기하에서 가장 흔한 버그의 원인은 부동소수점 오차입니다. 입력 좌표가 정수라면, 내적·외적·거리 제곱 같은 핵심 연산을 정수만으로 유지할 수 있습니다.

연산정수 유지 가능?비고
덧셈·뺄셈·스칼라곱O항상 정수
내적O각도 부호 판정에 충분
외적O방향 판별의 핵심 (다음 글)
거리 제곱O비교에는 제곱이면 충분
실제 거리·각도X√, arccos 필요 시에만

원칙은 단순합니다. 비교와 판정은 정수로, 실측이 필요할 때만 실수로 넘어갑니다. 이렇게 하면 eps 비교에 시달리는 일이 크게 줄어듭니다.

다음 글에서는 계산기하의 가장 중요한 도구인 외적(cross product)과 그것으로 점의 회전 방향(CCW)을 판별하는 법을 다룹니다. 선분 교차, 볼록 껍질, 다각형 넓이가 모두 이 한 연산 위에 세워집니다.


지난 글: 피보나치 계산 기법: 빠른 배가 공식과 피사노 주기

다음 글: 외적과 방향 판별: CCW의 모든 것


읽어주셔서 감사합니다. 😊