1872년, 펠릭스 클라인은 기하학을 변환군에서 보존되는 불변량의 연구로 설명했다. 이 관점에서는 도형 자체보다 도형에 작용하는 변환을 중심에 둔다. 이 단원에서는 변환을 행렬로 표현하고, 각 변환이 보존하는 성질을 비교한다.
연립일차방정식은 첨가행렬이 되고, 풀이는 세 가지 행 연산의 조합이 된다. 목표: 왼쪽을 $\begin{pmatrix}1&0\\0&1\end{pmatrix}$ 로 만들면 오른쪽 열이 곧 해! 최소 횟수로 풀어 보자.
첨가행렬 $(A \mid I)$ 에 같은 행 연산을 가해 $(I \mid A^{-1})$ 을 얻는 것이 가우스-조르당 역행렬 계산법이다 [12고대02-02]. 연결 탐구 1(Lights Out)에서는 이 소거법을 0과 1로 이루어진 $\mathbb{F}_2$에서 적용하면 퍼즐을 연립방정식으로 풀 수 있다. 같은 알고리즘, 다른 우주.
선형변환 $T$ 는 조건 둘로 정의된다: $T(u+v) = T(u)+T(v)$, $T(cu) = cT(u)$ — 도입에서 살펴본 두 조건이 그대로 적용된다. 이 조건 때문에 $T$는 격자를 "평행·등간격"으로만 구부릴 수 있고, $T(e_1), T(e_2)$ 두 벡터만 알면 전부 결정된다. 그 두 벡터를 열로 세운 것이 행렬이다.
초록/붉은 사각형 = 단위정사각형의 상. 그 넓이가 $|\det A|$, 뒤집히면(붉은색) $\det A < 0$ — 행렬식은 "넓이 배율 × 방향"이다 [12고대02-03]. 회전 프리셋에서 λ가 "복소수"가 되는 것도 놓치지 말 것 — Unit 3의 복선이다.
변환을 이어 붙이면(합성) 행렬은 곱이 된다: $T_2 \circ T_1 \leftrightarrow A_2 A_1$. 곱의 순서를 바꾸면 결과도 같을까? 두 합성변환을 나란히 실행해 보자.
가역인 변환들의 모임은 합성에 대해 닫혀 있고, 항등원(항등변환)과 역원(역변환)을 갖는다 — 이런 구조를 군(group)이라 부른다. 회전들만 모으면 가환군, 회전+반사를 모으면 비가환군(정다각형의 대칭군)이 된다. 현대 수학은 "대칭 = 군"이라는 사전으로 물리학 (입자물리 표준모형)까지 기술한다. wiki: algebra / groups.
변환군을 고르고 여러 변환을 적용해 보자. 어떤 성질이 계속 보존되는지 확인한다. 허용되는 변환이 넓어질수록 살아남는 성질은 줄어든다 — 그 생존자 목록이 곧 "그 기하학의 연구 대상"이다.
복소수 $z = a+bi$ 에 행렬 $M(z) = \begin{pmatrix} a & -b \\ b & a \end{pmatrix}$ 를 대응시키면, 복소수 곱셈이 정확히 행렬곱이 된다. $i$ 는 $\begin{pmatrix} 0 & -1 \\ 1 & 0 \end{pmatrix}$ — 90° 회전행렬. $i^2 = -1$ 이 신비였던 이유: 90° 회전을 두 번 하면 180° 회전(= −1배)이기 때문이다.
2차원 회전을 복소수가 담당했다면, 3차원 회전은 사원수(quaternion)가 담당한다 — 게임 엔진과 로켓 자세 제어가 실제로 쓰는 수 체계. 소장 논문 Quaternions and Rotations in E⁴를 참고하면 수행평가 심화 주제로 확장할 수 있다.
초점거리를 $d$로 두면 "멀수록 작게"는 $x' = \dfrac{d\,x}{z+d}$ — 나눗셈이 들어간 명백한 비선형이다. 그런데 좌표를 하나 늘려 $(x, y, z, 1)$ 로 쓰면(동차좌표), 원근 투영이 행렬 곱 + 마지막 나눗셈 한 번으로 정리된다. 모든 3D 게임의 매 프레임이 이 트릭 위에서 돈다.
과제: 논문 한 편을 골라 그 속의 정의·명제를 직접 계산/시뮬레이션으로 구현하고 LaTeX 논술로 정리한다. 아래 스타터 코드를 복사해 시작점으로 쓰고, ★ 표시된 값을 바꿔 자기만의 탐구로 발전시켜라.
<canvas id="c" width="500" height="500"></canvas>
<script>
const ctx = document.getElementById("c").getContext("2d");
// 반슬리의 아핀 변환 4개: [a,b,c,d,e,f,확률] → (x,y) ↦ (ax+by+e, cx+dy+f)
const maps = [
[ 0.00, 0.00, 0.00, 0.16, 0, 0.00, 0.01], // ★ 줄기
[ 0.85, 0.04, -0.04, 0.85, 0, 1.60, 0.85], // 본체의 0.85를 0.8로 바꾸어 보자.
[ 0.20, -0.26, 0.23, 0.22, 0, 1.60, 0.07], // ★ 왼쪽 잎
[-0.15, 0.28, 0.26, 0.24, 0, 0.44, 0.07], // ★ 오른쪽 잎
];
let x = 0, y = 0;
for (let i = 0; i < 40000; i++) {
let r = Math.random(), m;
for (m of maps) { r -= m[6]; if (r < 0) break; }
[x, y] = [m[0]*x + m[1]*y + m[4], m[2]*x + m[3]*y + m[5]];
ctx.fillStyle = "#55703F";
ctx.fillRect(250 + x*46, 500 - y*46, 1, 1); // ★ 46: 확대 배율
}
</script>
<canvas id="c" width="500" height="400"></canvas>
<script>
const ctx = document.getElementById("c").getContext("2d");
const d = 4; // ★ 카메라 거리 (2로 줄이면 광각!)
const verts = []; // 정육면체 8꼭짓점
for (const sx of [-1,1]) for (const sy of [-1,1]) for (const sz of [-1,1])
verts.push([sx, sy, sz]);
const edges = [[0,1],[0,2],[0,4],[3,1],[3,2],[3,7],[5,1],[5,4],[5,7],[6,2],[6,4],[6,7]];
let th = 0;
setInterval(() => {
ctx.clearRect(0, 0, 500, 400);
th += 0.01; // ★ 회전 속도
const P = verts.map(([x,y,z]) => {
const rx = x*Math.cos(th) + z*Math.sin(th); // y축 회전 (선형!)
const rz = -x*Math.sin(th) + z*Math.cos(th);
const w = rz/d + 1; // 동차좌표의 마지막 성분
return [250 + 130*rx/w, 200 - 130*y/w]; // 원근 나눗셈은 여기 한 번뿐
});
ctx.strokeStyle = "#8A4525"; ctx.lineWidth = 2;
for (const [i,j] of edges) {
ctx.beginPath(); ctx.moveTo(...P[i]); ctx.lineTo(...P[j]); ctx.stroke();
}
}, 16);
</script>
Lights Out 해법 스타터는 연결 탐구 1 하단에 있으며, 논술 개요 양식은 교사 배포 자료에서 확인할 수 있다.
오늘 배운 변환을 확률적으로 반복하면 IFS 프랙탈을 만들 수 있다.
프레네 틀에서 T를 N으로 보내는 변환은 90° 회전행렬로 표현된다.