행렬의 고유값(eigenvalue)을 회전 각도로 사용합니다.
선형대수학에서 Second Difference Matrix는 이산 2차 미분 연산자를 행렬로 표현한 것입니다.
연속 함수의 2차 도함수 f″(x)를 이산 점(discrete points)에서 근사할 때 나타납니다.
중심 차분(central difference)으로 근사하면:
계수 [1, −2, 1]이 행렬의 각 행을 구성합니다. 경계 조건(boundary condition)에 따라 세 가지 행렬이 만들어집니다.
K — Fixed-Fixed (양쪽 고정)
양 끝이 벽에 고정된 스프링-질량 시스템에 해당합니다. 모든 대각 원소가 2입니다.
T — Free-Fixed (한쪽 자유, 한쪽 고정)
왼쪽 끝이 자유롭고 오른쪽이 고정된 경우입니다. 첫 번째 대각 원소가 1입니다.
B — Free-Free (양쪽 자유)
양 끝이 모두 자유로운 경우입니다. 첫 번째와 마지막 대각 원소가 1입니다. B는 특이 행렬(singular matrix)로, 고유값 0을 가집니다.
각 행렬의 고유값은 경계 조건에 따라 달라집니다. n×n 행렬에 대해:
3×3 경우 구체적인 값:
이 데모에서는 3×3 행렬의 3개 고유값 (λ₁, λ₂, λ₃)을 X, Y, Z 축의 회전 각도(라디안)로 매핑합니다.
행렬마다 고유값이 다르므로 큐브가 서로 다른 각도로 회전합니다. 특히 B 행렬은 λ₁ = 0 이므로 X축 회전이 없는 것을 관찰할 수 있습니다.
Three.js로 3D 장면을 만듭니다. Scene, Camera, Renderer를 세팅하고 정육면체(BoxGeometry)를 추가합니다.
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(50, w / h, 0.1, 100);
const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
// 정육면체 생성
const geometry = new THREE.BoxGeometry(2, 2, 2);
const material = new THREE.MeshPhongMaterial({
color: 0x58a6ff,
transparent: true,
opacity: 0.85
});
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);
// 와이어프레임 (모서리 선)
const edges = new THREE.EdgesGeometry(geometry);
const lineMat = new THREE.LineBasicMaterial({ color: 0xffffff });
const wireframe = new THREE.LineSegments(edges, lineMat);
cube.add(wireframe);
Second Difference Matrices K, T, B를 2차원 배열로 정의합니다.
const matrices = {
K: [[2,-1,0], [-1,2,-1], [0,-1,2]],
T: [[1,-1,0], [-1,2,-1], [0,-1,2]],
B: [[1,-1,0], [-1,2,-1], [0,-1,1]]
};
고유값은 해석적 공식으로 구합니다:
function eigenvalues(name) {
const n = 3;
if (name === 'K')
return [1,2,3].map(k => 2 - 2*Math.cos(k*Math.PI/(n+1)));
if (name === 'T')
return [1,2,3].map(k => 2 - 2*Math.cos((2*k-1)*Math.PI/(2*n+1)));
// B
return [0,1,2].map(k => 2 - 2*Math.cos(k*Math.PI/n));
}
고유값을 목표 회전 각도로 설정하고, 매 프레임 현재 각도를
lerp(선형 보간)로 부드럽게 이동시킵니다.
// 목표 각도 설정
const ev = eigenvalues(name); // [λ₁, λ₂, λ₃]
targetRotation = { x: ev[0], y: ev[1], z: ev[2] };
// 매 프레임 보간 (animate 루프 안)
cube.rotation.x += (targetRotation.x - cube.rotation.x) * 0.05;
cube.rotation.y += (targetRotation.y - cube.rotation.y) * 0.05;
cube.rotation.z += (targetRotation.z - cube.rotation.z) * 0.05;
0.05는 보간 속도입니다. 값이 작을수록 천천히, 클수록 빠르게 회전합니다.
Reset 버튼은 목표 각도를 (0, 0, 0)으로 돌려 큐브를 원래 위치로 복원합니다.