서브젝트에서 말하는 것에 대해 먼저 알아보자면,
- 쥘리아 집합
- 망델브로 집합
- 그리고 다른 프랙탈
- 쥘리아 집합(매개변수를 마우스로만 변경/클릭없이)
- 키보드로 화면 이동
- 키보드 ESC로 종료
- 마우스 기점으로 확대/축소
- 멀티스레딩
- 색상 범위 변경
그렇다면 fractal 은 무엇인가?
일부 작은 조각이 전체와 비슷한 기하학적 형태(자기 유사성), 자기 유사성을 갖는 기하학적 구조를 프랙탈 구조라고 말한다.
이러한 것은 과학, 공학, 컴퓨터 예술에도 쓰이며 최근에는 충격을 감소를 위해 프랙탈 구조를 사용함으로써 더 많은 충격을 감소 시키는 구조로 쓰인다고 한다. 프랙탈의 분류로 보면은 시간매개형 프랙탈, 반복함수계, 기이한 끌개, 무작위적 프랙탈 로 나뉘는데, 그 중에서도 완벽한 자기유사성을 가진 것은 반복함수계(기하학적 프랙탈)이다.
위에서 말한 쥘리아 집합과 망델브로 집합은 시간 매개형 프랙탈로
쥘리아 집합은 주어진 복소수 c에 대해서 다음 점화식에 따라 정의된 수열이 발산하지 않는 성질을 갖도록 하는 복소수 z의 집합으로 정의가 되며, 망델브로 집합은 복소수 z에 대해 (주로 0부터 시작) 점화식에 따라 zn이 발산하지 않게 하는 복소수 c들의 집합이다.
쥘리아 집합과 망델브로 집합은 이러한 구조로 되어있다는 걸 알고, 이 서브젝트의 가장 중요한 것은 mlx를 사용해보라는 의미가 강하다.
cub3d에서 좌절을 맛보는 경우가 많아 이러한 서브젝트가 생겼다 생각이 들며, 그 만큼 mlx에 대해서 배워야 함을 의미한다.
mlx는 튜토리얼이 존재하는데, 해당 깃허브를 통해서 배울 수 있다.
해당 mlx.h 과 man 을 보게 되면,
MiniLibX는 그래픽 소프트웨어를 만드는 쉬운 방법입니다. 간단한 창 생성, 그리기 도구, 이미지 및 기본 이벤트 관리를 제공합니다.
void *mlx_init();
// return (void*)0 if failed
void *mlx_new_window(void *mlx_ptr, int size_x, int size_y, char *title);
// return (void*)0 if failed
int mlx_clear_window(void *mlx_ptr, void *win_ptr);
int mlx_pixel_put(void *mlx_ptr, void *win_ptr, int x, int y, int color);
// origin for x & y is top left corner of the window
// y down is positive
// color is 0x00RRGGBB
mlx_new_window () 함수는 size_x 및 size_y 매개 변수를 사용하여 크기를 결정하고 창의 제목 표시 줄에 표시 할 텍스트로 제목을 사용하여 화면에 새 창을 만듭니다. mlx_ptr 매개 변수는 mlx_init ()에서 반환하는 연결 식별자입니다.
mlx_clear_window () 및 mlx_destroy_window ()는 각각 지정된 창을 지우고 파괴합니다. mlx_ptr은 화면 연결 식별자이고 win_ptr은 창 식별자입니다.
mlx_loop ()는 이벤트를 수신(이벤트를 기다린 다음 이벤트와 관련된 사용자 정의 함수를 호출하는 무한 루프)하기 위해 사용, 마지막에 이걸 쳐줘야 프로그램이 종료하지 않고 계속 돌아간다.
mlx_key_hook (), mlx_mouse_hook () 및 mlx_expose_hook ()는 키보드, 마우스의 입력을 받는 함수이지만, man에 나와있지 않지만 int mlx_hook(void *win_ptr, int x_event, int x_mask, int (*funct)(), void *param);를 쓰게 된며, 이 함수는 x_event값에 따라 key_press, key_release, mouse클릭, 창닫기버튼 등 입력을 받을 수 있다고 한다.
mlx_int_param_KeyPress == 2
mlx_int_param_KeyRelease == 3
mlx_int_param_ButtonPress == 4
mlx_int_param_ButtonRelease == 5
더 자세한 사항
Mouse button codes
- Left button — 1
- Right button — 2
- Third (Middle) button — 3
- Scroll Up — 4
- Scroll Down — 5
- Scroll Left — 6
- Scroll Right — 7
대략적인 mlx와 키값으로 설정하는 것을 알았으니, 무언가를 구현하는 것부터 해보려고 한다.
1. ac != 2, print ERROR_Message
2. ac == 2, don't match, ERROR_Message
3. matching, create
4. mlx_init, mlx_new_window, mlx_new_image, mlx_get_data_addr, mlx_setting
5. setting, fractal_name check, create
6. color, zoom, mouse
위 목차는 머리 정리를 위해 대략적인 구조가 되고, 함수를 하나하나 쓰면서 구현을 시작한다.
언급했듯이 mlx 사용을 하면서, 진행될 것이기에 다른 사람이 보기에도 편하게 코드하나하나 설명과 순서를 기입할 예정이다.
시 ~ 작!!
1. fractol 선택창 만들기
처음 시도는 표를 그려서 만들고자 했다
void fractols_list()
{
int i;
ft_putendl("\033[01;31m\n\u23B9");
i = -1;
while (i++ < 32)
ft_putendl("\u23B4");
ft_putendl("\u23B8\n\u23B9 \033[0m");
ft_putendl("\033[07;37m fractol List \033[0m");
ft_putendl("\033[01;31m \u23B8\n\u23B9\033[0m");
ft_putendl("\033[01;32m ./fractol Julia \033[0m");
ft_putendl("\033[01;31m \u23B8\n\u23B9\033[0m");
ft_putendl("\033[01;32m ./fractol Mandelbrot \033[0m");
ft_putendl("\033[01;31m \u23B8\n\u23B9\033[0m");
ft_putendl("\033[01;32m ./fractol jaewpark \033[0m");
ft_putendl("\033[01;31m \u23B8\n\u23B9");
i = -1;
while (i++ < 32)
ft_putendl("\u23B5");
ft_putendl("\u23B8\n\033\n[0m");
}
그림과 같이 쓰기 위해서 터미널에서 아래와 같은 구조로 쓰게 되면,
"\033[07;37m fractol List \033[0m"
Reverse Character, white
"\033[01;31m fractol List \033[0m"
Bold Character, red
[ TEXT ATTRIBUTES ]
ANSI CODE Meaning
0 Normal Characters
1 Bold Characters
4 Underlined Characters
5 Blinking Characters
7 Reverse video Characters
[ Color Foreground Background ]
black | 30 | 40 |
red | 31 | 41 |
green | 32 | 42 |
yellow | 33 | 43 |
blue | 34 | 44 |
magenta | 35 | 45 |
cyan | 36 | 46 |
white | 37 | 47 |
참고 사이트 : 여기
1-1. 선택창을 mlx로 구현하기
이렇게까지 해야하나 싶었지만, 깊게 들어가면 보너스에서 구현해야 하는 부분이기에 도전을 하게 되었다
먼저 이미지를 만들어와서 선택창을 mlx로 구현을 하고자 한다.
ta = 1.958591030 - 0.011278560I;
tb = 2;
tab = 0.5(ta tb - Sqrt[ta^2tb^2 - 4(ta^2 + tb^2)]);
z0 = (tab - 2)tb/(tb tab - 2ta + 2I tab);
a = {{ta/2, (ta tab - 2tb + 4I)/(2tab + 4)/z0}, {(ta tab - 2 tb - 4I)z0/(2tab - 4), ta/2}};
A = Inverse[a];
b = 0.5{{tb - 2I, tb}, {tb, tb + 2I}};
B = Inverse[b];
ToMatrix[{z_, r_}] := I{{z, r^2 - z Conjugate[z]}, {1, -Conjugate[z]}}/r; Fix[{{a_, b_}, {c_, d_}}] := 0.5(a - d - Sqrt[4 b c + (a - d)^2])/c;
a1 = a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.B;
a2 = a.b.A.B;
c1 = ToMatrix[{0, -1}];
c2 = ToMatrix[{x + I y, r} /. Solve[Map[(Re[#] - x)^2 + (Im[#] -y)^2 == r^2 &, {Fix[a1], Fix[a2], Fix[a1.a2]}], {x, y, r}][[2]]];
Reflect[c_, a_] := a.c.Inverse[Conjugate[a]];
orbits = Join[Reverse[NestList[Reflect[#, a] &, c1, 3*15 + 8]], Drop[NestList[Reflect[#, A] &, c1, 3*15 + 6], 1], Reverse[NestList[Reflect[#, a] &, c2, 3*15 - 7]], Drop[NestList[Reflect[#, A] &, c2, 3*15 + 7],1]];
Show[Graphics[Table[{{a, b}, {c, d}} = orbits[[i]];
{Hue[i/15], Disk[-{Re[a/c], Im[a/c]}, Re[I/c]]}, {i, 1, Length[orbits]}]], AspectRatio -> Automatic, PlotRange -> All]
Element wise product or Hadamard product (아다마르 곱)
각 행렬의 원소끼리만 곱한 것을 의미한다.
일반 행렬곱은 m x n과 n x p의 꼴의 두 행렬을 곱하지만, 아다마르 곱은 m x n과 m x n의 꼴의 두 행렬을 곱한다.
http://www.bugman123.com/Fractals/index.html
http://klein.math.okstate.edu/IndrasPearls/DoubleCuspGroup/DoubleCuspGroup/
'42 Seoul' 카테고리의 다른 글
[42Seoul/minitalk] mandatory 및 개념 1편 (3) | 2021.09.24 |
---|---|
[push_swap] 정렬에 대한 공부 / 42 SEOUL (0) | 2021.09.21 |
[42Seoul] Network netwhat (0) | 2021.06.28 |
born2beroot (0) | 2021.06.22 |
[42Seoul/GNL] get next line (0) | 2021.06.12 |
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!