Explorateur de l'ensemble de Mandelbrot

Description

Salut

Un explorateur de l'ensemble de Mandelbrot, qui peut atteindre un zoom de 10^14,
et qui utilise le multithreading pour améliorer ses performances, tout en permettant
a l'utilisateur de choisir le niveau de details qu'il veut obtenir en plus du choix
de la resolution

N'hesitez pas a laissez vos critiques
Merci

/////////////////////////////////////////////////////
//                                                 //
//             MANDELBROT SET EXPLORER             //
//     Crée par BELAID Hocine Anis, 03/08/2016     //
//                                                 //
/////////////////////////////////////////////////////

#include <omp.h>

#include <iostream>
#include <iomanip>
#include <sstream>
#include <string>
#include <cmath>
#include <ctime>

#include "Configuration.h"

#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>

#include "Functions.h"

using namespace std;

//Fonction de la fenetre principale
int main_window(int& factor_image)
{
    int res_x(factor_image*RATIO_X), res_y(factor_image*RATIO_Y);
    double focus_x(-0.5), focus_y(0), zoom(1), actual_x(-0.5), actual_y(0), zoom_coefficient(pow(10,0.2));
    double span_x(RATIO_X*0.25), span_y(RATIO_Y*0.25);
    //Variables concernant les couleurs et leur proportions
    double var_red(0.05), var_green(0.05), var_blue(0.1), cursor_red(0.55), cursor_green(0.45),  cursor_blue(0.5);
    int iter_max(256);
    bool not_done(true), debug(true), actualize_time(true);
    sf::Clock cl;
    sf::Time render_time;

    sf::Texture buffer;
    buffer.create(res_x,res_y);

    sf::RenderWindow window(sf::VideoMode(res_x,res_y,32), "Mandelbrot set explorer", sf::Style::Close);

    //Buffer servant a manipuler l'image
    sf::Uint8 *pixels = new sf::Uint8[res_x*res_y*4];
    //Nuancier contenant les couleurs a rendre selon le nbr d'iterations
    sf::Uint8 *colors = new sf::Uint8[1024];
    //Tableau representant le nombre d'iterations de chaque pixel du buffer, avec en premiere case le nbr d'iterations max
    int *iterations_table = new int[res_x*res_y+1];
    //Remplissaque de nuancier
    fill_colors(colors,var_red,var_green,var_blue,cursor_red,cursor_green,cursor_blue);

    //remplissage des zones transparentes de l'image à l'avance
    for(int i(3);i<res_x*res_y*4;i+=4)
        pixels[i] = 255;

    //Chargement de la police
    sf::Font font;
    if(!font.loadFromFile("courbd.ttf"))
    {
        cerr << "Unable to load fonts" << endl;
        return 0;
    }

    //Remplissage du buffer
    fill_buffer(pixels,colors,iterations_table,res_x,res_y,focus_x,focus_y,span_x,span_y,iter_max);
    window.setFramerateLimit(60);

    //Boucle principale
    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            if(event.type == sf::Event::Closed)
                window.close();

            else if (sf::Mouse::isButtonPressed(sf::Mouse::Left))
            {
                //Mise a jour de l'image en fonction de la position du clic
                sf::Clock limit;
                sf::Vector2i pos = sf::Mouse::getPosition(window);
                if(pos.x>=0 && pos.x<res_x && pos.y>=0 && pos.y<res_y)
                {
                    int x_l(0), x_r(res_x), y_u(0), y_d(res_y), pos_x(pos.x - (res_x+1)/2), pos_y((res_y+1)/2 - pos.y);
                    if(pos_x!=0 && pos_y!=0)
                    {
                        if(pos_x >= 0 && pos_y >= 0)
                        {
                            x_r -= pos_x;
                            y_u += pos_y;
                        }
                        else if(pos_x < 0 && pos_y > 0)
                        {
                            x_l -= pos_x;
                            y_u += pos_y;
                        }
                        else if(pos_x < 0 && pos_y < 0)
                        {
                            x_l -= pos_x;
                            y_d += pos_y;
                        }
                        else if(pos_x > 0 && pos_y < 0)
                        {
                            x_r -= pos_x;
                            y_d += pos_y;
                        }

                        focus_x += static_cast<double>(pos.x*span_x)/res_x - span_x/2;
                        focus_y += span_y/2 - static_cast<double>(pos.y*span_y)/res_y;

                        move_buffer(pixels,res_x,res_y,-pos_x,-pos_y, iterations_table);
                        not_done = true;

                        cl.restart();
                        fill_buffer(x_l,x_r,y_u,y_d,pixels,colors,iterations_table,res_x,res_y,focus_x,focus_y,span_x,span_y,iter_max);
                    }
                }
            }
            else if (event.type == sf::Event::MouseMoved)
            {
                //Mise a jour puis affichage de la position de la souris
                sf::Vector2i pos = sf::Mouse::getPosition(window);
                if(pos.x>=0 && pos.x<res_x && pos.y>=0 && pos.y<res_y)
                {
                    actual_x = static_cast<double>(pos.x*span_x)/res_x - span_x/2 + focus_x;
                    actual_y = span_y/2 - static_cast<double>(pos.y*span_y)/res_y + focus_y;
                    not_done = true;
                    actualize_time = false;
                }
            }
            else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Add) || sf::Keyboard::isKeyPressed(sf::Keyboard::F6))
            {
                //Zoom+
                zoom*=zoom_coefficient;
                span_x = RATIO_X/(4*zoom);
                span_y= RATIO_Y/(4*zoom);

                cl.restart();
                if(iter_max > 512)
                {
                    fill_buffer(pixels,colors,iterations_table,res_x,res_y,focus_x,focus_y,span_x,span_y,512);
                    increase_iterations(pixels,colors,iterations_table,res_x,res_y,focus_x,focus_y,span_x,span_y,iter_max);
                }
                else
                    fill_buffer(pixels,colors,iterations_table,res_x,res_y,focus_x,focus_y,span_x,span_y,iter_max);
                not_done = true;
            }
            else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Subtract) || sf::Keyboard::isKeyPressed(sf::Keyboard::F5))
            {
                //Zoom-
                zoom/=zoom_coefficient;
                span_x = RATIO_X/(4*zoom);
                span_y = RATIO_Y/(4*zoom);

                cl.restart();
                if(iter_max > 512)
                {
                    fill_buffer(pixels,colors,iterations_table,res_x,res_y,focus_x,focus_y,span_x,span_y,512);
                    increase_iterations(pixels,colors,iterations_table,res_x,res_y,focus_x,focus_y,span_x,span_y,iter_max);
                }
                else
                    fill_buffer(pixels,colors,iterations_table,res_x,res_y,focus_x,focus_y,span_x,span_y,iter_max);
                not_done = true;
            }
            else if (sf::Keyboard::isKeyPressed(sf::Keyboard::R))
            {
                //Reinitialisation de la vue
                iter_max = 256;
                zoom = 1;
                span_x = RATIO_X*0.25;
                span_y = RATIO_Y*0.25;
                focus_x = -0.5;
                focus_y = 0;
                not_done = true;
                cl.restart();
                fill_buffer(pixels,colors,iterations_table,res_x,res_y,focus_x,focus_y,span_x,span_y,iter_max);
            }
            else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up) || sf::Keyboard::isKeyPressed(sf::Keyboard::F2))
            {
                //Double le nbr d'iterations
                if(iter_max<ITER_MAX_MAX)
                {
                    iter_max*=2;
                    cl.restart();
                    increase_iterations(pixels,colors,iterations_table,res_x,res_y,focus_x,focus_y,span_x,span_y,iter_max);
                    not_done = true;
                }
            }
            else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down) || sf::Keyboard::isKeyPressed(sf::Keyboard::F1))
            {
                //Divise par 2 le nbr d'iterations
                if(iter_max>=ITER_MIN)
                {
                    iter_max/=2;
                    cl.restart();
                    decrease_iterations(pixels,colors,iterations_table,res_x,res_y,focus_x,focus_y,span_x,span_y,iter_max);
                    not_done = true;
                }
            }
            else if (sf::Keyboard::isKeyPressed(sf::Keyboard::H) && debug)
            {
                //Cache le panneau d'informations
                debug = false;
                not_done = true;
                actualize_time = false;
            }
            else if (sf::Keyboard::isKeyPressed(sf::Keyboard::S) && !debug)
            {
                //Affiche les panneau d'informations
                cl.restart();
                debug = true;
                not_done = true;
                actualize_time = false;
            }
            else if (sf::Keyboard::isKeyPressed(sf::Keyboard::P))
            {
                //Ouvre la fenetre de parametres, et teste si elle renvoie une demande de redimensionnement de la fenetre pricipale
                if(set_configuration(factor_image,colors,var_red,var_green,var_blue,cursor_red,cursor_green,cursor_blue))
                {
                    cl.restart();
                    fill_buffer(pixels,colors,iterations_table,res_x,res_y,focus_x,focus_y,span_x,span_y,iter_max);
                }
                else
                {
                    //Si oui, on ferme la fenentre et on retoure dans le main
                    window.close();
                    delete [] iterations_table;
                    delete [] colors;
                    delete [] pixels;

                    return factor_image;
                }
            }
            else if (sf::Keyboard::isKeyPressed(sf::Keyboard::C))
            {
                //Screenshot
                stringstream ss;
                ss << "( " << setprecision(20) << focus_x << " , " << setprecision(20) << focus_y << " )";
                string title(ss.str());
                sf::Image im;
                im.create(res_x,res_y,pixels);
                if(im.saveToFile(ss.str()+".bmp"))
                    cout << "Screenshot saved succesfully : " << title << endl;
                else
                    cout << "Unable to save screenshot" << endl;
            }
            else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Escape))
            {
                //Fermeture de la fenetre
                window.close();
            }
        }

        if(not_done)
        {
            //Mise a jour du buffer
            buffer.update(pixels,res_x,res_y,0,0);
            buffer.setSmooth(true);
            sf::Sprite sp(buffer);
            window.clear();
            window.draw(sp);

            if(debug)
            {
                if(actualize_time)
                    render_time = cl.getElapsedTime();
                debugging(window,font,res_x,res_y,focus_x,focus_y,actual_x,actual_y,zoom,iter_max,render_time);
            }

            window.display();
            not_done = false;
            actualize_time = true;
        }
    }

    return 0;
}

int main(void)
{
    int factor_image(40), return_value;

    return_value = main_window(factor_image);

    //Si la fonction de la fenetre principale renvoie une demande de redimensionnement, on re-execute la fonction avec le parametre de reddimensionnement (return value)
    while(return_value != 0)
    {
        return_value = main_window(return_value);
    }

    return 0;
}

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.