Mandelbrot-Menge komische Figur
-
Hallo,
wir sollten ein Programm schreiben, was deine Mandelbrot Menge darstellt.
http://img64.imageshack.us/f/mandelbrotb.jpg/
Das Ergebnis schaut komisch aus.
hier die wichtigsten Funktionen
int CApfel::getAnzIt(CComplex C, int Nmax, int Max) { int n=0; CComplex z; while ((z.getBetrag()<Max) && (n<Nmax)) { z=z*z+C; n++; } return n; }double CComplex::getBetrag() { return (sqrt(pow(real,2)+pow(ima,2))); }double CMandelmaenchenDlg::aufloesungX() { double xSchritt; xSchritt=(C1R-C2R)/250.; return xSchritt; } double CMandelmaenchenDlg::aufloesungY() { double ySchritt; ySchritt=(C1I-C2I)/250.; return ySchritt; } void CMandelmaenchenDlg::OnBnClickedBberechnen() { UpdateData(true); CClientDC dc(this); for (int y=0;y<250;y++) { for (int x=0;x<250;x++) { CComplex cAktuell(C1R+x*aufloesungX(),C1I-y*aufloesungY()); int n=Apfel.getAnzIt(cAktuell, Nmax, Max); dc.SetPixel(x+275,y+22,RGB(2*n,2*n,0)); } } }
-
pumple schrieb:
Das Ergebnis schaut komisch aus.
Stimmt. Danke für die Info!
-
Das sieht so aus, als ob die Iterationstiefe nicht genügend hoch ist.
btw:
Du bist im völlig falschen Unteforum. Es gibt eines für Grafik/Spieleprogrammierung.
-
Du solltest schon etwas kompilierbares liefern. Zumindest mal die CComplex-Klasse, besser aber gleich complex<double> verwenden.
Edit: liegt womöglich wirklich an CComplex, denn:
#include <complex> int getAnzIt(complex<double> C, int Nmax, int Max) { int n=0; complex<double> z; while (abs(z)<Max && n<Nmax) { z=z*z+C; n++; } return n; } [...] const int width=800,height=600; const double l=-2,r=1,t=-1,b=1; const double xstep=(r-l)/width,ystep=(b-t)/height; for (int y=0;y<height;y++) { for (int x=0;x<width;x++) { int n=getAnzIt(complex<double>(l+x*xstep,t+y*ystep),50,1000); canvas.setPixel(x,y,RGB(n*2,n*2,0)); } }liefert bei mir das:
http://94.23.22.190/etc/mandel.png
-
Liegt wohl doch an meiner CComplex Klasse

edit: hab den Fehler gefunden.
Ich hatte zur besseren aufgabe die Werte auf 0 gesetzt wenn der Imaginär oder Realteil <0.0000001 wird.
Kommentier ich das raus, funktionierts auch.complex.h
#pragma once #include <iostream> using namespace std; class CComplex { private: double real,ima; public: CComplex(double r=0, double i=0); void ausgabeKartesisch(); void ausgabeExponential(); double getRealteil(); double getImaginaerteil(); double getBetrag(); double getPhaseBogen(); double getPhaseGrad(); void setImaginaerteil(double x); void setRealteil(double x); void setBetrag(double x); void setPhase(double x); friend void operator+=(CComplex &c1, CComplex &c2); friend void operator-=(CComplex &c1, CComplex &c2); friend istream &operator>> (istream &is, CComplex &c); ~CComplex(void); }; CComplex operator+(CComplex c1,CComplex c2); CComplex operator+(CComplex c1, double x); CComplex operator+(double x,CComplex &c2); CComplex operator++(CComplex c); CComplex operator-(CComplex c1,CComplex c2); CComplex operator-(CComplex c1, double x); CComplex operator-(double x,CComplex c2); CComplex operator-(CComplex c); CComplex operator--(CComplex c); CComplex operator/(CComplex c1,CComplex c2); CComplex operator/(CComplex c1, double x); CComplex operator/(double x,CComplex c2); CComplex operator*(CComplex c1,CComplex c2); CComplex operator*(CComplex c1, double x); CComplex operator*(double x,CComplex c2); bool operator==(CComplex c1, CComplex c2); bool operator==(CComplex c1, double x); bool operator==(double, CComplex c2); bool operator!=(CComplex c1, CComplex c2); bool operator!=(CComplex c1, double x); bool operator!=(double, CComplex c2); ostream& operator<<(ostream &os,CComplex c); void imaRealNull (CComplex &c);Complex.cpp
#include "stdafx.h" #include "Complex.h" #include <math.h> #include <iostream> using namespace std; const double pi=3.14159265; //Start der Klassenfunktionen: CComplex::CComplex(double r,double i) { real = r; ima = i; } CComplex::~CComplex(void){} void CComplex::ausgabeKartesisch() { cout << "Kartesiche Schreiweise: " << real << " + j" << ima; } void CComplex::ausgabeExponential() { cout << "Exponentialschreibweise: " << getBetrag() << "e^(j" << getPhaseGrad() << ")"; } double CComplex::getRealteil() { return (real); } double CComplex::getImaginaerteil() { return (ima); } double CComplex::getBetrag() { return (sqrt(pow(real,2)+pow(ima,2))); } double CComplex::getPhaseBogen() { if (ima<0 && real==0) return (-pi/2); if (ima>0 && real==0) return (pi/2); if (ima==0 && real==0) return (0); else return (atan(ima/real)); } double CComplex::getPhaseGrad() { return (CComplex::getPhaseBogen()*(360/(2*pi))); } void CComplex::setImaginaerteil(double x) { ima = x; } void CComplex::setRealteil(double x) { real = x; } void CComplex::setBetrag(double x) { double temp=getPhaseBogen(); ima = x*sin(temp); real = x*cos(temp); } void CComplex::setPhase(double x) { double temp=getBetrag(); ima = temp*sin(x*2*pi/360); real = temp*cos(x*2*pi/360); } //Ende der Klassenfunktionen //Start der Friendfunktionen: //Überladen des "+=" Operators void operator+=(CComplex &c1, CComplex &c2) { c1.real += c2.real; c1.ima += c2.ima; } //Überladen des "-=" Operators void operator-=(CComplex &c1, CComplex &c2) { c1.real -= c2.real; c1.ima -= c2.ima; } //Überladen des ">>" Operators für cin istream &operator>> (istream &is, CComplex &c) { is >> c.real >> c.ima; return is; } //Ende der Friendfunktionen //Überladen des "+" Operators durch drei Funktionen CComplex operator+(CComplex c1,CComplex c2) { return CComplex(c1.getRealteil()+c2.getRealteil(),c1.getImaginaerteil()+c2.getImaginaerteil()); } CComplex operator+(CComplex c1, double x) { return CComplex(c1.getRealteil()+x,c1.getImaginaerteil()); } CComplex operator+(double x,CComplex &c2) { return CComplex(x+c2.getRealteil(),c2.getImaginaerteil()); } //Überladen des "++" Operators CComplex operator++(CComplex c) { return CComplex(c.getRealteil()+1,c.getImaginaerteil()+1); } //Überladen des "-" Operators durch drei Funktionen CComplex operator-(CComplex c1,CComplex c2) { return CComplex(c1.getRealteil()-c2.getRealteil(),c1.getImaginaerteil()-c2.getImaginaerteil()); } CComplex operator-(CComplex c1, double x) { return CComplex(c1.getRealteil()-x,c1.getImaginaerteil()); } CComplex operator-(double x,CComplex c2) { return CComplex(x-c2.getRealteil(),-c2.getImaginaerteil()); } CComplex operator-(CComplex c) { return CComplex(-c.getRealteil(),-c.getImaginaerteil()); } //Überladen des "--" Operators CComplex operator--(CComplex c) { return CComplex(c.getRealteil()-1,c.getImaginaerteil()-1); } //Überladen des "/" Operators durch drei Funktionen CComplex operator/(CComplex c1,CComplex c2) { CComplex temp(0,0); temp.setBetrag(c1.getBetrag()/c2.getBetrag()); temp.setPhase(c1.getPhaseGrad()-c2.getPhaseGrad()); imaRealNull(temp); return CComplex(temp); } CComplex operator/(CComplex c1, double x) { CComplex temp(0,0); temp.setBetrag(c1.getBetrag()/x); imaRealNull(temp); return CComplex(temp); } CComplex operator/(double x,CComplex c2) { CComplex temp(0,0); temp.setBetrag(x/c2.getBetrag()); temp.setPhase(-c2.getPhaseGrad()); return CComplex(temp); } //Überladen des "*" Operators durch drei Funktionen CComplex operator*(CComplex c1,CComplex c2) { CComplex temp(1,1); temp.setBetrag(c1.getBetrag()*c2.getBetrag()); temp.setPhase(c1.getPhaseGrad()+c2.getPhaseGrad()); imaRealNull(temp); return CComplex(temp); } CComplex operator*(CComplex c1, double x) { CComplex temp(1,1); temp.setBetrag(c1.getBetrag()*x); temp.setPhase(c1.getPhaseGrad()); imaRealNull(temp); return CComplex(temp); } CComplex operator*(double x,CComplex c2) { CComplex temp(1,1); temp.setBetrag(x*c2.getBetrag()); temp.setPhase(c2.getPhaseGrad()); imaRealNull(temp); return CComplex(temp); } //Überladen des "==" Operators durch drei Funktionen bool operator==(CComplex c1, CComplex c2) { if (c1.getRealteil()==c2.getRealteil() && c1.getImaginaerteil()== c2.getImaginaerteil()) return true; else return false; } bool operator==(CComplex c1, double x) { if (c1.getRealteil()==x && c1.getImaginaerteil()== 0) return true; else return false; } bool operator==(double x, CComplex c2) { if (x==c2.getRealteil() && 0 == c2.getImaginaerteil()) return true; else return false; } //Überladen des "!=" Operators durch drei Funktionen bool operator!=(CComplex c1, CComplex c2) { if (c1==c2) return false; else return true; } bool operator!=(CComplex c1, double x) { if (c1==x) return false; else return true; } bool operator!=(double x, CComplex c2) { if (x==c2) return false; else return true; } //Überladen des "<<" Operators für cout ostream& operator<<(ostream &os,CComplex c) { if (c.getImaginaerteil()==0) os << c.getRealteil(); if (c.getImaginaerteil()<0) os << c.getRealteil() << " - j" << -c.getImaginaerteil(); if (c.getImaginaerteil()>0) os << c.getRealteil() << " + j" << c.getImaginaerteil(); return os; } // Funktion um eine null zu erhalten, wenn der Wert des Imaginaer- oder Realteil gegen Null geht. void imaRealNull (CComplex &c) { if (c.getRealteil()<0.0000001) c.setRealteil(0); if (c.getImaginaerteil()<0.0000001) c.setImaginaerteil(0); }
-
Dann würde ich mir die Implementation der Multiplikation noch einmal in Ruhe anschauen. Wenn ich complex<double> durch CComplex ersetze, sieht das dann hier auch abenteuerlich aus:
http://94.23.22.190/etc/mandel2.png
-
haste die Funktion imaRealNull(temp); rauskommentiert?
Dann siehst bei mir aus, wie es aussehen soll
-
pumple schrieb:
haste die Funktion imaRealNull(temp); rauskommentiert?
Dann siehst bei mir aus, wie es aussehen soll
Nein, das hatte ich vor der Korrektur geschrieben.
Ohne imaRealNull funktioniert es, allerdings geht die Berechnung mit complex<double> fast 30 mal schneller.
-
So multipliziert man doch keine komplexen Zahlen, das wird doch arschlahm, mit Phase und trigonometrischen Funktionen...
Eine komplexe Zahl ist definiert als z = a + jb.
Also ist
z1 * z2 =
(a1 + jb1) * (a2 + jb2) =
(a1 a2 + j a1 b2 + j b1 a2 + j j b1 b2) = [mit j j = -1]
(a1 a2 - b1 b2) + j (a1 b2 + b1 a2)Das dürfte bißchen schneller und bißchen genauer sein.
[In http://www.baeckmann.de/pdf/DFT.pdf Seite 39 steht noch, wie man auch diese Multiplikation u.U. noch etwas schneller machen kann.]
-
Athar schrieb:
allerdings geht die Berechnung mit complex<double> fast 30 mal schneller.
Wenn man sich sowas anschaut, ist das auch nicht allzu verwunderlich.

CComplex operator*(CComplex c1,CComplex c2) { CComplex temp(1,1); temp.setBetrag(c1.getBetrag()*c2.getBetrag()); temp.setPhase(c1.getPhaseGrad()+c2.getPhaseGrad()); imaRealNull(temp); return CComplex(temp); }