Computer Graphics & Algorithms

Visualizing complex systems through mathematical computing: from rasterizing primitives to generating recursive fractals. 수학적 계산으로 복잡계를 시각화합니다: 래스터화 기본 도형부터 재귀 프랙탈 생성까지.

Python (NumPy) Fractal Geometry Rasterization Linear Algebra

Project Overview프로젝트 개요

Computer graphics bridges the gap between abstract mathematics and visual perception. This project explores fundamental algorithms for rendering images from code.컴퓨터 그래픽스는 추상 수학과 시각적 인식 사이를 연결합니다. 이 프로젝트는 코드로 이미지를 렌더링하는 기본 알고리즘을 다룹니다.

It includes a low-level implementation of Rasterization (converting vector shapes into pixels) and a high-performance visualizer for the Mandelbrot Set, optimizing complex number calculations using NumPy vectorization.벡터 도형을 픽셀로 변환하는 저수준 래스터화 구현과, NumPy 벡터화로 복소수 계산을 최적화한 만델브로 집합 고성능 시각화를 포함합니다.

Key Concepts Implemented구현한 핵심 개념

Vectorization벡터화

Optimized the Mandelbrot generation by operating on entire 2D grids of complex numbers simultaneously, replacing slow Python loops with C-optimized NumPy arrays.복소수 2D 격자 전체를 동시에 연산해 만델브로 생성 속도를 높였고, 느린 파이썬 루프를 C 최적화 NumPy 배열 연산으로 대체했습니다.

Rasterization래스터화

Implemented a scan-line algorithm logic to determine whether pixels lie within a mathematically defined triangle, manually handling anti-aliasing and edge cases.수학적으로 정의된 삼각형 내부 여부를 판단하는 스캔라인 로직을 구현하고, 안티앨리어싱 및 경계 케이스를 직접 처리했습니다.

Fractal Recursion프랙탈 재귀

Visualized chaotic behavior where simple iterative rules ($z = z^2 + c$) give rise to infinitely complex boundary structures.단순 반복 규칙(\(z = z^2 + c\))이 무한히 복잡한 경계 구조를 만들어내는 카오스 거동을 시각화했습니다.

Source Code소스 코드

1. Mandelbrot Fractal (`p5_hw5.py`)

Generates high-resolution visualizations of the Mandelbrot set.

#!/usr/bin/env python3
#before I begin, I want to say that first I will plot the mandelbrot via pyplot and then make a ps file with the exact scaling (image) of the part that I zoomed in the pyplot.

import numpy as np
import matplotlib.pyplot as plt

#function of mandelbrot

def mandelbrot(c, max_iter):
    z = 0
    for n in range(max_iter):
        if abs(z) > 2:
            return n
        z = z*z +c
    return max_iter

def mandelbrotset(xmin, xmax, ymin,ymax, width, height, max_iter):
    x = np.linspace(xmin,xmax, width)
    y = np.linspace(ymin, ymax, height)
    mset = np.zeros((height,width))
    
    for i in range(height):
        for j in range(width):
            c = complex(x[j],y[i])
            mset[i,j] = mandelbrot(c, max_iter)
    return mset

width, height = 512, 384
max_iter = 250
xmin, xmax, ymin, ymax = -0.74625,-0.73875,0.10125,0.11375

print("Generating Mandelbrot: ")
print(f"Re axis: [{xmin},{xmax}] (range: {xmax - xmin})")
print(f"Im axis: [{ymin},{ymax}] (range: {ymax - ymin})")
print(f"Grid: {width}x{height}, Max iterations: {max_iter}\n")

mandelbrot_image = mandelbrotset(xmin,xmax,ymin,ymax,width,height,max_iter)
plt.imshow(mandelbrot_image, extent=[xmin,xmax,ymin,ymax], cmap = 'hot')
plt.colorbar()
plt.title('mandelbrot visualization')
plt.xlabel('Re(c)')
plt.ylabel('Im(c)')
plt.savefig("p5_hw5.ps")
plt.show()

2. Triangle Rasterization (`p4_hw5.py`)

Low-level implementation of drawing a triangle pixel-by-pixel.

#!/usr/bin/env python3

import numpy as np
import matplotlib.pyplot as plt
from PIL import Image

X, Y = 512, 409
lw = 20
base_x1, base_y1 = 0, 0
base_x2, base_y2 = 400, 0
top_x, top_y = 400, 300
slope = 3 / 4
color = (0, 0, 255)        
bg_color = (255, 255, 255) 
offset = 48
half_lw = lw//2
total_offset = offset+half_lw
save_name = "p4_hw5_rt345_raster.tif"

hyp_thickness = int(lw/0.8) #cos of angle is 0.8)

#Setting white canvas
pvals = np.full((X, Y, 3), bg_color, dtype='uint8')

# Draw
for x in range(X):
    for y in range(Y):
        rel_x = x-total_offset
        rel_y = y-total_offset
        y_hyp = slope * rel_x
        if (0 <= rel_y <= lw) or (y_hyp - hyp_thickness <= rel_y <= y_hyp) or (top_x - lw <= rel_x <= top_x):
            if rel_y <= slope * rel_x and rel_x <= top_x and rel_y >= 0:
                pvals[x, y, :] = color

plotarr = np.flipud(pvals.transpose(1, 0, 2))
f1, ax1 = plt.subplots()
ax1.imshow(plotarr, interpolation='none')
ax1.axis('off')
plt.show()

# Save image
im = Image.fromarray(plotarr, 'RGB')
im.save(save_name)
print(f'Image saved to {save_name}')
input("\nPress Enter to exit...\n")