0. 과제 설명

mlx 라이브러리를 이용해 다양한 Fractal을 구현한다.


1. 필요 개념

Fractal

프랙탈은 일부 작은 조각이 전체와 비슷한 기하학적 형태 즉, 자기 유사성을 가지는 기하학적 구조이다. 자기 유사성은 같은 패턴에 대해 재귀 또는 반복을 이용해 구현한다.

복소 평면에서 각 점이 점화식에서 발산하는지, 발산하지 않는지에 따라 프랙탈 집합이 결정된다.

프랙탈을 더 예쁘게(자세하게) 구현하고 싶다면, 각 점이 얼마나 빠르게 발산하는 지에 따라서 색을 다르게 표현해 주면 된다.

망델브로 집합(Mandelbrot set)

\[Z_0 = 0\] \[Z_n+_1 = Z_n ^2 + C\]

위 식을 만족(수렴)하는 C의 집합.

줄리아 집합(Julia set)

망델브로 집합과 식은 같지만, 주어진 C에 대해 점화식이 수렴하는 Z의 집합이라는 점이 다르다.

불타는 배(Burning ship)

\[z_0 = 0\] \[z_{n+1} = (|Re(z_n)| + i|Im(z_n)|)^2 + c\]


Pixel

picture element의 약자로, 디지털 이미지의 가장 작은 단위.
화소라고도 부르며, 이미지를 구성하는 각 점 또는 작은 사각형으로 이해할 수 있다.

픽셀은 색상 정보를 나타내기 위해 비트로 표현된다. 8비트, 16비트, 24비트, 32비트(약 42억 색상) 등의 비트 깊이로 표현된다.

4바이트(32비트, int) 픽셀의 경우, 각 바이트는 알파 투명도(A), R, G, B 값을 나타낸다.

32비트 컴퓨터 아키텍처에서는 메모리의 주소 지정이 32비트로 이루어지기 때문에 한번에 4바이트 크기의 데이터를 처리하는 것이 효율적이고, 따라서 픽셀을 4바이트로 표현하는 것은 자연스럽다.

Byte Order(Endian)

[Byte Order 바이트 오더] 빅엔디안(Big Endian)과 리틀엔디안(little endian) - 1편

Bit Calculator

«, » : 피연산자의 비트 열을 왼쪽, 오른쪽으로 이동시킨다.


	int num = 15; // 00000000 00000000 00000000 00001111
	int result1 = num << 1; // 00000000 00000000 00000000 00011110
	int result2 = num << 2; // 00000000 00000000 00000000 00111100

	int num2 = 16; // 00000000 00000000 00000000 00010000
	int result3 = num >> 1; // 00000000 00000000 00000000 00011110
	int result4 = num >> 2; // 00000000 00000000 00000000 00001111

\& : 비트단위로 AND 연산을 한다.

0 & 0 -> 0
0 & 1 -> 0
1 & 0 -> 0
1 & 1 -> 1

int num = 15; // 00000000 00000000 00000000 00001111
int num2 = 20; // 00000000 00000000 00000000 000010100

int num3 = num1 & num2;

--> num3 = 4
** ** : 비트단위로 OR 연산을 한다.
0 | 0 -> 0
0 | 1 -> 1
1 | 0 -> 1
1 | 1 -> 1

int num = 15; // 00000000 00000000 00000000 00001111
int num2 = 20; // 00000000 00000000 00000000 000010100

int num3 = num1 | num2;

--> num3 = 1 + 2 + 4 + 8 + 16 = 31

^ : 두 개의 비트가 서로 다른 경우에 1을 반환하는 XOR 연산이다.

0 ^ 0 -> 0
1 ^ 0 -> 1
0 ^ 1 -> 1
1 ^ 1 -> 0

int num = 15; // 00000000 00000000 00000000 00001111
int num2 = 20; // 00000000 00000000 00000000 000010100

int num3 = num1 ^ num2;

--> num3 = 27

~ : 비트를 0에서 1로, 1에서 0으로 반전시키는 NOT 연산자이다. 보수 연산이라고도 불린다.

~0 --> 1
~1 --> 0

int num1 = 15; // 00000000 00000000 00000000 00001111
int num2 = ~num1;

--> num2 = -16 // 11111111 11111111 11111111 11110000

Hooking

컴퓨터 프로그래밍에서 Hooking이라는 용어는 소프트웨어 구성 요소간에 전달되는 함수 호출이나 메시지 또는 이벤트를 가로 채서 운영 체제, 응용 프로그램 또는 기타 소프트웨어 구성 요소의 동작을 변경하거나 강화하는 데 사용되는 다양한 기술을 말한다. 이러한 가로채는 함수 호출, 이벤트 또는 메시지를 처리하는 코드를 Hook이라고 한다.

exit vs return

exit()

  • exit() 함수는 프로그램을 즉시 종료시키는 기능을 한다.
  • 이 함수를 호출하면 프로그램이 즉시 종료되며, 이후의 코드는 실행되지 않는다.
  • 종료 코드(exit code)를 지정할 수 있으며, 이는 프로그램이 종료되면 운영 체제에게 전달된다.
  • 일반적으로 0은 성공적인 종료를 의미하고, 0 이외의 값은 오류를 나타낸다.
  • exit() 함수는 주로 비정상적인 상황이 발생했을 때 또는 특정 조건이 충족되었을 때 프로그램을 종료하는 데 사용된다.

    return()

  • return 구문은 함수에서 결과 값을 반환하는 용도로 사용된다.
  • 함수 내에서 return을 사용하면 함수가 값을 계산하거나 처리한 후, 그 값을 호출한 부분으로 반환한다.
  • 함수가 값을 반환하면, 호출한 부분에서 반환ㄴ된 값을 변수에 할당하거나 다른 작업에 활용할 수 있다.
  • 함수는 return을 만나면 해당 구문에서 즉시 종료되며, 이후의 코드는 실행되지 않는다.

요약하면, exit() 함수는 프로세스 자체를 종료시키는 데 사용되고, return 구문은 함수 내에서 결과값을 반환하고 함수의 실행을 제어하는 데 사용된다.



2. 구현

마우스 위치 기준으로 확대하기

복소 평면 r축의 가장 작은 값을 min_r, 확대 후 새로운 r축의 최소값(모니터에 보여지는 r축의 최소값)을 new_min_r, 확대를 하기 위한 ZOOMIN 상수를 0.9라고 하자.

마우스 포인터의 위치 x, y는 확대 전이나 확대 후나 같은 값을 가져야 한다(마우스 포인터를 기준으로 확대할 것이므로).

즉,

\[min\_r + x * dx = new\_min\_r + x * 0.9 * dx\] \[new\_min\_r = min\_r + 0.1 * x * dx\]

따라서 ZOOMIN 할 때마다

\[min\_r += 0.1 * x * dx\]


위와 같이 min_r을 업데이트 해주면 된다.

3. 시행착오

  • double로 계산해야하는 변수를 int로 선언해놔서, 이미지가 부드럽게 이어지지 않고 큼지막한 직사각형처럼 각이 졌다. → 비교적 좁은 범위에서 이미지를 디스플레이하는 경우였어서 int로 변수를 사용하면 이렇게 보였다.
  • 문자열도 header 파일에 define할 수 있다.
  • libft는 이미 makefile이 있으므로, fractol makefile을 실행할 때 libft 디렉토리로 들어가서 libft makefile을 실행시키고, 나와서 libft.a만 따로 사용해서 makefile을 구성하면 된다.
    $(NAME) : $(OBJS)
      cd libft; make; cd ..
      cc first.o second.o -Llibft -lft
    
  • 인자의 형태가 같은 함수들은 함수포인터로 묶어서 경우에 맞게 대입해 사용하면 깔끔하다.



📬 Reference

42 wiki
자바 실험실

Leave a comment