C:/sources/c++/buddhabrot/buddhabrot/app.cpp

Go to the documentation of this file.
00001 /*
00002 Copyright 2010 Pierre SCHWARTZ
00003 
00004 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 
00005 documentation files (the "Software"), to deal in the Software without restriction, including without 
00006 limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 
00007 of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following 
00008 conditions: The above copyright notice and this permission notice shall be included in all copies or 
00009 substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
00010 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 
00011 PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
00012 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 
00013 OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
00014 */
00015 
00024 #include <QtGui>
00025 #include <QtGui/QPushButton>
00026 #include <QtGui/QVBoxLayout>
00027 #include <QtGui/QHBoxLayout>
00028 #include <QtGui/QMainWindow>
00029 #include <QtGui/QMenu>
00030 #include <QtGui/QMessageBox>
00031 #include <QtGui/QFileDialog>
00032 #include <QtGui/QGridLayout>
00033 #include <QtGui/QDockWidget>
00034 #include <QtGui/QButtonGroup>
00035 #include <QtGui/QRadioButton>
00036 #include <QtGui/QScrollArea>
00037 
00038 #include <complex>
00039 
00040 #include "app.h"
00041 #include "colormaker.h"
00042 #include "imagecalculator.h"
00043 #include "darkbody.h"
00044 #include "grayscale.h"
00045 #include "scriptedcolormaker.h"
00046 #include "fulllinear.h"
00047 #include "fractale.h"
00048 #include "buddhabrot.h"
00049 #include "mandelbrot.h"
00050 #include "julia.h"
00051 #include "newton.h"
00052 #include "bateauenfeu.h"
00053 #include "hexamandelbrot.h"
00054 #include "tricorn.h"
00055 #include "sharingan.h"
00056 #include "networkinput.h"
00057 #include "pluginfractale.h"
00058 #include "configurationloader.h"
00059 #include "mandelbrot3d.h"
00060 #include "lightningmaker.h"
00061 
00067 App::App(QWidget *parent): QMainWindow(parent){
00068         applyStyle();
00069         
00070         collectVectorialPalets();
00071         collectPluginFractales();
00072 
00073         qsrand(0);
00074 
00075         buildUI();      
00076         connectSignals();
00077         calculatedImage = coloredImage = NULL;  
00078         isNetworkUsed = false;
00079 
00080         setCurrentWindow(buddhabrot::getBestWindow());
00081 }
00082 
00087 App::~App(){
00088         if (coloredImage)
00089                 delete coloredImage;
00090         if (calculatedImage)
00091                 delete calculatedImage;
00092         if (renderingImage)
00093                 delete renderingImage;
00094 
00095         for (QMap<QString, fractale*>::iterator i = pluginFractales.begin(); i!=pluginFractales.end(); i++)
00096                 delete i.value();
00097 }
00098 
00102 void App::connectSignals(){
00103         // évènements double clic pour zoomer/dézoomer
00104         QObject::connect(renderingImage, SIGNAL(zoom(int, int)), this, SLOT(s_zoom(int, int)));
00105         QObject::connect(renderingImage, SIGNAL(unzoom(int, int)), this, SLOT(s_unzoom(int, int)));
00106         QObject::connect(renderingImage, SIGNAL(move(int, int)), this, SLOT(s_displayRealCoordinates(int, int)));
00107 
00108         // lancement global de génération
00109         QObject::connect(calculateButton, SIGNAL(clicked()), this, SLOT(s_generate()));
00110 
00111         // mise à jour de la progressbar
00112         QObject::connect(this, SIGNAL(processFinishing(int)), bar, SLOT(setValue(int)));
00113 
00114         // boutons de coloration
00115         QObject::connect(darkBodyBtn,   SIGNAL(clicked()), this, SLOT(s_colorate_darkBody()));
00116         QObject::connect(grayBtn,               SIGNAL(clicked()), this, SLOT(s_colorate_gray()));
00117         QObject::connect(fullBtn,               SIGNAL(clicked()), this, SLOT(s_colorate_full()));
00118 
00119         // combobox
00120         QObject::connect(fractalType,           SIGNAL(currentIndexChanged  (int)), this, SLOT(s_changeFractale(int)));
00121 
00122         // QRadio
00123         QObject::connect(parPointsAleatoires,           SIGNAL(toggled (bool)), this, SLOT(s_displayPointsAleatoires(bool)));
00124 
00125         // network
00126         QObject::connect(useNetwork,    SIGNAL(clicked (bool)), this, SLOT(s_enableNetwork(bool)));
00127         QObject::connect(clearNetwork,  SIGNAL(clicked ()), this, SLOT(s_deleteLastNetwork()));
00128         QObject::connect(addNetwork,    SIGNAL(clicked()), this, SLOT(s_addNetwork()));
00129 }
00130 
00134 void App::buildUI(){
00135         setWindowTitle(tr("DVP Générateur de fractales"));
00136         setWindowIcon(QIcon("data/qt.ico"));    
00137 
00138         // créer la barre de menu
00139         createActions();
00140         createMenu();
00141 
00142         // barre d'état
00143         statusBar = QMainWindow::statusBar();
00144         statusBarLabel = new QLabel();  
00145         statusBar->addPermanentWidget(statusBarLabel, 200);
00146         statusBar->show();
00147 
00148         // création des widgets. une progressbar, une combo de choix de fractale, des boutons de coloration
00149         renderingImage = new ZoomableImage();
00150         fractalType = new QComboBox();
00151         fractalType->setToolTip(tr("Choix de la fractale à calculer"));
00152         fractalType->addItem("BuddhaBrot", 0);  
00153         fractalType->addItem("MultiBrot", 1);           
00154         fractalType->addItem("MandelBrot", 2);  
00155         fractalType->addItem("Julia (0.285)", 3);       
00156         fractalType->addItem("Julia (-0.038088 + 0.9754633i)", 4);
00157         fractalType->addItem("Newton", 5);                      
00158         fractalType->addItem("Bateau en feu", 6);       
00159         fractalType->addItem("Tricorn", 7);             
00160         fractalType->addItem("Sharingan", 8);   
00161         fractalType->addItem("MandelBrot3D", 9);        
00162 
00163         // ajouter les fractales plugguées
00164         int lastIndex = 10;
00165         for (QMap<QString, fractale*>::iterator i = pluginFractales.begin(); i!=pluginFractales.end(); i++, lastIndex++){
00166                 fractalType->addItem(i.key(), lastIndex);
00167         }
00168 
00169         // le bouton pour démarrer la génération de la fractale
00170         calculateButton = new QPushButton(tr("Calculer"));      
00171         calculateButton->setToolTip(tr("Lancer le calcul"));
00172         
00173         bar = new QProgressBar();
00174         bar->setVisible(false);         // la barre n'est visible que quand elle est utile      
00175 
00176         // création des layouts pour positionner les widgets à l'écran, rien de bien compliqué
00177         QVBoxLayout *mainLayout = new QVBoxLayout();    
00178         QHBoxLayout *hlayout = new QHBoxLayout();
00179 
00180         // spinbox du choix du nombre d'itérations 
00181         iterations = new QSpinBox();    
00182         iterations->setMaximum(10000);
00183         iterations->setMinimum(10);
00184         iterations->setSingleStep(10);  
00185         iterations->setValue(70);
00186         iterations->setToolTip(tr("Taille maximale des séries fractales"));
00187 
00188         // choix de la résolution de sortie
00189         sizes = new QComboBox();
00190         sizes->setToolTip(tr("Résolution de l'image résultat"));
00191         
00192         QWidget *hlayoutWidget = new QWidget();
00193         hlayoutWidget->setLayout(hlayout);
00194         hlayout->addWidget(new QLabel(tr("Itérations")));
00195         hlayout->addWidget(iterations);
00196         hlayout->addWidget(sizes);
00197                 sizes->addItem("128x128", 128);
00198                 sizes->addItem("256x256", 256);
00199                 sizes->addItem("512x512", 512);
00200                 sizes->addItem("1024x1024", 1024);
00201                 sizes->addItem("2048x2048", 2048);
00202                 hlayout->addWidget(fractalType);
00203                 hlayout->addWidget(calculateButton);
00204                 hlayout->setSizeConstraint(QLayout::SetFixedSize);
00205         mainLayout->addWidget(hlayoutWidget);
00206         
00207         // coche pour animer la génération ou non       
00208         showAnimation = new QCheckBox(tr("Animer la génération"));      
00209         showAnimation->setChecked(false);
00210         showAnimation->setVisible(false);
00211 
00212         mainLayout->addWidget(showAnimation);
00213         mainLayout->addWidget(bar);
00214 
00215         QScrollArea *area = new QScrollArea();
00216         area->setWidget(renderingImage);
00217         renderingImage->hide();
00218         mainLayout->addWidget(area);
00219 
00220         // créer la zone de coloration
00221         colorationWidget = new QWidget();
00222         QGridLayout *colorationLayout = new QGridLayout();      
00223                 darkBodyBtn = new QPushButton(tr("DarkBody"));
00224                 darkBodyBtn->setStyleSheet("QWidget{ background-image: url(data/images/darkBody.png); background-repeat:repeat-y;}");           
00225                 
00226                 grayBtn = new QPushButton(tr("Niveau de gris"));
00227                 grayBtn->setStyleSheet("QWidget{ background-image: url(data/images/gray.png); background-repeat:repeat-y;}");           
00228                 
00229                 fullBtn = new QPushButton(tr("Full linear"));
00230                 fullBtn->setStyleSheet("QWidget{ background-image: url(data/images/fullLinear.png); background-repeat:repeat-y;}");             
00231                 
00232         colorationLayout->addWidget(darkBodyBtn);
00233         colorationLayout->addWidget(grayBtn);
00234         colorationLayout->addWidget(fullBtn);
00235         colorationButtons.push_back(darkBodyBtn);
00236         colorationButtons.push_back(grayBtn);
00237         colorationButtons.push_back(fullBtn);
00238 
00239         // ajouter toutes les palettes dynamiques
00240         for ( QStringList::Iterator it = palettesListe.begin(); it != palettesListe.end(); ++it ) {
00241                 QPushButton *b = new QPushButton(*it);
00242                 
00243                 // si un png du même nom existe, on le place en style
00244                 QTextCodec::setCodecForCStrings(QTextCodec::codecForName("IBM 850"));
00245                 QString filename = "data/palettes/%1.png";              
00246                 filename = filename.arg(*it);
00247                 if (QFile::exists(filename)){
00248                         QString style = QString("QWidget{ background-image: url(%1); background-repeat:repeat-y;}").arg(filename);
00249                         b->setStyleSheet(style);
00250                 }
00251                 
00252                 colorationButtons.push_back(b);
00253                 QObject::connect(b, SIGNAL(clicked()), this, SLOT(s_run_dynamic_coloration()));
00254                 colorationLayout->addWidget(b);
00255         }
00256         // on disable tous les boutons de coloration présents
00257         enableColorationButtons(false);
00258 
00259         colorationWidget->setLayout(colorationLayout);
00260 
00261         // dock de coloration
00262         dockColoration = new QDockWidget(tr("Coloration"));
00263         dockColoration->setFeatures(QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable);
00264         addDockWidget(Qt::RightDockWidgetArea, dockColoration);
00265         dockColoration->setWidget(colorationWidget);
00266 
00267         // dock de fenêtrage
00268         windowDock = new QDockWidget(tr("Fenêtrage"));
00269         windowDock->setFeatures(QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable);
00270         
00271         QGridLayout *g = new QGridLayout();
00272         windowX1 = new QLineEdit();     windowX1->setInputMask(QString("#00.000"));     windowX1->setMaxLength(8); windowX1->setAlignment(Qt::AlignCenter);
00273         windowY1 = new QLineEdit();     windowY1->setInputMask(QString("#00.000"));     windowY1->setMaxLength(8); windowY1->setAlignment(Qt::AlignCenter);
00274         windowX2 = new QLineEdit(); windowX2->setInputMask(QString("#00.000")); windowX2->setMaxLength(8); windowX2->setAlignment(Qt::AlignCenter);
00275         windowY2 = new QLineEdit(); windowY2->setInputMask(QString("#00.000")); windowX2->setMaxLength(8); windowY2->setAlignment(Qt::AlignCenter);
00276         g->addWidget(windowY1, 0, 1);
00277         g->addWidget(windowY2, 2, 1);
00278         g->addWidget(windowX1, 1, 0);
00279         g->addWidget(windowX2, 1, 2);
00280         windowY1->setToolTip(tr("Borne complexe inférieure"));
00281         windowY2->setToolTip(tr("Borne complexe supérieure"));
00282         windowX1->setToolTip(tr("Borne réelle inférieure"));
00283         windowX2->setToolTip(tr("Borne réelle supérieure"));
00284         QWidget *ww = new QWidget();
00285         ww->setLayout(g);
00286         windowDock->setWidget(ww);
00287         
00288         addDockWidget(Qt::RightDockWidgetArea, windowDock);
00289 
00290         // dock d'itérations
00291         iterationsDock = new QDockWidget(tr("Itérations"));
00292         iterationsDock->setFeatures(QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable);
00293         addDockWidget(Qt::RightDockWidgetArea, iterationsDock);
00294         QWidget *www = new QWidget();
00295         QVBoxLayout *vb = new QVBoxLayout();
00296         
00297         QButtonGroup *group = new QButtonGroup();
00298         parPointsAleatoires = new QRadioButton(tr("Par points aléatoires"));    
00299         parPixel = new QRadioButton(tr("Par points pixels"));
00300         parPixel->setChecked(true);
00301 
00302         group->addButton(parPointsAleatoires);
00303         group->addButton(parPixel);
00304         aleatoiresPoints = new QSpinBox();
00305         aleatoiresPoints->setMinimum(10000);
00306         aleatoiresPoints->setMaximum(1000000000);       
00307         aleatoiresPoints->setSingleStep(10000);
00308         aleatoiresPoints->hide();
00309 
00310         vb->setSizeConstraint(QLayout::SetMinimumSize);
00311         vb->addWidget(parPixel);
00312         vb->addWidget(parPointsAleatoires);
00313         vb->addWidget(aleatoiresPoints);
00314 
00315         www->setLayout(vb);
00316         iterationsDock->setWidget(www);
00317 
00318         // paramétrage du rendu réseau
00319         QDockWidget *networkDock = new QDockWidget(tr("Réseau"));
00320         networkDock->setFeatures(QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable);
00321         addDockWidget(Qt::RightDockWidgetArea, networkDock);    
00322         QWidget *wwww = new QWidget();
00323         vbnetworkDock = new QVBoxLayout();
00324 
00325         useNetwork = new QCheckBox(QString(tr("Utiliser les agents réseau")));
00326 
00327         vbnetworkDock->addWidget(useNetwork);
00328         QHBoxLayout *networkHLayout = new QHBoxLayout();
00329 
00330         addNetwork = new QPushButton(QString(tr("Ajouter un agent réseau")));
00331         networkHLayout->addWidget(addNetwork);
00332         clearNetwork = new QPushButton(QString(tr("Supprimer")));
00333         networkHLayout->addWidget(clearNetwork);
00334         QWidget *networkHLayoutWidget = new QWidget();
00335         networkHLayoutWidget->setLayout(networkHLayout); 
00336 
00337         vbnetworkDock->addWidget(networkHLayoutWidget);
00338         NetworkInput *n = new NetworkInput();
00339         QObject::connect(n, SIGNAL(message(const QString&)), this, SLOT(s_receiveMessageFromNetwork(QString&)));
00340         networkAddresses.append(n);
00341         vbnetworkDock->addWidget(n);
00342 
00343         wwww->setLayout(vbnetworkDock);
00344         networkDock->setWidget(wwww);
00345         s_enableNetwork(false);
00346 
00347 
00348         // zone de rendu
00349         QWidget *renderingWidget = new QWidget();               
00350         renderingWidget->setLayout(mainLayout); 
00351         setCentralWidget(renderingWidget);      
00352 }
00353 
00358 void App::enableColorationButtons(bool b){
00359         QList<QPushButton*>::iterator i = colorationButtons.begin();
00360         while (i != colorationButtons.end()){
00361                 (*i)->setDisabled(!b);
00362                 i++;
00363         }
00364 }
00365 
00370 void App::s_displayRealCoordinates(int x, int y){
00371         float fx = currentWindow.left() + x* (currentWindow.width() / currentSize.width());
00372         float fy = currentWindow.top() + y* (currentWindow.height() / currentSize.height());
00373 
00374         statusBarLabel->setText(QString(tr("(%1,%2)")).arg(fx).arg(fy));
00375 }
00376 
00381 void App::applyStyle(){
00382         QFile file("data/style.qss");
00383     file.open(QFile::ReadOnly);
00384     QString styleSheet = QLatin1String(file.readAll());
00385         setStyleSheet(styleSheet);
00386 }
00391 void App::collectVectorialPalets(){     
00392         QDir dir("data/palettes");
00393         QStringList filters;
00394         filters << "*.js";
00395         dir.setNameFilters(filters);
00396         
00397         QFileInfoList list = dir.entryInfoList();
00398         for (int i = 0; i < list.size(); ++i) {         
00399                 QFileInfo fileInfo = list.at(i);
00400                 QString fname = fileInfo.fileName();
00401 
00402                 // oublier l'extension .js
00403                 fname.truncate(fname.size()-3);
00404                 
00405                 palettesListe.append(fname);            
00406         }
00407 }
00408 
00413 void App::collectPluginFractales(){
00414         QDir pluginsDir = QDir("data/fractales");
00415     foreach (QString fileName, pluginsDir.entryList(QDir::Files)) {
00416         QPluginLoader loader(pluginsDir.absoluteFilePath(fileName));
00417         QObject *plugin = loader.instance();
00418         if (plugin) {
00419             pluginfractale * op = qobject_cast<pluginfractale*>(plugin);
00420             if (op) {
00421                                 pluginFractales[op->getName()] =op;
00422             }
00423         }
00424     }
00425 }
00426 
00427 
00431 void App::createActions(){      
00432         saveAct = new QAction(tr("&Sauver..."), this);
00433         saveAct->setShortcut(tr("Ctrl+S"));
00434         saveAct->setIcon(QIcon::fromTheme(QString(""), QIcon("data/icons/document-save.png")));
00435         connect(saveAct, SIGNAL(triggered()), this, SLOT(save()));
00436 
00437         loadConfigAct = new QAction(tr("Charger un paramétrage..."), this);
00438         loadConfigAct->setIcon(QIcon::fromTheme(QString(""), QIcon("data/icons/param-load.png")));
00439         connect(loadConfigAct, SIGNAL(triggered()), this, SLOT(s_loadConfig()));
00440 
00441         saveConfigAct = new QAction(tr("Sauvegarder le paramétrage..."), this);
00442         saveConfigAct->setIcon(QIcon::fromTheme(QString(""), QIcon("data/icons/param-save.png")));
00443         connect(saveConfigAct, SIGNAL(triggered()), this, SLOT(s_saveConfig()));
00444 
00445         quitAct = new QAction(tr("&Quitter..."), this);
00446         quitAct->setIcon(QIcon::fromTheme(QString(""), QIcon("data/icons/quit.png")));
00447         connect(quitAct, SIGNAL(triggered()), this, SLOT(close()));
00448 
00449         aboutAct = new QAction(tr("&A propos..."), this);
00450         aboutAct->setIcon(QIcon::fromTheme(QString(""), QIcon("data/icons/about.png")));
00451         connect(aboutAct, SIGNAL(triggered()), this, SLOT(about()));
00452 }
00456 void App::createMenu(){ 
00457         QMenu *fileMenu = new QMenu(tr("&Fichier"), this);
00458         fileMenu->addAction(saveAct);
00459         fileMenu->addAction(loadConfigAct);
00460         fileMenu->addAction(saveConfigAct);
00461         fileMenu->addAction(quitAct);
00462 
00463         QMenu *aboutMenu = new QMenu("?", this);
00464         aboutMenu->addAction(aboutAct);
00465 
00466         menuBar()->addMenu(fileMenu);
00467         menuBar()->addMenu(aboutMenu);
00468 }
00469 
00473 void App::save(){
00474         QString fileName = QFileDialog::getSaveFileName(this,
00475                                      tr("Enregistrer le rendu"), QDir::currentPath(), QString(tr("Images PNG (*.png)")));
00476 
00477         if (!fileName.isEmpty())        
00478                 renderingImage->pixmap()->save(fileName);
00479 }
00480 
00484 void App::about(){
00485         QMessageBox::about(this, tr("A propos"), tr("Fruit de plusieurs semaines de travail, ce programme est ma modeste participation au Défi Qt de Developpez.com"));
00486 }
00487 
00488 
00489 
00493 void App::generateStartFractaleWindows(){
00494         int fractaleType = fractalType->itemData(fractalType->currentIndex()).value<int>();
00495 
00496         switch(fractaleType){
00497                 case 0 : 
00498                         generateBuddhaBrot(); 
00499                         break;
00500                 case 2 : 
00501                         generateMandelBrot();
00502                         break;
00503                 case 3 : 
00504                         generateJulia(std::complex<float>(.285f,0));
00505                         break;
00506                 case 4 : 
00507                         generateJulia(std::complex<float>(-0.038088f, 0.9754633f));
00508                         break;
00509                 case 5 : 
00510                         generateNewton();
00511                         break;
00512                 case 6 : 
00513                         generateBateauEnFeu();
00514                         break;
00515                 case 1 : 
00516                         generateHexaMandelBrot();
00517                         break;
00518                 case 7 : 
00519                         generateTricorn();
00520                         break;
00521                 case 8 : 
00522                         generateSharingan();
00523                         break;
00524                 case 9:
00525                         generateMandel3D();
00526                         break;
00527                 default:
00528                         // plugged fractale
00529                         QString name = fractalType->itemText(fractalType->currentIndex());
00530                         generatePlugged(name);
00531                         break;
00532         }
00533 }
00534 
00538 void App::s_generate(){
00539         // collecter les données de fenêtrage
00540         float x1 = windowX1->text().toFloat();
00541         float x2 = windowX2->text().toFloat();
00542         float y1 = windowY1->text().toFloat();
00543         float y2 = windowY2->text().toFloat();
00544 
00545         currentWindow = QRectF(x1,y1,x2-x1,y2-y1); 
00546 
00547         generateStartFractaleWindows();
00548 }
00549 
00553 void App::s_loadConfig(){
00554         QString fileName = QFileDialog::getOpenFileName(this, tr("Ouvrir un paramétrage"), QDir::currentPath(), QString(tr("Paramétrage (*.dvp)")));
00555         if (!fileName.isEmpty()){
00556                 ConfigurationLoader config(fileName);
00557                 
00558                 iterations->setValue(config.getIterations());
00559                 
00560                 useNetwork->setCheckState(config.getUseNetwork()?Qt::Checked:Qt::Unchecked);
00561                 parPixel->setChecked(!config.getUseRandom());
00562                 parPointsAleatoires->setChecked(config.getUseRandom());
00563                 aleatoiresPoints->setValue(config.getRandomCount());
00564 
00565                 windowX1->setText(QString("%1").arg(config.getWindow().left()));
00566                 windowX2->setText(QString("%1").arg(config.getWindow().right()));
00567                 windowY1->setText(QString("%1").arg(config.getWindow().top()));
00568                 windowY2->setText(QString("%1").arg(config.getWindow().bottom()));
00569 
00570                 setNetworkList(config.getNetworkAgents());
00571         }
00572 }
00573 
00577 void App::s_saveConfig(){
00578         QString filename = QFileDialog::getSaveFileName(this, tr("Sauvegarder un paramétrage"), QDir::currentPath(), QString(tr("Paramétrage (*.dvp)")));
00579         
00580         ConfigurationLoader config;     
00581                         
00582         config.setIterations(iterations->text().toLong());
00583         config.setRandomCount(aleatoiresPoints->text().toLong());
00584         config.setUseNetwork(useNetwork->checkState() == Qt::Checked);
00585         config.setUseRandom(parPointsAleatoires->isChecked());
00586         
00587         QRectF window(windowX1->text().toFloat(), windowY1->text().toFloat(), 
00588                 windowX2->text().toFloat() - windowX1->text().toFloat(),
00589                 windowY2->text().toFloat() - windowY1->text().toFloat());
00590         config.setWindow(window);
00591         config.setNetworkAgents(collectNetworkAgents());
00592 
00593         config.save(filename);  
00594         
00595 }
00596 
00600 void App::setCurrentWindow(QRectF& r){
00601         windowX1->setText(QString("%1" ).arg(r.left()));
00602         windowX2->setText(QString("%1" ).arg(r.right()));
00603         windowY1->setText(QString("%1" ).arg(r.top()));
00604         windowY2->setText(QString("%1" ).arg(r.bottom()));
00605 }
00606 
00610 void App::s_changeFractale(int type){
00611         switch(type){
00612                 case 0:
00613                         setCurrentWindow(buddhabrot::getBestWindow());
00614                         break;
00615                 case 1:
00616                         setCurrentWindow(hexamandelbrot::getBestWindow());
00617                         break;
00618                 case 2:
00619                         setCurrentWindow(mandelbrot::getBestWindow());
00620                         break;
00621                 case 3:
00622                 case 4:
00623                         setCurrentWindow(julia::getBestWindow());
00624                         break;
00625                 case 5:
00626                         setCurrentWindow(newton::getBestWindow());
00627                         break;
00628                 case 6:
00629                         setCurrentWindow(bateauEnFeu::getBestWindow());
00630                         break;
00631                 case 7:
00632                         setCurrentWindow(tricorn::getBestWindow());
00633                         break;
00634                 case 8:
00635                         setCurrentWindow(sharingan::getBestWindow());
00636                         break;
00637                 case 9:
00638                         setCurrentWindow(mandelbrot::getBestWindow());
00639                         break;
00640         }
00641 }
00642 
00646 void App::generateBuddhaBrot(){ 
00647         buddhabrot b(std::complex<float>(), iterations->value());
00648         generateFractale(b);
00649 }
00650 
00654 void App::generateMandel3D(){
00655         if (calculatedImage != NULL)
00656                 delete calculatedImage;
00657 
00658         threeDrendering.clear();
00659 
00660         int resolution = sizes->itemData(sizes->currentIndex()).value<int>();
00661         currentSize = QSize(resolution,resolution);
00662 
00663         renderingImage->setMinimumHeight(resolution);
00664         renderingImage->setMaximumHeight(resolution);
00665         renderingImage->setMinimumWidth(resolution);
00666         renderingImage->setMaximumWidth(resolution);
00667 
00668         bar->setVisible(true);
00669         calculatedImage = new QImage(currentSize, QImage::Format_RGB888);
00670 
00671         // mettre l'image en noir
00672         calculatedImage->fill(QColor(0,0,0).rgb());
00673 
00674         // collecter les données de fenêtrage
00675         float x1 = windowX1->text().toFloat();
00676         float x2 = windowX2->text().toFloat();
00677         float y1 = windowY1->text().toFloat();
00678         float y2 = windowY2->text().toFloat();
00679 
00680         currentWindow = QRectF(x1,y1,x2-x1,y2-y1); 
00681 
00682         MandelBrot3d mandel(threeDrendering, normalMap, calculatedImage, currentWindow, resolution, iterations->value());
00683         QObject::connect(&mandel, SIGNAL(progress(int)), bar, SLOT(setValue(int)));
00684 
00685         maxValue = mandel.process();
00686 
00687         // appeler l'éclairage par défaut
00688         if (coloredImage != NULL)
00689                 delete coloredImage;
00690         coloredImage = new QImage(currentSize, QImage::Format_RGB888);
00691         
00692         runLightning();
00693 
00694         renderingImage->setPixmap(QPixmap::fromImage(*coloredImage));
00695         coloredImage->save("colored.bmp");
00696 
00697         s_colorate_gray();
00698 
00699         renderingImage->show();
00700         calculatedImage->save("./result.bmp");
00701 
00702         bar->setVisible(false);
00703 
00704         enableColorationButtons(true);
00705         statusBarLabel->setText("");
00706 }
00707 
00711 void App::generatePlugged(QString& name){
00712         fractale *f = pluginFractales[name];
00713         f->setMaxIterations(iterations->value());
00714         generateFractale(*f);
00715 }
00716 
00720 void App::generateHexaMandelBrot(){     
00721         hexamandelbrot b(std::complex<float>(), iterations->value());
00722         generateFractale(b);
00723 }
00724 
00728 void App::generateMandelBrot(){ 
00729         mandelbrot b(std::complex<float>(), iterations->value());
00730         generateFractale(b);
00731 }
00735 void App::s_run_dynamic_coloration(){
00736         QObject *from = sender();
00737         QPushButton * button = qobject_cast<QPushButton*>(from);
00738 
00739         QString paletteName = button->text();
00740 
00741         scriptedColorMaker d(1000, paletteName);
00742         colorate(d);
00743 }
00744 
00748 void App::generateNewton(){     
00749         newton b(std::complex<float>(), iterations->value());
00750         generateFractale(b);
00751 }
00752 
00756 void App::generateJulia(std::complex<float> c){
00757         julia b(c, iterations->value());
00758         generateFractale(b);
00759 }
00760 
00764 void App::generateBateauEnFeu(){
00765         bateauEnFeu b(std::complex<float>(), iterations->value());
00766         generateFractale(b);
00767 }
00771 void App::generateTricorn(){
00772         tricorn b(std::complex<float>(), iterations->value());
00773         generateFractale(b);
00774 }
00775 
00779 void App::generateSharingan(){
00780         sharingan b(std::complex<float>(), iterations->value());
00781         generateFractale(b);
00782 }
00783 
00784 
00791 void App::generateFractale(fractale &f){
00792         // collecter les infos de config
00793         QRectF rect = currentWindow;
00794         int resolution = sizes->itemData(sizes->currentIndex()).value<int>();
00795         currentSize = QSize(resolution,resolution);
00796 
00797         renderingImage->setMinimumHeight(currentSize.height());
00798         renderingImage->setMaximumHeight(currentSize.height());
00799         renderingImage->setMinimumWidth(currentSize.width());
00800         renderingImage->setMaximumWidth(currentSize.width());
00801 
00802         bar->setVisible(true);
00803         if (calculatedImage != NULL)
00804                 delete calculatedImage;
00805         calculatedImage = new QImage(currentSize, QImage::Format_RGB888);
00806 
00807         // mettre l'image en noir
00808         calculatedImage->fill(QColor(0,0,0).rgb());     
00809 
00810         // trouver combien de threads il faut lancer
00811         int nbThreads = QThread::idealThreadCount();
00812         if (nbThreads <= 0)
00813                 nbThreads = 1;
00814 
00815         // agents réseau ?
00816         QStringList networkAgentsList = collectNetworkAgents();
00817 
00818         if (networkAgentsList.count() == 0)
00819                 statusBarLabel->setText(QString(tr("%1 thread(s) en cours ...")).arg(nbThreads));
00820         else
00821         if (networkAgentsList.count() == 1)
00822                 statusBarLabel->setText(QString(tr("%1 thread(s) en cours + 1 agent réseau...")).arg(nbThreads));
00823         else
00824                 statusBarLabel->setText(QString(tr("%1 thread(s) en cours + %2 agents réseau...")).arg(nbThreads).arg(networkAgentsList.count()));
00825                 
00826         enableColorationButtons(false);
00827 
00828         bool type = parPointsAleatoires->isChecked();
00829         long nbRandom = aleatoiresPoints->value() / nbThreads;
00830 
00831         ImageCalculator ic(nbThreads, calculatedImage, rect, currentSize, f, type, nbRandom, showAnimation->isChecked(), networkAgentsList);
00832         QObject::connect(&ic, SIGNAL(progress(int)), bar, SLOT(setValue(int)));
00833         QObject::connect(&ic, SIGNAL(render()), this, SLOT(s_render()));
00834         ic.run();
00835         ic.wait();
00836         maxValue = ic.maxValue;
00837 
00838         // rendu + sauvegarde auto
00839         renderingImage->setPixmap(QPixmap::fromImage(*calculatedImage).scaled(renderingImage->size(),Qt::IgnoreAspectRatio, Qt::FastTransformation));
00840         calculatedImage->save("./result.bmp");
00841 
00842         bar->setVisible(false);
00843         showAnimation->setVisible(true);
00844 
00852         s_colorate_gray();
00853         colorationWidget->setVisible(true);
00854         renderingImage->show();
00855         enableColorationButtons(true);
00856         statusBarLabel->setText("");
00857 }
00858 
00862 void App::s_zoom(int x, int y){
00863         // obtenir les coordonnées réelles cliquées
00864         QPointF center ( currentWindow.left() + float(x) * currentWindow.width() / currentSize.width(), 
00865                                         currentWindow.top() + float(y) * currentWindow.height() / currentSize.height()
00866                                         );
00867         
00868         currentWindow = QRectF(center.x() - currentWindow.width()/4, 
00869                                                         center.y() - currentWindow.height()/4,
00870                                                         currentWindow.width()/2,
00871                                                         currentWindow.height()/2
00872                                                         );
00873         setCurrentWindow(currentWindow);
00874         
00875         s_generate();
00876         //generateStartFractaleWindows();
00877 }
00878 
00882 void App::s_unzoom(int x, int y){
00883         // obtenir les coordonnées réelles cliquées
00884         QPointF center ( currentWindow.left() + float(x) * currentWindow.width() / currentSize.width(), 
00885                                         currentWindow.top() + float(y) * currentWindow.height() / currentSize.height()
00886                                         );
00887         
00888         currentWindow = QRectF(center.x() - currentWindow.width(), 
00889                                                         center.y() - currentWindow.height(),
00890                                                         currentWindow.width()*2,
00891                                                         currentWindow.height()*2
00892                                                         );
00893         setCurrentWindow(currentWindow);
00894         
00895         s_generate();
00896         //generateStartFractaleWindows();
00897 }
00898 
00902 void App::s_render(){
00903         renderingImage->setPixmap(QPixmap::fromImage(*calculatedImage).scaled(renderingImage->size(),Qt::IgnoreAspectRatio, Qt::FastTransformation));
00904         
00905         if (showAnimation->checkState() == Qt::Checked)
00906                 s_colorate_gray();
00907 }
00908 
00912 void App::s_colorate_darkBody(){
00913         darkBody d(1000);
00914         colorate(d);
00915 }
00916 
00920 void App::s_colorate_gray(){
00921         grayScale d(1000);
00922         colorate(d);
00923 }
00924 
00928 void App::s_colorate_full(){
00929         fullLinear d(100);
00930         colorate(d);
00931 }
00932 
00936 void App::s_displayPointsAleatoires(bool b){
00937         if (b)
00938                 aleatoiresPoints->show();
00939         else
00940                 aleatoiresPoints->hide();
00941 }
00942 
00946 void App::s_enableNetwork(bool b){
00947         addNetwork->setDisabled(!b);
00948         clearNetwork->setDisabled(!b);
00949         isNetworkUsed = b;
00950 }
00951 
00952 
00956 void App::s_deleteLastNetwork(){
00957         if (networkAddresses.length() > 0){
00958                 NetworkInput*e = networkAddresses.last();
00959                 networkAddresses.pop_back();
00960                 delete e;
00961         }
00962 }
00963 
00967 void App::s_receiveMessageFromNetwork(QString& s){
00968         statusBar->showMessage(s);
00969 }
00970 
00974 void App::s_addNetwork(){
00975         NetworkInput *n = new NetworkInput();
00976         networkAddresses.append(n);
00977         vbnetworkDock->addWidget(n);
00978         QObject::connect(n, SIGNAL(message(QString&)), this, SLOT(s_receiveMessageFromNetwork(QString&)));
00979 }
00980 
00984 void App::colorate(colorMaker &color){
00985         if (coloredImage != NULL)
00986                 delete coloredImage;
00987         coloredImage = new QImage(currentSize, QImage::Format_RGB888);
00988         
00989         if (maxValue == 0 || maxValue > 10000000)
00990                 maxValue = 256;
00991 
00992         if (showAnimation->checkState() != Qt::Checked)
00993                 bar->show();
00994         
00995         for (int i=0; i<currentSize.width(); i++){
00996                 for (int j=0; j<currentSize.height(); j++){
00997                         QRgb r = calculatedImage->pixel(i,j);
00998                         float value = ImageCalculator::RGBAToInt(r) * color.getNbLevels() / maxValue;
00999 
01000                         QColor newColor = color.get(value);
01001                         coloredImage->setPixel(i,j, newColor.rgb());
01002                 }
01003 
01004                 if (showAnimation->checkState() != Qt::Checked)
01005                         bar->setValue(100 * i / currentSize.width());
01006         }
01007 
01008         renderingImage->setPixmap(QPixmap::fromImage(*coloredImage));
01009         if (showAnimation->checkState() != Qt::Checked)
01010                 bar->hide();
01011         coloredImage->save("colored.bmp");
01012 }
01013 
01017 QStringList App::collectNetworkAgents(){
01018         QStringList networkAgentsList;
01019         for (QList<NetworkInput*>::iterator i = networkAddresses.begin(); i != networkAddresses.end(); i++)
01020                 if ((*i)->getUrl() != QString(""))
01021                         networkAgentsList << (*i)->getUrl();            
01022         
01023         return networkAgentsList;
01024 }
01025 
01029 void App::setNetworkList(QList<QString>& l){    
01030         // vider le layout      
01031         for (QList<NetworkInput*>::const_iterator i=networkAddresses.begin(); i!=networkAddresses.end(); i++){
01032                 NetworkInput *n = *i;
01033                 delete n;
01034         }       
01035         networkAddresses.clear();
01036         
01037         // recharger la liste
01038         for (QList<QString>::const_iterator i = l.begin(); i!=l.end(); i++){
01039                 NetworkInput *n = new NetworkInput();
01040                 n->setUrl(*i);
01041                 QObject::connect(n, SIGNAL(message(const QString&)), this, SLOT(s_receiveMessageFromNetwork(QString&)));
01042                 networkAddresses.append(n);
01043                 vbnetworkDock->addWidget(n);
01044         }
01045         vbnetworkDock->update();
01046 }
01047 
01051 void App::runLightning(){
01052         // le point de vue est spécifié en dur : 0,0,3   la source de lumière est aussi spécifiée en dur -2,-2,-3
01053         lightningMaker m(threeDrendering, normalMap, currentWindow, currentSize, coloredImage, 
01054                 triplex(0,0,-3), triplex(-2,-2,-3));
01055         m.run();
01056 }

Generated on Fri Feb 26 21:07:52 2010 for BuddhaBrot by  doxygen 1.4.6-NO