PHP Mandelbrot

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • PHP Mandelbrot

    Ein Mandelbrot (Fraktale mit PHP)
    Quelle: http://www.thegeek.de/blog/type/archiv/post/200501.html
    Sourcecode: http://www.thegeek.de/src/fraktal.phps
    Demo: http://www.thegeek.de/src/fraktal.php

    Ein Mandelbrot ist zuerst einmal etwas essbares, nur ob das schmeckt? Nein, Mandelbrot ist eine Zahlenmenge bestehend aus komplexen Zahlen, die auf einer kompexen Ebene betrachtet werden. Komplexe Zahlen haben die Eigenschaft, dass sie aus zwei Teilen bestehen. Aus dem Realteil und dem Imaginärteil. Diese mathematische Regel ermöglicht es, eine komplexe Zahl 2-dimensional darzustellen. Der Punkt kann am Bildschirm dargestellt werden, wenn der Realteil der komplexen Zahl als X-Koordinate und der Imaginärteil als Y-Koordinate verwendet wird.

    Das erklärt aber immernoch nicht, wie das Apfelmännchen zustande kommt. Im Grunde ist es recht einfach. Wie schon erwähnt ist die Mandelbrotmenge ein Zahlenmenge aus komplexen Zahlen. Es gibt komplexe Zahlen, die innerhalb der Mandelbrotmenge liegen, und komplexe Zahlen, die außerhalb der Menge liegen. Ob ein Punkt Bestandteil der Menge ist wird mit einer Iteration ermittelt. Die Formel zur Iteration ist dabei folgende:

    Zn = Zn-1² + C

    Eine kurze Erklärung der Formel: Z ist ist der iterative Teil, C ist eine Konstante, wobei C die komplexe Zahl, die betrachtet wird. Zu Beginn der Iteration ist Z0 = 0.
    Da es sich bei Z und C um komplexe Zahlen handelt, benötigen wir zur Durchführung der Iteration noch zwei weitere mathematische Tricks, um die Formel zu rechnen.

    Um das Quadrat von Z zu bilden, muss Z mit sich selbst multipliziert werden. Hier die Berechnungsformel:

    ZRe = Z1 Re * Z2 Re - Z1 Im * Z2 Im
    ZIm = Z1 Re * Z2 Im + Z1 Im * Z2 Re

    Um zwei komplexe Zahlen zu addieren, werden die Realteile und die Imaginärteile addiert:

    ZRe = Z1 Re + Z2 Re
    ZIm = Z1 Im + Z2 Im

    Mit diesen Formeln können wir unsere iterative Formel in einer Schleife berechnen. Die Anzahl der Iteration (Schleifendurchläufe) bestimmt dabei die Genauigkeit, bzw. die Detailtiefe des Fraktals. Um zu bestimmen, ob der berechnete Punkt innerhalb der Mandelbrotmenge liegt oder nicht, wird Z bei jeder Iteration betrachtet. Strebt Z offensichtlich gegen unendlich, bzw. überschreitet Z einen gewissen Grenzwert, so ist der betrachtete Punkt NICHT Bestandteil der Mandelbrotmenge. Ist Z jedoch nach dem Durchlaufen aller Iterationen unterhalb des Grenzwertes, so ist er Bestandteil der Mandelbrotmenge.

    Nun haben wir aber das Problem, dass Z aus einem Realteil und einem Imaginärteil besteht, doch auch hierfür gibt es eine Lösung: Es muss der Betrag der komplexen Zahl berechnet werden. Auch hierfür gibt es eine Formel, die sich vom Satz des Pythagoras herleitet:

    | Z | = SQRT( ZRe² + ZIm²)

    Das Ergebnis dieser Berechnung wird als Betrag angenommen und bei jeder Iteration mit dem Grenzwert verglichen.

    Soviel erstmal zum mathematischen Hintergrund, ich hoffe ich habe es ausreichend erklärt, Mathe war nie so unbedingt mein Ding, also falls ich irgendwas komisch oder auch falsch formuliert habe, bitte ich das zu entschuldigen.

    Nun aber zum Programm, endlich ran an den Source-Code! Die Klasse "fraktal" besitzt folgende öffentliche Eigenschaften:


    complex -> start -> Re = -2,5 (double)
    complex -> start -> Im = -1,5 (double)
    complex -> end -> Re = 1.5 (double)
    complex -> end -> Im = 1.5 (double)
    iterations = 30 (integer)
    size_x = 320 (integer)
    size_y = 240 (integer)
    pal_startcolor = 0x666666 (long)
    pal_endcolor = 0xFF0000 (long)


    Über "complex -> start -> Re/Im" und "complex -> end -> Re/Im" wird die komplexe Zahlenmenge festgelegt, die zur Überprüfung über das Iterationsverfahren herangezogen wird. Die maximal durchzuführenden Iterationen werden über die Eigenschaft "iterations" bestimmt. "size_x" und "size_y" legen die Breite und die Höhe des Bildes fest, das per GDlib ausgegeben wird. Über die Breite und Höhe errechnen sich auch die Punkte der komplexen Zahlenmenge, indem eine Schrittweite für "complex -> z -> Re" und "complex -> z -> Im" berechnet wird. Die Eigenschaften "pal_startcolor" und "pal_endcolor" erwarten hexadezimale 24-Bit Farbangaben. Aus den beiden Farben wird dann eine Verlaufspalette errechnet. Die Farbe der Pixel wird übrigens aus der Anzahl der durchlaufenen Iterationen ermittelt.

    Und nun zu den verfügbaren Methoden der Klasse "frakal":

    image_createpalette( &$image, $start_color, $end_color )
    Hier wird die Farbpalette, abhängig von den maximalen Iterationen und Start- und Endfarbwert für unser GDlib-Bild erzeugt. Für $start_color und $end_color werden 24-Bit hexadezimale Farbwerte erwartet (z.B. 0xFF0000 für rot).

    complex_calcstepwidth()
    Abhängig von der Breite und Höhe des Bildes, wird hier der Additionsfaktor für den Real- und Imaginärteil von "complex -> z" errechnet. Dies hat zur Folge, dass für jeden Pixel im Bild eine komplexe Zahl per Iteration untersucht wird.

    complex_to_real( $cmplx )
    Die Methode liefert den Betrag einer komplexen Zahl zurück. $cmplx ist bei der Übergabe ein Objekt mit den Unterobjekten "Re" und "Im".

    complex_mul( $cmplx1, $cmplx2 )
    Hier werden zwei komplexe Zahlen miteinander multipliziert. Wir benötigen diese Methode zur Quadrierung von Z. Die übergebenen Variablen sind auch hier Objekte mit den Unterobjekten "Re" und "Im".

    complex_iterate( $cmplx_z )
    Diese Methode führt das oben beschriebene Iterationsverfahren für die übergebene komplexe Zahl durch. Rückgabewert ist die Anzahl der durchgeführten Iterationen. Ist der zurückgegebene Wert kleiner als die Anzahl der maximalen Iterationen, handelt es sich bei der übergebenen komplexen Zahl nicht um eine Zahl, die Bestandteil der Mandelbrotmenge ist.

    render_mandelbrot()
    Diese Methode führt alle Funktionen zusammen und führt die Schleife aus, die jeden einzelnen Bildpunkt berechnet.


    Abschließend möchte ich zum Source-Code noch etwas sagen:
    Sicherlich kann man die Laufzeit noch wesentlich geringer bekommen, doch es geht bei diesem Beispiel nicht um die Laufzeit, sondern darum sich mit Fraktalen zu beschäftigen. Und es geht auch darum zu zeigen wie es geht, und vorallem, dass es auch mit PHP geht. Deswegen ist der Source-Code sicherlich nicht der schnellste, aber ich denke ziemlich gut lesbar wenn man alles mal nach der Reihe durchgeht.
    In PHP fehlt einfach folgender Befehl "_asm { }", aber okay, PHP ist schließlich nicht C++ und das ist auch verdammt gut so! Wenn man bedenkt, dass die Fraktalklasse nur ca. 140 Zeilen Source-Code hat, dann sieht man mal wieder, wie wunderbar schön PHP zu programmieren ist.
    Allerdings merkt man auch, das PHP für komplexe Berechnungen nicht so optimal ist, denn die Laufzeit ist wirklich ziemlich hoch.

    Hier das Script zum ausprobieren (gibt ein PNG aus): http://www.thegeek.de/src/fraktal.php
    Und hier der Source-Code zur freien Verwendung: http://www.thegeek.de/src/fraktal.phps

    Viel Spaß mit dem Apfelmännchen!


    PS: Die Berechnung benötigt natürlich seine Zeit. Nur Geduld.