Skip to content

Instantly share code, notes, and snippets.

@ViktorSimko
Created February 27, 2016 11:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ViktorSimko/88a02936af52ea213ba6 to your computer and use it in GitHub Desktop.
Save ViktorSimko/88a02936af52ea213ba6 to your computer and use it in GitHub Desktop.
Mandelbrot Qt using signals and slots
// frakablak.cpp
//
// Mandelbrot halmaz nagyító
// Programozó Páternoszter
//
// Copyright (C) 2011, Bátfai Norbert, nbatfai@inf.unideb.hu, nbatfai@gmail.com
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// Ez a program szabad szoftver; terjeszthetõ illetve módosítható a
// Free Software Foundation által kiadott GNU General Public License
// dokumentumában leírtak; akár a licenc 3-as, akár (tetszõleges) késõbbi
// változata szerint.
//
// Ez a program abban a reményben kerül közreadásra, hogy hasznos lesz,
// de minden egyéb GARANCIA NÉLKÜL, az ELADHATÓSÁGRA vagy VALAMELY CÉLRA
// VALÓ ALKALMAZHATÓSÁGRA való származtatott garanciát is beleértve.
// További részleteket a GNU General Public License tartalmaz.
//
// A felhasználónak a programmal együtt meg kell kapnia a GNU General
// Public License egy példányát; ha mégsem kapta meg, akkor
// tekintse meg a <http://www.gnu.org/licenses/> oldalon.
//
//
// Version history:
//
// 0.0.1 Bár a Nokia Qt SDK éppen tartalmaz egy Mandelbrotos példát, de
// ezt nem tartottam megfelelõnek elsõ Qt programként ajánlani, mert elég
// bonyolult: használ kölcsönös kizárást stb. Ezért "from scratch" megírtam
// egy sajátot a Javát tanítokhoz írt dallamára:
// http://www.tankonyvtar.hu/informatika/javat-tanitok-2-2-080904-1
//
#include "frakablak.h"
FrakAblak::FrakAblak(double a, double b, double c, double d,
int szelesseg, int iteraciosHatar, QWidget *parent)
: QMainWindow(parent)
{
setWindowTitle("Mandelbrot halmaz");
szamitasFut = true;
x = y = mx = my = 0;
this->a = a;
this->b = b;
this->c = c;
this->d = d;
this->szelesseg = szelesseg;
this->iteraciosHatar = iteraciosHatar;
magassag = (int)(szelesseg * ((d-c)/(b-a)));
setFixedSize(QSize(szelesseg, magassag));
fraktal= new QImage(szelesseg, magassag, QImage::Format_RGB32);
mandelbrot = new FrakSzal(a, b, c, d, szelesseg, magassag, iteraciosHatar, this);
mandelbrot->start();
}
FrakAblak::~FrakAblak()
{
delete fraktal;
delete mandelbrot;
}
void FrakAblak::paintEvent(QPaintEvent*) {
QPainter qpainter(this);
qpainter.drawImage(0, 0, *fraktal);
if(!szamitasFut) {
qpainter.setPen(QPen(Qt::white, 1));
qpainter.drawRect(x, y, mx, my);
}
qpainter.end();
}
void FrakAblak::mousePressEvent(QMouseEvent* event) {
// A nagyítandó kijelölt területet bal felsõ sarka:
x = event->x();
y = event->y();
mx = 0;
my = 0;
update();
}
void FrakAblak::mouseMoveEvent(QMouseEvent* event) {
// A nagyítandó kijelölt terület szélessége és magassága:
mx = event->x() - x;
my = mx; // négyzet alakú
update();
}
void FrakAblak::mouseReleaseEvent(QMouseEvent* event) {
if(szamitasFut)
return;
szamitasFut = true;
double dx = (b-a)/szelesseg;
double dy = (d-c)/magassag;
double a = this->a+x*dx;
double b = this->a+x*dx+mx*dx;
double c = this->d-y*dy-my*dy;
double d = this->d-y*dy;
this->a = a;
this->b = b;
this->c = c;
this->d = d;
delete mandelbrot;
mandelbrot = new FrakSzal(a, b, c, d, szelesseg, magassag, iteraciosHatar, this);
mandelbrot->start();
update();
}
void FrakAblak::keyPressEvent(QKeyEvent *event)
{
if(szamitasFut)
return;
if (event->key() == Qt::Key_N)
iteraciosHatar *= 2;
szamitasFut = true;
delete mandelbrot;
mandelbrot = new FrakSzal(a, b, c, d, szelesseg, magassag, iteraciosHatar, this);
mandelbrot->start();
}
void FrakAblak::setRow(int magassag, int *sor, int meret)
{
for(int i=0; i<meret; ++i) {
QRgb szin = qRgb(0, 255-sor[i], 0);
fraktal->setPixel(i, magassag, szin);
}
update();
}
void FrakAblak::setImage()
{
szamitasFut = false;
x = y = mx = my = 0;
}
#include <QMouseEvent>
#include <QKeyEvent>
#include "frakszal.h"
class FrakSzal;
class FrakAblak : public QMainWindow
{
Q_OBJECT
public:
FrakAblak(double a = -2.0, double b = .7, double c = -1.35,
double d = 1.35, int szelesseg = 600,
int iteraciosHatar = 1000, QWidget *parent = 0);
~FrakAblak();
// A komplex sík vizsgált tartománya [a,b]x[c,d].
double a, b, c, d;
// A komplex sík vizsgált tartományára feszített
// háló szélessége és magassága.
int szelesseg, magassag;
// Max. hány lépésig vizsgáljuk a z_{n+1} = z_n * z_n + c iterációt?
// (tk. most a nagyítási pontosság)
int iteraciosHatar;
protected:
void paintEvent(QPaintEvent*);
void mousePressEvent(QMouseEvent*);
void mouseMoveEvent(QMouseEvent*);
void mouseReleaseEvent(QMouseEvent*);
void keyPressEvent(QKeyEvent*);
private:
QImage* fraktal;
FrakSzal* mandelbrot;
bool szamitasFut;
// A nagyítandó kijelölt területet bal felsõ sarka.
int x, y;
// A nagyítandó kijelölt terület szélessége és magassága.
int mx, my;
public slots:
void setRow(int magassag , int * sor, int meret);
void setImage();
};
#endif // FRAKABLAK_H
// frakszal.cpp
//
// Mandelbrot halmaz rajzoló
// Programozó Páternoszter
//
// Copyright (C) 2011, Bátfai Norbert, nbatfai@inf.unideb.hu, nbatfai@gmail.com
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// Ez a program szabad szoftver; terjeszthetõ illetve módosítható a
// Free Software Foundation által kiadott GNU General Public License
// dokumentumában leírtak; akár a licenc 3-as, akár (tetszõleges) késõbbi
// változata szerint.
//
// Ez a program abban a reményben kerül közreadásra, hogy hasznos lesz,
// de minden egyéb GARANCIA NÉLKÜL, az ELADHATÓSÁGRA vagy VALAMELY CÉLRA
// VALÓ ALKALMAZHATÓSÁGRA való származtatott garanciát is beleértve.
// További részleteket a GNU General Public License tartalmaz.
//
// A felhasználónak a programmal együtt meg kell kapnia a GNU General
// Public License egy példányát; ha mégsem kapta meg, akkor
// tekintse meg a <http://www.gnu.org/licenses/> oldalon.
//
//
// Version history:
//
// 0.0.1 Bár a Nokia Qt SDK éppen tartalmaz egy Mandelbrotos példát, de
// ezt nem tartottam megfelelõnek elsõ Qt programként ajánlani, mert elég
// bonyolult: használ kölcsönös kizárást stb. Ezért "from scratch" megírtam
// egy sajátot a Javát tanítokhoz írt dallamára:
// http://www.tankonyvtar.hu/informatika/javat-tanitok-2-2-080904-1
//
#include "frakszal.h"
FrakSzal::FrakSzal(double a, double b, double c, double d,
int szelesseg, int magassag, int iteraciosHatar, FrakAblak *frakAblak)
{
this->a = a;
this->b = b;
this->c = c;
this->d = d;
this->szelesseg = szelesseg;
this->iteraciosHatar = iteraciosHatar;
this->frakAblak = frakAblak;
this->magassag = magassag;
connect(this, SIGNAL(rowReady(int, int *, int)),
frakAblak, SLOT(setRow(int, int *, int)));
connect(this, SIGNAL(imageReady()),
frakAblak, SLOT(setImage()));
egySor = new int[szelesseg];
}
FrakSzal::~FrakSzal()
{
disconnect(this, SIGNAL(rowReady(int, int *, int)),
frakAblak, SLOT(setRow(int, int *, int)));
disconnect(this, SIGNAL(imageReady()),
frakAblak, SLOT(setImage()));
delete[] egySor;
}
// A szál kódját a Javát tanítokhoz írt Java kódomból vettem át
// http://www.tankonyvtar.hu/informatika/javat-tanitok-2-2-080904-1
// mivel itt az algoritmust is leírtam/lerajzoltam, így meghagytam
// a kommenteket, hogy a hallgató könnyen hozzáolvashassa az "elméletet",
// ha érdekli.
void FrakSzal::run()
{
// A [a,b]x[c,d] tartományon milyen sûrû a
// megadott szélesség, magasság háló:
double dx = (b-a)/szelesseg;
double dy = (d-c)/magassag;
double reC, imC, reZ, imZ, ujreZ, ujimZ;
// Hány iterációt csináltunk?
int iteracio = 0;
// Végigzongorázzuk a szélesség x magasság hálót:
for(int j=0; j<magassag; ++j) {
//sor = j;
for(int k=0; k<szelesseg; ++k) {
// c = (reC, imC) a háló rácspontjainak
// megfelelõ komplex szám
reC = a+k*dx;
imC = d-j*dy;
// z_0 = 0 = (reZ, imZ)
std::complex<double> c(reC, imC);
reZ = 0;
imZ = 0;
std::complex<double> z_n(reZ, imZ);
iteracio = 0;
// z_{n+1} = z_n * z_n + c iterációk
// számítása, amíg |z_n| < 2 vagy még
// nem értük el a 255 iterációt, ha
// viszont elértük, akkor úgy vesszük,
// hogy a kiinduláci c komplex számra
// az iteráció konvergens, azaz a c a
// Mandelbrot halmaz eleme
/*
while(reZ*reZ + imZ*imZ < 4 && iteracio < iteraciosHatar) {
// z_{n+1} = z_n * z_n + c
ujreZ = reZ*reZ+ std::atan(reZ*reZ - imZ*imZ) + std::sqrt(reC);
ujimZ = 2*reZ*imZ+std::atan(2*reZ*imZ) + imC;
reZ = ujreZ;
imZ = ujimZ;
++iteracio;
}
*/
while( std::abs(z_n) < 4 && iteracio < iteraciosHatar) {
z_n = z_n * z_n + c;
++iteracio;
}
// ha a < 4 feltétel nem teljesült és a
// iteráció < iterációsHatár sérülésével lépett ki, azaz
// feltesszük a c-rõl, hogy itt a z_{n+1} = z_n * z_n + c
// sorozat konvergens, azaz iteráció = iterációsHatár
// ekkor az iteráció %= 256 egyenlõ 255, mert az esetleges
// nagyítasok során az iteráció = valahány * 256 + 255
iteracio %= 256;
//a színezést viszont már majd a FrakAblak osztályban lesz
egySor[k] = iteracio;
}
// Ábrázolásra átadjuk a kiszámolt sort a FrakAblak-nak.
//frakAblak->vissza(j, egySor, szelesseg);
emit rowReady(j, egySor, szelesseg);
}
//frakAblak->vissza();
emit imageReady();
}
#ifndef FRAKSZAL_H
#define FRAKSZAL_H
#include <QThread>
#include <cmath>
#include <complex>
#include "frakablak.h"
class FrakAblak;
class FrakSzal : public QThread
{
Q_OBJECT
public:
FrakSzal(double a, double b, double c, double d,
int szelesseg, int magassag, int iteraciosHatar, FrakAblak *frakAblak);
~FrakSzal();
void run();
protected:
// A komplex sík vizsgált tartománya [a,b]x[c,d].
double a, b, c, d;
// A komplex sík vizsgált tartományára feszített
// háló szélessége és magassága.
int szelesseg, magassag;
// Max. hány lépésig vizsgáljuk a z_{n+1} = z_n * z_n + c iterációt?
// (tk. most a nagyítási pontosság)
int iteraciosHatar;
// Kinek számolok?
FrakAblak* frakAblak;
// Soronként küldöm is neki vissza a kiszámoltakat.
int* egySor;
signals:
void rowReady(int magassag, int *sor, int meret);
void imageReady();
};
#endif // FRAKSZAL_H
// main.cpp
//
// Mandelbrot halmaz rajzoló
// Programozó Páternoszter
//
// Copyright (C) 2011, Bátfai Norbert, nbatfai@inf.unideb.hu, nbatfai@gmail.com
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Bár a Nokia Qt SDK éppen tartalmaz egy Mandelbrotos példát, de
// ezt nem tartottam megfelelõnek elsõ Qt programként ajánlani, mert elég
// bonyolult: használ kölcsönös kizárást stb. Ezért "from scratch" megírtam
// egy sajátot a Javát tanítokhoz írt dallamára:
// http://www.tankonyvtar.hu/informatika/javat-tanitok-2-2-080904-1
//
#include <QApplication>
#include "frakablak.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// További adatokat olvashatsz le innen:
// http://www.tankonyvtar.hu/informatika/javat-tanitok-2-3-080904
FrakAblak w1;
w1.show();
/*
FrakAblak w1,
w2(-.08292191725019529, -.082921917244591272,
-.9662079988595939, -.9662079988551173, 600, 3000),
w3(-.08292191724880625, -.0829219172470933,
-.9662079988581493, -.9662079988563615, 600, 4000),
w4(.14388310361318304, .14388310362702217,
.6523089200729396, .6523089200854384, 600, 38655);
w1.show();
w2.show();
w3.show();
w4.show();
*/
return a.exec();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment