2015-04-27 2 views
2

Я пытаюсь создать программу, которая генерирует изображение стандартного набора Мандельброта, создавая файл .PPM. Программа не создает действительный файл PPM, и я не знаю, почему.C++ Программа Mandelbrot не даст корректного вывода

Вот мой код:

#include <fstream> 
#include <iostream> 

using namespace std; 

/* 
For each pixel (Px, Py) on the screen, do: 
{ 
    x0 = scaled x coordinate of pixel (scaled to lie in the Mandelbrot X scale (-2.5, 1)) 
    y0 = scaled y coordinate of pixel (scaled to lie in the Mandelbrot Y scale (-1, 1)) 
    x = 0.0 
    y = 0.0 
    iteration = 0 
    max_iteration = 1000 
    while (x*x + y*y < 2*2 AND iteration < max_iteration) 
    { 
     xtemp = x*x - y*y + x0 
     y = 2*x*y + y0 
     x = xtemp 
     iteration = iteration + 1 
    } 
    color = palette[iteration] 
    plot(Px, Py, color) 
} 
*/ 

int findMandelBrot(double cr, double ci, int max_iterations){ 
    int i = 0; 
    double zr = 0.0, zi = 0.0; 
    while (i > max_iterations && zr * zr + zi * zi < 4.0){ 
     double temp = zr * zr - zi * zi; 
     zi = 2.0 * zr * zi + ci; 
     zr = temp; 
     i++; 
    } 
    return i; 
} 

double mapToReal(int x, int imageWidth, double minR, double maxR){ 
    double range = maxR - minR; 

    return x * (range/imageWidth) + minR; 
} 

double mapToImaginary(int y, int imageWidth, double minI, double maxI){ 
    double range = maxI - minI; 

    return y * (range/imageWidth) + minI; 

} 

int main(){ 

ifstream fin; 
fin.open ("input.txt"); 
int imageWidth, imageHeight, maxN; 
double minR, maxR, minI, maxI; 

if (!fin.is_open()){ 
    cerr << "Couldn't load input.txt file" << endl; 
    return 0; 
} 

fin >> imageWidth >> imageHeight >> maxN; 
fin >> minR >> maxR >> minI >> maxI; 
fin.close(); 

ofstream fout("output_image.ppm"); 
fout << "P3" << endl; 
fout << imageWidth << " " << imageHeight; 
fout << "256" << endl; 

for (int y = 0; y < imageHeight; y++){ 
    for (int x = 0; x < imageWidth; x++){ 
     double cr = mapToReal(x, imageWidth, minR, maxR); 
     double ci = mapToImaginary(y, imageHeight, minI, maxI); 

     int n = findMandelBrot(cr, ci, maxN); 

     int r = (n % 256); 
     int g = (n % 256); 
     int b = (n % 256); 

     fout << r << " " << g << " " << b << " "; 
    } 
    fout.close(); 
} 
fout.close(); 
cout << "Finished! " << endl; 

cin.ignore(); 
cin.get(); 
return 0; 
} 
+1

Приведите пример входного файла. – ooga

+0

Не думайте, что ваш результат вполне соответствует спецификации PPM, см. Http://netpbm.sourceforge.net/doc/ppm.html – paisanco

+0

Что говорит вам, что это не действительный PPM-файл? –

ответ

1

Хорошее начало с отладкой для запуска программы с помощью простых входов (например, для создания выходного изображения 8x5), а затем посмотреть на выходе. Поскольку PPM легко читается человеком, вы увидите, что вы получаете только 8 образцов. Это должно быть ключом к тому, что первая строка в порядке, и есть проблема между этой и второй строкой. Теперь увеличьте масштаб до цикла строки, и вы увидите, что вы написали fout.close(), где вы хотели испустить новую строку.

Следующее, что вы заметите, это то, что все ваши значения равны нулю. Это немного сложнее диагностировать, но если вы посмотрите в findMandelBrot и пройдите в своем уме, вы перейдете в цикл while с i равным 0, и вы должны заметить, что цикл никогда не вводится.

Я немного переработал ваш код. В дополнение к исправляет ошибку, у меня есть

  • используется станд :: комплекс, а не заново изобретать колесо - посмотреть его в вашей любимой ссылке, если вы не знакомы с этим
  • предположил, что вы будете делать что-то другое с цветами, когда оно работает, или я бы упростил вывод в PGM, а не PPM.
  • добавлена ​​минимальная проверка чтения и записи файлов.
  • содержит комментарии к коду, объясняющим мои исправления.

Вот код:

#include <fstream> 
#include <iostream> 
#include <complex> 

using namespace std; 


// Converted to take a std::complex to make the arithmetic clearer 
int findMandelBrot(complex<double> c, int max_iterations) 
{ 
    int i = 0; 
    complex<double> z = 0; 
    // was while(i > max_iterations ...) which would make this always 
    // return false 
    while (i <= max_iterations && norm(z) < 4.0) { 
     z *= z; 
     z += c; 
     i++; 
    } 
    return i; 
} 

double mapToReal(int x, int imageWidth, double minR, double maxR) 
{ 
    double range = maxR - minR; 
    return x * (range/imageWidth) + minR; 
} 

double mapToImaginary(int y, int imageWidth, double minI, double maxI) 
{ 
    double range = maxI - minI; 
    return y * (range/imageWidth) + minI; 

} 

int main() 
{ 
    ifstream fin; 
    fin.open("input.txt"); 
    int imageWidth, imageHeight, maxN; 
    double minR, maxR, minI, maxI; 

    if (!fin.is_open()) { 
     cerr << "Couldn't load input.txt file" << endl; 
     return EXIT_FAILURE; 
    } 

    fin >> imageWidth >> imageHeight >> maxN; 
    fin >> minR >> maxR >> minI >> maxI; 

    // Check whether we managed to read the values 
    if (!fin) { 
     cerr << "Failed to read input.txt file" << endl; 
     return EXIT_FAILURE; 
    } 
    fin.close(); 

    ofstream fout("output_image.ppm"); 
    if (!fout) { 
     // something went wrong 
     cerr << "Couldn't open output file" << endl; 
     return EXIT_FAILURE; 
    } 
    fout << "P3" << endl; 
    fout << imageWidth << " " << imageHeight; 
    fout << " " << "256" << endl; 

    for (int y = 0; y < imageHeight; y++) { 
     for (int x = 0; x < imageWidth; x++) { 
      double cr = mapToReal(x, imageWidth, minR, maxR); 
      double ci = mapToImaginary(y, imageHeight, minI, maxI); 

      int n = findMandelBrot({cr, ci}, maxN); 

      int r = (n % 256); 
      int g = (n % 256); 
      int b = (n % 256); 

      fout << r << " " << g << " " << b << " "; 
     } 
     // was fout.close() - ending the image after first line 
     fout << endl; 

     // Periodically check for errors 
     if (!fout) { 
      // something went wrong 
      cerr << "Write failed" << endl; 
      return EXIT_FAILURE; 
     } 
    } 
    fout.close(); 

    return EXIT_SUCCESS; 
} 

Это позволит вам продолжать немного дальше.