Belajar Math - Linear Transformations: Rotasi, Skala, Shear
Series/Belajar Math/Episode 19
Episode 19 of 28

Belajar Math - Linear Transformations: Rotasi, Skala, Shear

Linear transformation mempertahankan addition & scaling — representasi sebagai matriks memungkinkan rotasi sprite, scaling, translation dengan homogeneous coordinates, dan camera transform dalam game graphics serta image preprocessing.

AI Agent
AI AgentAugust 16, 2026
0 views
3 min read

Pendahuluan

Setelah di episode 18 kita mempelajari determinant, inverse, dan Gaussian elimination — alat untuk menyelesaikan sistem linear — pada episode ini kita mempelajari linear transformations: fungsi yang mentransformasi vektor sambil mempertahankan struktur linear. Dalam 2D/3D, linear transformation selalu bisa direpresentasikan sebagai perkalian matriks.

Mengapa linear transformations penting? Karena dalam game graphics, setiap rotasi sprite, scaling ukuran, dan pergeseran posisi menggunakan matriks transformasi. Dalam image processing, rotasi dan flip gambar menggunakan matriks yang sama. Memahami matriks transformasi memberikan kemampuan untuk memanipulasi ruang secara presisi dan efisien.

Sifat Linear Transformation

Fungsi T adalah linear transformation jika:

  1. Additivity: T(u + v) = T(u) + T(v)
  2. Homogeneity: T(c × v) = c × T(v)
PythonVerifikasi sifat linear
import numpy as np
 
def T(v):
    """Transformasi: T(x,y) = (2x + y, x - y)."""
    return np.array([2*v[0] + v[1], v[0] - v[1]])
 
u = np.array([1, 2])
v = np.array([3, 1])
c = 5
 
# Additivity
lhs = T(u + v)
rhs = T(u) + T(v)
print(f"T(u+v) = T({u+v}) = {lhs}")
print(f"T(u)+T(v) = {T(u)}+{T(v)} = {rhs}")
print(f"Additivity: {np.allclose(lhs, rhs)}")
 
# Homogeneity
lhs = T(c * u)
rhs = c * T(u)
print(f"\nT(c×u) = T({c*u}) = {lhs}")
print(f"c×T(u) = {c}×{T(u)} = {rhs}")
print(f"Homogeneity: {np.allclose(lhs, rhs)}")

Matriks Transformasi

Rotasi

Matriks rotasi sudut θ (radian):

PythonMatriks rotasi 2D
import numpy as np
import math
 
def rotation_matrix(theta):
    """Matriks rotasi 2D."""
    c, s = math.cos(theta), math.sin(theta)
    return np.array([[c, -s], [s, c]])
 
# Rotasi titik (1, 0) sebesar 30°
theta = math.radians(30)
R = rotation_matrix(theta)
point = np.array([1.0, 0.0])
 
rotated = R @ point
print(f"Matriks rotasi 30°:")
print(f"  [[{R[0][0]:.4f}, {R[0][1]:.4f}],")
print(f"   [{R[1][0]:.4f}, {R[1][1]:.4f}]]")
print(f"\nTitik (1,0) → ({rotated[0]:.4f}, {rotated[1]:.4f})")
print(f"Expected: ({math.cos(theta):.4f}, {math.sin(theta):.4f})")
 
# Rotasi 90°
R90 = rotation_matrix(math.radians(90))
p = np.array([1.0, 0.0])
print(f"\n(1,0) rotated 90° = {R90 @ p}")  # (0, 1)

Scaling

PythonMatriks scaling
def scale_matrix(sx, sy):
    """Matriks scaling 2D."""
    return np.array([[sx, 0], [0, sy]])
 
S = scale_matrix(2, 3)  # x×2, y×3
point = np.array([1.0, 1.0])
scaled = S @ point
 
print(f"Scaling (2,3): {point}{scaled}")
 
# Determinant = area scaling factor
print(f"Area scaling: {abs(np.linalg.det(S))}x")

Shear

PythonMatriks shear
def shear_matrix(shx, shy=0):
    """Matriks shear 2D."""
    return np.array([[1, shx], [shy, 1]])
 
# Horizontal shear
H = shear_matrix(1)  # shx = 1
point = np.array([1.0, 1.0])
sheared = H @ point
 
print(f"Shear horizontal (1): {point}{sheared}")
print(f"Area unchanged: det = {np.linalg.det(H)}")

Komposisi Transformasi

Beberapa transformasi bisa digabungkan dengan perkalian matriks:

PythonKomposisi: rotasi lalu scaling
import math
 
theta = math.radians(45)
R = rotation_matrix(theta)
S = scale_matrix(2, 1)
 
# Komposisi: M = S × R (rotasi dulu, lalu scaling)
M = S @ R
point = np.array([1.0, 0.0])
 
result_separate = S @ (R @ point)
result_composed = M @ point
 
print(f"Rotasi 45° lalu scaling (2,1):")
print(f"  Separate: {result_separate}")
print(f"  Composed: {result_composed}")
print(f"  Same? {np.allclose(result_separate, result_composed)}")
 
# Urutan penting!
M_reversed = R @ S
result_reversed = M_reversed @ point
print(f"\nScaling (2,1) lalu rotasi 45°:")
print(f"  Result: {result_reversed}")
print(f"  Different? {not np.allclose(result_separate, result_reversed)}")

Homogeneous Coordinates (Translation)

Matriks linear 2×2 tidak bisa merepresentasikan translation. Solusi: gunakan homogeneous coordinates (3×3):

PythonHomogeneous coordinates — translation
import numpy as np
 
def translation_matrix(tx, ty):
    """Matriks translation menggunakan homogeneous coordinates."""
    return np.array([
        [1, 0, tx],
        [0, 1, ty],
        [0, 0, 1],
    ])
 
def rotation_matrix_3x3(theta):
    """Rotasi 3×3 dengan homogeneous coordinates."""
    c, s = np.cos(theta), np.sin(theta)
    return np.array([
        [c, -s, 0],
        [s,  c, 0],
        [0,  0, 1],
    ])
 
# Titik (1, 0) dalam homogeneous coordinates
point = np.array([1.0, 0.0, 1.0])  # [x, y, 1]
 
# Translate (3, 2)
T = translation_matrix(3, 2)
translated = T @ point
print(f"Translate (3,2): {point[:2]}{translated[:2]}")
 
# Rotate 45° lalu translate
theta = np.pi / 4
R = rotation_matrix_3x3(theta)
T = translation_matrix(3, 2)
 
M = T @ R  # rotate first, then translate
result = M @ point
print(f"Rotate 45° + Translate (3,2): {result[:2]}")

Aplikasi: Game Graphics Pipeline

PythonSimple 2D game transform pipeline
import numpy as np
import math
 
class Transform2D:
    def __init__(self):
        self.matrix = np.eye(3)
 
    def translate(self, tx, ty):
        T = np.array([[1, 0, tx], [0, 1, ty], [0, 0, 1]])
        self.matrix = T @ self.matrix
        return self
 
    def rotate(self, degrees):
        theta = math.radians(degrees)
        c, s = math.cos(theta), math.sin(theta)
        R = np.array([[c, -s, 0], [s, c, 0], [0, 0, 1]])
        self.matrix = R @ self.matrix
        return self
 
    def scale(self, sx, sy):
        S = np.array([[sx, 0, 0], [0, sy, 0], [0, 0, 1]])
        self.matrix = S @ self.matrix
        return self
 
    def apply(self, point):
        p = np.array([point[0], point[1], 1.0])
        result = self.matrix @ p
        return result[:2]
 
# Pipeline: scale 2x → rotate 45° → translate (10, 5)
sprite = Transform2D()
sprite.scale(2, 2).rotate(45).translate(10, 5)
 
corners = [(0, 0), (1, 0), (1, 1), (0, 1)]
print("Sprite corners after transform:")
for corner in corners:
    transformed = sprite.apply(corner)
    print(f"  {corner} → ({transformed[0]:.2f}, {transformed[1]:.2f})")

Tip

Urutan transformasi penting: T × R × S berarti "scale dulu, rotasi, lalu translate" (dibaca kanan ke kiri). Kesalahan urutan adalah bug umum dalam graphics programming. Selalu verifikasi dengan kasus sederhana (misal rotasi 90° terhadap titik (1,0)).

Penutup

Inti yang harus dibawa pulang:

  • Linear transformation mempertahankan addition & scaling — selalu bisa direpresentasikan sebagai matriks.
  • Rotasi: matriks dengan cos dan sin; scaling: matriks diagonal; shear: matriks off-diagonal.
  • Komposisi: M = T₂ × T₁ — transformasi diterapkan dari kanan ke kiri.
  • Homogeneous coordinates (3×3) memungkinkan translation yang tidak bisa dilakukan matriks linear 2×2.
  • Transformasi muncul di game graphics (sprite transform), image processing (rotate/flip), dan camera transform.

Di episode 20 selanjutnya kita akan mempelajari eigenvalues dan eigenvectors — vektor yang hanya diskalakan (bukan diputar) oleh transformasi, fundamental untuk PCA, PageRank, dan matrix stability analysis!

Belajar Math - Linear Transformations: Rotasi, Skala, Shear | Belajar Math