Переменные z
c
являются В STL предусмотрен полезный класс std::complex
Как это делается
В этом примере мы выведем на консоль такое же изображение, которое было показано на рис. 6.7, в формате ASCII.
1. Сначала включим все заголовочные файлы и объявим об использовании пространства имен std
#include
#include
#include
#include
#include
#include
using namespace std;
2. Множество Мандельброта и формула работают с комплексными числами. Поэтому определим псевдоним типа cmplx
double
:using cmplx = complex
3. Вы можете скомпоновать весь код для отрисовки изображения для множества Мандельброта с помощью ASCII примерно за 20 строк кода, но мы реализуем каждый логический шаг отдельно, а затем соберем все воедино. Первый шаг — реализация функции, которая переводит координаты из целых чисел в числа с плавающей точкой. Изначально мы имеем столбцы и строки для всех позиций символов на консоли. Нужно получить координаты с типом complex
int
и возвращает координату double
.static auto scaler(int min_from, int max_from,
double min_to, double max_to)
{
const int w_from {max_from - min_from};
const double w_to {max_to - min_to};
const int mid_from {(max_from - min_from) / 2 + min_from};
const double mid_to {(max_to - min_to) / 2.0 + min_to};
return [=] (int from) {
return double(from - mid_from) / w_from * w_to + mid_to;
};
}
4. Теперь можно преобразовать точки в одном измерении, но множество Мандельброта существует в двумерной системе координат. Чтобы выполнить преобразование из одной системы координат (x, y)
scaler_x
и scaler_y
, а также создадим экземпляр типа cmplx
на основе их выходных данных.template
static auto scaled_cmplx(A scaler_x, B scaler_y)
{
return [=](int x, int y) {
return cmplx{scaler_x(x), scaler_y(y)};
};
}
5. После получения возможности преобразовывать координаты в правильные измерения можно реализовать множество Мандельброта. Функция, которую мы реализуем, сейчас ничего не знает о концепции консольных окон или линейного тангенциального преобразования, поэтому можно сконцентрироваться на математике, описывающей множество Мандельброта. Возводим в квадрат значение z
2
. Для некоторых координат это не происходит никогда, так что прерываем цикл, если будет превышено максимальное количество итераций max_iterations
. В конечном счете мы вернем количество итераций, которое успели выполнить до того, как сойдется значение по модулю.static auto mandelbrot_iterations(cmplx c)
{
cmplx z {};
size_t iterations {0};
const size_t max_iterations {1000};
while (abs(z) < 2 && iterations < max_iterations) {
++iterations;
z = pow(z, 2) + c;
}
return iterations;
}
6. Теперь можно начать с функции main
scale
, который будет масштабировать значения наших координат для обеих осей:int main()
{
const size_t w {100};
const size_t h {40};
auto scale (scaled_cmplx(
scaler(0, w, -2.0, 1.0),
scaler(0, h, -1.0, 1.0)
));