Улучшение моего кода набора Мандельброта

У меня есть следующий код набора Мандельброта в C. Я делаю расчет и создаю файл .ppm для окончательного фрактального изображения. Дело в том, что мое фрактальное изображение перевернуто, то есть повернуто на 90 градусов. Вы можете проверить это, выполнив мой код: ./mandel > test.ppm

С другой стороны, я также хочу изменить цвета. Я хочу добиться этого фрактального изображения:

введите здесь описание изображения

Моя последняя проблема заключается в том, что мой код не проверяет время выполнения моего кода. У меня тоже есть код для этой части, но когда выполнение кода завершается, время выполнения не печатается. Если кто-то может внести соответствующие изменения в мой код и помочь мне получить это фрактальное изображение и отобразить прошедшее время, я был бы рад.

#include <math.h>
#include <stdlib.h>
#include <time.h>
#include <stdio.h>

void color(int red, int green, int blue)
{
    fputc((char)red, stdout);
    fputc((char)green, stdout);
    fputc((char)blue, stdout);
}

int main(int argc, char *argv[])
{
    int w = 600, h = 400, x, y; 
    //each iteration, it calculates: newz = oldz*oldz + p, where p is the current pixel, and oldz stars at the origin
    double pr, pi;                   //real and imaginary part of the pixel p
    double newRe, newIm, oldRe, oldIm;   //real and imaginary parts of new and old z
    double zoom = 1, moveX = -0.5, moveY = 0; //you can change these to zoom and change position
    int maxIterations = 1000;//after how much iterations the function should stop

    clock_t begin, end;
    double time_spent;

    printf("P6\n# CREATOR: E.T / mandel program\n");
    printf("%d %d\n255\n",w,h);

    begin = clock();

    //loop through every pixel
    for(x = 0; x < w; x++) 
    for(y = 0; y < h; y++)
    {
        //calculate the initial real and imaginary part of z, based on the pixel location and zoom and position values
    pr = 1.5 * (x - w / 2) / (0.5 * zoom * w) + moveX;
        pi = (y - h / 2) / (0.5 * zoom * h) + moveY;
        newRe = newIm = oldRe = oldIm = 0; //these should start at 0,0
        //"i" will represent the number of iterations
        int i;
        //start the iteration process
        for(i = 0; i < maxIterations; i++)
        {
            //remember value of previous iteration
            oldRe = newRe;
            oldIm = newIm;
            //the actual iteration, the real and imaginary part are calculated
            newRe = oldRe * oldRe - oldIm * oldIm + pr;
            newIm = 2 * oldRe * oldIm + pi;
            //if the point is outside the circle with radius 2: stop
            if((newRe * newRe + newIm * newIm) > 4) break;
        }

        color(i % 256, 255, 255 * (i < maxIterations));

    }

    end = clock();

    time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
    printf("Elapsed time: %.2lf seconds.\n", time_spent);

    return 0;
}

person Community    schedule 20.04.2013    source источник


Ответы (1)


Часть 1: вам нужно поменять порядок ваших циклов на:

for(y = 0; y < h; y++)
for(x = 0; x < w; x++)

Это даст вам правильно ориентированный фрактал.

Часть 2: Чтобы получить время для печати, вы должны вывести его на стандартный вывод, так как вы печатаете вывод ppm на стандартный вывод:

fprintf(stderr, "Elapsed time: %.2lf seconds.\n", time_spent);

Часть 3: Чтобы получить непрерывную плавную окраску, вам нужно использовать метод нормализованного подсчета итераций или что-то подобное. Вот замена вашего раздела раскраски, которая дает вам что-то похожее на то, что вы хотите:

    if(i == maxIterations)
        color(0, 0, 0); // black
    else
    {
        double z = sqrt(newRe * newRe + newIm * newIm);
        int brightness = 256. * log2(1.75 + i - log2(log2(z))) / log2(double(maxIterations));
        color(brightness, brightness, 255);
    }

Это не совсем так, потому что я сделал простую приблизительную реализацию метода нормализованного подсчета итераций.

Мандельброт с полунепрерывной раскраской

Это не полностью непрерывная окраска, но она близка к ней.

person Justin Peel    schedule 20.04.2013
comment
Спасибо! Это решило мою проблему. Но есть небольшая ошибка приведения относительно круглых скобок в последней части вашего кода. Если бы вы могли исправить это ради других людей, это было бы здорово. - person ; 21.04.2013
comment
@erkant, вы имеете в виду двойное (maxIterations)? У меня отлично работает с gcc. Это что-то другое? - person Justin Peel; 21.04.2013
comment
Да, я говорил об этом. У меня это не сработало, мне пришлось использовать скобки типа ((double)maxIterations). - person ; 21.04.2013
comment
Хорошо, может быть, я использую более новый/другой компилятор, чем вы. Обычно я пишу код на C++, поэтому, возможно, раньше это не работало в C. - person Justin Peel; 21.04.2013