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);
    }
    

Anmelden zum Antworten