Lemma
수학, 거꾸로
도입 · 가만히 있지 않는 수

사라진 교점들은 어디로 갔을까?

화면 위 두 이차곡선을 끌어보라. 어떤 때는 교점이 네 개, 어떤 때는 , 하나, 없음. 충돌을 계산하는 물리 엔진, 패스를 잘라내는 벡터 도구, 외곽선을 다듬는 폰트 래스터라이저, 픽을 처리하는 레이 트레이서 — 모두 “몇 개?”라는 물음에 흔들리지 않는 답이 필요하다. 화면 위의 수는 깜빡거린다. 그 아래 수학은 깜빡이지 않는다.

베주 정리는 두 이차곡선의 교점이 늘 4개라고 말한다 — 올바른 수 체계, 올바른 평면, 올바른 중복도로 셀 때. 아래 위젯은 베주 모듈에 실린 위젯과 같은 것이다. 다만 여기서 답하는 질문이 다르다: 그 4개 중에서 화면이 실제로 보여주는 건 어느 것인가?

위젯 — 두 원뿔곡선, 네 교점
실수4
복소0
중복도 > 10
총합 (베주)4 = 2 · 2
Re xIm x복소 x-평면
네 프리셋을 순서대로 눌러보자. 일반은 4개의 실수 교점 (베주가 도움 없이 성립). 은 3개로 떨어져 보인다 — 중복도 표시를 켜면 접점이 두 번으로 센다. 분리는 0개로 보인다 — 복소 보기를 켜면 네 교점이 실평면 바깥에 있는 게 드러난다. 부분은 두 보정이 섞인다. 모든 프리셋의 총합은 4.
흐름
1

화면이 보는 것 vs 거기 있는 것

2D 평면 위의 두 실수 곡선. 눈에 보이는 셈이란 같은 픽셀에서 두 곡선이 만나는 점의 개수 — 좌표가 실수이고 양쪽 모두 유한한 경우다. 래스터 샘플링으로 답을 내는 단순 충돌 검출기, 근사 근-찾기로 답을 내는 CAD 엔진이 모두 이 셈을 내놓는다. 곡선이 지금 어디쯤 떠 있느냐에 따라 달라지고, 작은 섭동에도 쉽게 흔들린다.

위젯에서 확인해 보자. 일반 프리셋은 실수 교점 4개 — 보이는 셈과 베주의 셈이 맞아떨어진다. 프리셋에서는 3개로 보이지만, 중복도 표시를 켜면 그중 하나에 ×2×2가 붙는다. 분리 프리셋에서는 0개로 보이지만, 복소 보기를 켜면 옆 패널에 빈 동그라미 네 개가 떠오른다. 사라진 교점들은 잃어버린 것이 아니다. 단지 실-아핀 평면을 떠났을 뿐.

2

세 가지 숨는 곳

베주의 보정(베주 모듈에서 자세히 다룬다)은 사라진 교점이 어디로 갔는지 정확히 짚어준다. 보정은 셋, 들여다볼 자리도 셋이다.

  • 접점. 두 교점이 한 기하점으로 포개진 경우 — 대수는 여전히 둘이라고 말하지만 렌더러 눈에는 한 점만 보인다. 이걸 장부에 적는 방식이 다. 접 교점은 2로 센다.
  • 보이는 평면 바깥. 교점의 좌표가 복소수인 경우 — 대수의 해로는 분명히 존재하지만 실수 (x,y)(x, y) 격자 위에는 찍을 자리가 없다. 떨어져 있는 두 단위원조차 (3/2,±i5/2)(3/2, ± i \sqrt{5} / 2)에서 만난다. 화면에는 이 점을 놓을 곳이 없다.
  • 무한 멀리. 어떤 교점은 무한원선 위에 자리 잡는다. 서로 다른 두 원은 어디에 놓여 있든 늘 두 원형점 I=[1:i:0]I = [1 : i : 0]J=[1:i:0]J = [1 : −i : 0]을 공유한다 — 베주의 4개 중 2개는 이미 화면 밖, 복소수, 좋든 싫든 장부에 적힌 셈이다. 이 보정의 무대가 이다.
3

그래픽 엔진이 *흔들리지 않는 수*를 챙기는 이유

“보이는 셈”만 좇는 엔진은 깨지기 쉽다. 거의 접하는 두 원의 보이는 셈은 서브픽셀 떨림에 따라 0이 되었다 1이 되었다 2가 된다. 한 프레임에 “교점 없음”, 다음 프레임에 “교점 둘”이라 보고하는 렌더러는 결국 수치 잡음을 물리로 둔갑시키고 있는 것이다. 답은 대수적 셈 — 베주가 보장해 주는 바로 그 셈 — 을 먼저 구하고, 각 근을 분류하는 데 있다.

실제 절차는 이렇다. y-종결식(x에 대한 4차)을 푼다. 중복도까지 포함해 복소근 4개를 모두 찾는다. 각각을 실-아핀(보임), 복소(평면 밖), 무한원(점근) 중 하나로 분류한다. 첫 번째 부류의 개수가 곧 보이는 셈이다. 접점은 “우연히 매우 가까운 두 근”이 아니라 중복근으로 표시된다. 중복도 2인 실수 근 하나서로 ε 안에 있는 서로 다른 실수 근 둘은 화면 위에서는 똑같아 보이지만, _기하적으로는 전혀 다른 상황_이다 — 대수 분류가 이 둘을 갈라놓는다.

4

엔진이 실제로 계산하는 것

파이프라인은 짧다. (1) 두 이차곡선 식에서 해 다른 변수만 남은 단일 다항식을 얻는다 — 둘 다 차수 2이면 4차식이 나온다. (2) 이 다항식의 근을 수치적으로 구한다(Durand–Kerner 같은 방법으로). (3) 대응하는 y 좌표를 선형 역대입으로 복원한다. (4) 각 교점에 실-아핀, 복소, 무한 중 하나의 꼬리표를 단다. 위쪽 위젯은 슬라이더를 움직일 때마다 (1)–(4)를 처음부터 다시 돌린다.

# Engine pipeline: solve, classify, render. Bezout count = 4 always
# for two conics; the picture only shows the real-affine subset.
import numpy as np

def conic_resultant(c1, c2):
    """y-resultant of two conics → quartic in x. (Same as bezout module.)"""
    a1, b1, cc1, d1, e1, k1 = c1
    a2, b2, cc2, d2, e2, k2 = c2
    P = np.polynomial.Polynomial
    A1, A2 = cc1, cc2
    B1, B2 = P([e1, b1]), P([e2, b2])
    C1, C2 = P([k1, d1, a1]), P([k2, d2, a2])
    return (A1*C2 - A2*C1)**2 - (A1*B2 - A2*B1)*(B1*C2 - B2*C1)

def classify(roots, eps=1e-6):
    """Group complex roots into 'real-affine' (visible) and 'complex' (off-plane)."""
    visible, off_plane = [], []
    for r in roots:
        if abs(r.imag) < eps:
            visible.append(r.real)
        else:
            off_plane.append(r)
    return visible, off_plane

# Two ellipses, perpendicular major axes — the "general" preset.
c1 = (1/4, 0, 1,    0, 0, -1)
c2 = (1,   0, 1/4,  0, 0, -1)
roots = conic_resultant(c1, c2).roots()
visible, hidden = classify(roots)
len(visible), len(hidden)        # → (4, 0)   four visible crossings

# Two disjoint ellipses — the "disjoint" preset.
c2_far = (9, 0, 1, 0, -10, 24)
roots2 = conic_resultant(c1, c2_far).roots()
v2, h2 = classify(roots2)
len(v2), len(h2)                 # → (0, 4)   nothing on screen, all complex
# Bezout 4 = 0 visible + 4 hidden. The "disjoint" pair never lost the count;
# the renderer just had no place to draw the imaginary parts.
5

그래픽 스택 안의 자리

같은 베주 + 분류 로직이 모양만 바꿔서 곳곳에서 돌아간다.

  • 충돌 검출. 두 볼록 도형(원·타원·캡슐)이 몇 번 만나는가? 베주가 상한을 잡아 주고, 접 + 중복도가 스치는 접촉을 잡아내며, “실수 0 + 복소 4”는 곡선이 깔끔히 떨어져 있다는 뜻이 된다.
  • 벡터 클리핑. Illustrator나 Figma에서 두 경로의 교차를 구할 때, 도구는 3차 베지에 곡선 사이의 대수 교점을 계산한다 — 차수 3 × 차수 3 = 최대 9개를 보임 / 구간 밖 / 접으로 나눈다.
  • 레이-곡선 픽. 직선(차수 1)과 이차곡선(차수 2)은 대수적으로 2개의 점에서 만난다. 마우스 클릭은 레이를 따라 처음 만나는 실-아핀 교점을 고른다. 둘 다 복소수면 클릭은 그대로 빗나간다.
  • 폰트 외곽선 래스터화. 수평 스캔라인(차수 1)이 글리프 외곽선(최대 3차의 베지에)을 d·1 = d개의 점에서 가로지른다. 중복도까지 함께 세면 짝-홀 채움 규칙이 덤으로 따라온다.

겉 이야기는 어디서나 “세고 분류한다”이고, 그 밑의 이야기는 베주 정리와 근 분류기다. 입는 옷은 달라지지만, 셈의 규약은 변하지 않는다.

실수 교점은 들고 난다. 베주의 셈은 그러지 않는다. 화면에 비치는 것은 변하지 않는 그 셈의 실-아핀 부분집합이다. 그래픽 엔진은 셈 전체를 손에 쥔 채 원소 하나하나에 꼬리표를 달고, 그림은 그중 한 부류일 뿐이다.

exercises · 손으로 풀기
1직선과 원계산기 없이

직선 y=mx+cy = mx + c는 단위원 x2+y2=1x² + y² = 1과 베주 셈으로 몇 점에서 만나는가? 어떤 (m,c)(m, c)의 범위에서 그 점들이 모두 보이고(실-아핀), 어떤 범위에서 일부가 복소수로 숨는가? 각 경우의 예를 하나씩 그려 보라.

2두 원은 무한원을 공유한다

서로 다른 두 원을 잡자. 베주는 4번 만난다고 한다. 그런데 화면 위 그림에서는 실-아핀 교점이 늘 2개를 넘지 않는다. 나머지 2개는 언제나 어디에 있는가? (힌트: 원의 식을 무한원선 Z=0Z = 0에 넣으면 최고차 항만 남는다.)

3접 vs 거의-빗나감계산기 없이

엔진에 매개변수가 둘 있다고 하자. 각도 θθ와 허용오차 εε. θθ가 접 배치를 통과할 때, 보이는 셈은 2 → 1 → 0 → 1 → 2로 변한다. 순간은 하나의 배치, 그 양옆의 거의-접 순간은 또 다른 배치다. 그 차이를 대수적으로 진술하고(중복도 2인 근 하나 vs ε 안에 놓인 서로 다른 두 근), 견고한 엔진이 단순한 εε-거리만으로 중복 제거를 해서는 안 되는 이유를 설명하라.

4맞지 않는 삼차

수평 직선 y=0y = 0과 3차 곡선 y=x3+1y = x³ + 1의 교점을 구해 보자. 베주 예측은 1·3 = 3. 실-아핀은 몇 개이고, 나머지는 어디에 있는가? (보이는 점에는 ii가 필요 없고, 나머지에는 각각 하나씩 들어간다.)

용어집 · 이 페이지에서 쓰임 · 4
intersection multiplicity·교차 중복도
한 교점을 몇 번으로 셀지 정한 수. 두 곡선이 가로질러 만나면 한 번. 단순히 접하면 두 번 — 한 변수를 소거하면 그 점에서 이중근이 나온다. 더 높은 차수의 접촉이면 세 번, 네 번, … 베주 정리의 "정확히 de 점"은 중복도까지 더한 합이다.
projective plane·사영평면
보통 평면에 방향마다 무한원점을 하나씩 추가한 평면. 같은 방향을 공유하는 평행선들은 그 무한원점에서 만난다. 이 추가 후에는 서로 다른 두 직선이 정확히 한 점에서 만난다. 실사영평면 ℝℙ², 복사영평면 ℂℙ². 베주 정리는 ℝ²가 아니라 ℂℙ²에서 성립한다.
resultant·종결식
두 다항식 P, Q로 만든 다항식으로, 둘이 공통근을 가질 때만 0이 된다. 두 원뿔곡선 (각각 y에 대해 차수 2, 계수는 x의 식)에서 종결식으로 y를 소거하면 x에 대한 차수 2·2 = 4 다항식이 나온다. 그 4개의 (복소수, 중복도 포함) 근이 곧 베주가 약속한 4개 교점의 x좌표.
homogenize·동차화
affine 방정식을 사영좌표로 다시 쓰는 절차: x → X/Z, y → Y/Z를 대입하고 Z를 정리해 모든 항의 총 차수가 같아지게 한다. Z = 1을 대입하면 원래 affine 방정식으로 돌아온다. 예: y = x² → YZ = X².