C++ / 콘솔로 망델브로 집합 그려보기

망델브로 집합은 다음 점화식이 발산하지 않는 복소수 c의 집합으로 정의됩니다.

\[z_{n+1}=z_{n}^{2}+c\]

여기서 ‘발산한다’라는건 n이 무한하게 증가해야만 구할 수 있지만 컴퓨터에게 무한의 개념을 적용할 순 없으므로 여기선 적당하게 계산하다가 z의 절대값이 어느 경계 밖일 때 발산한다고 합니다. 적당하게 라는건 점화식 계산의 반복 횟수인 iteration으로 사용자로부터 입력받는 값이 되고, 어느 경계라는 것은 보통 2로 알려져 있습니다(그 밖에선 항상 발산한다는 사실이 밝혀졌으므로). 그래서 iteration값이 변함에 따라 다양한 모양의 집합을 얻을 수 있습니다.

main.cpp
#include <iostream>
#include <string>
#include <complex>

using namespace std;

inline bool mandelbrot(complex<float> c, uint32_t iteration) {
	complex<float> z(0., 0.);
	while (iteration --> 0) {
		z = z * z + c;
		if (abs(z) >= 2.) return false;
	}
	return true;
}

int main() {
	const uint32_t width = 51, height = 51;
	uint32_t iteration;

	string str;
	str.reserve((2 * width + 3) * height);
	while (true) {
		cout << "iteration = ";
		cin >> iteration;

		if (iteration == 0) break;
		if (iteration > 100) {
			cout << "too high!\n";
			continue;
		}

		for (uint32_t h = 0; h < height; ++h) {
			str += "  ";
			for (uint32_t w = 0; w < width; ++w) {
				float x = 4.f * (w + 0.5f) / width - 2.f;
				float y = 4.f * (h + 0.5f) / height - 2.f;

				str += mandelbrot({x, y}, iteration) ? u8"■" : "  ";
			}
			str += '\n';
		}
		cout << str;
	}

	return 0;
}
C++

콘솔에다가 바로 출력하기 때문에 코드는 아주 간단합니다. 빌드 전에 width와 height에다가 원하는 가로 세로 픽셀을 입력하고, 실행 시에 원하는 반복 횟수(iteration)을 입력하면 됩니다. 종료하고 싶으면 반복 횟수를 0으로 하면 됩니다. 코드를 실행시켜 보면 콘솔에서 아래와 같은 출력을 얻을 수 있습니다(width, heigth = 51, iteration = 1, 2, 4, 8, 16, 32).

만약 더 좋은 해상도로 보고 싶다면 윈도우의 경우 콘솔 위로 마우스 커서를 옮기고 ctrl + 스크롤을 하면 화면 배율이 조정됩니다. 그렇게 콘솔을 최대한 작게 만들어 두고 전체화면으로 전환해서 width, height를 적당히 크게 조정하면 거의 이미지 수준의 출력을 얻을 수 있습니다(마찬가지로 iteration = 1, 2, 4, 8, 16, 32)

제 모니터 해상도에서 가능한 한 가장 크게 만들어 봤습니다(width, height = 1251, iteration = 64).

유니코드에 종류 별로 256개 존재하는 점자문자(⣝, ⣿ 등)을 사용한다면 좀 더 높은 해상도를 얻을 수 있지 않을까 합니다. 다음엔 SFML이나 SDL같은 간단한 2D 그래픽 라이브러리로 만들어 보도록 하겠습니다.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다