Im zweiten Teil dieses Tutorials zeige ich Euch, wie Ihr Eure eigenen Fraktalformeln entwickeln könnt.

Bevor Ihr jetzt aber völlig planlos Eure eigenen Formeln entwickelt, solltet Ihr Euch natürlich ein paar grundlegende Gedanken machen. Was soll diese Formel können, stellt sie etwas noch nie dagewesenes dar oder reichen die von Ultra Fractal bereitgestellten Formeln für Eure Zwecke völlig aus.

Solide Grundlage für das Entwickeln eigener Formeln ist, so banal wie es klingt, ein Plan.

Deshalb möchte ich vorab einige Eckpunkte für unseren Formel definieren.

  1. die Iterationsgleichung soll einen Startwert, einen Exponenten und zwei Funktionen enthalten,
  2. eine Funktion soll vom Nutzer aktiviert und dann eingeblendet werden können,
  3. die Daten für den Startwert, Exponent und Bailout sollen vom Nutzer eingegeben werden können und
  4. zwischen den Fraktaltypen soll umgeschaltet werden können.

Dann lasst uns anfangen.

Fraktalformeldatei erstellen

Zunächst erstellt Ihr Euch eine neue Fraktal-Formel-Datei (Fractal Formula File). Dazu wählt Ihr im Datei (File) Menü den Punkt Neu (New) aus.

Formeldatei öffnen

Daraufhin öffnet sich im Editor ein leeres Fenster mit den Namen Formula1.

Leere Formeldatei

Dieses Fenster bzw. diese Formeldatei nimmt nun nach und nach Eure Programmanweisungen auf. Damit Ihr nicht alles von Hand eingeben müsst, sind im Menüpunkt Einfügen (Insert) viele Anweisungen hinterlegt, die Ihr mit Klick einfügen könnt.

Die Formeln beginnen immer mit dem Eintrag-Identifikator, gefolgt von dessen Inhalt, der in geschweiften Klammern steht. Ihr solltet beachten, dass Leerzeichen und Tabulatoren nicht erlaubt sind. Ebenso darf der Eintrag-Identifikator innerhalb der Formeldatei nicht doppelt auftreten.

Meine-erste-Formel {
; Inhalt
}

Optional kann dem Identifikator ein Wert in Klammern beigefügt werden. Ultra Fractal kann somit die Symmetrie zum Beschleunigen der Berechnung nutzen.

MeinMandelbrot (XAXIS) {
; Inhalt
}

Kommentare in der Formel werden mit vorangestellten Semikolon gekennzeichnet. Zusätzliche globale Kommentare könnt Ihr mit dem speziellen ‘{ }‘-Kommentar kennzeichnen.

Ich habe es mir angewöhnt, bevor ich die Formeln schreibe, einen globalen Kommentar anzulegen, der folgende Inhalte aufweist:

comment {
  File: Formula1.ufm
  Version: 1.0
  Author: Oliver Konow, 2012
  Last Modification:
}

Als nächstes folgt der Identifikator in dem Abschnitte, Funktionen und Parameter sowie weitere Einträge stehen können.

Im Menü Einfügen (Insert) findet Ihr den Punkt Neue Formel (New Formula…)

Neue Formel erstellen

Es öffnet sich anschließend ein Fenster, in dem Ihr den Titel MeinMandelbrot eingeben und eine Symmetrie der verschiedenen Achsen auswählen könnt. In diesem Fall wählt Ihr XAXIS_NOPARM aus, sie erzwingt eine Symmetrie um die horizontale x-Achse bzw. real-Achse, jedoch nur, wenn alle komplexen Parameter auf (0, 0) gesetzt sind.

Den Haken am Punkt: Insert global section könnt Ihr entfernen. Falls Ihr für die verbleibenden Abschnitte keine Kommentare haben wollt, so entfernt den Haken auch am Punkt: Insert comments for each section. Drückt anschließend auf OK.

Eintrag-Identifikator

Hinweis zur Symmetrie: Damit Ultra Fractal die symmetrischen Eigenschaften von Fraktalen zum Beschleunigen der Berechnung nutzen kann, müsst Ihr die Symmetrie der Formel als optionale Einstellung in Klammern hinter dem Eintrag-Identifikator angeben.

Folgende Abschnitte sollten jetzt vorhanden sein:

MeinMandelbrot(XAXIS_NOPARM) {
init:
 
loop:
 
bailout:
 
default:
  title = "MeinMandelbrot"
 
switch:
}

Das Grundgerüst unserer Formel

Damit ist das Grundgerüst Eurer Formel fertig, welches Ihr an dieser Stelle speichern solltet. Im nächsten Schritt werde ich die Abschnitte näher erläutern bevor wir sie anschließend mit Variablen befüllen.

Die Abschnitte der Formel

Abschnitt: init

In diesem Abschnitt wird die Hauptvariable z initialisiert. Sie ist ein vordefiniertes Symbol, weshalb sie korrekterweise ‘#z‘ bezeichnet werden müsste. In Fraktalformeln kann das #-Präfix vor ‘#z‘ weggelassen werden. In Kolorierungs-Algorithmen wird es jedoch benötigt.

Dieser Abschnitt wird pro Pixel nur einmal ausgeführt und eignet sich, um Variablen zu initialisieren.

Abschnitt: loop

Hier steht unsere Hauptgleichung, die nur einmal pro Iteration ausgeführt wird. Der Abschnitt soll den Wert der vordefinierten komplexen Variable #z unter Berücksichtigung des alten Wertes von ‘z‘ aktualisieren.

Abschnitt: bailout

Dieser Abschnitt enthält einen einzelnen Boole’schen Ausdruck, der den loop-Abschnitt solange ausführt, wie dieser Wert true ist. Er wird mindestens einmal ausgeführt.

Abschnitt: default

Grundeinstellungen unserer Formel betreffend sind in diesem Abschnitt zu finden. Er kann Einstellungen wie title, angle, center, maxiter, helpfile und/oder helptopic beinhalten. Parametereinstellungen innerhalb der Blöcke param und endparam können ebenfalls verwendet werden.

Weitere Einstellungen sind in der Hilfedatei zu finden.

Abschnitt: switch

Dieser Abschnitt ermöglicht das Umschalten zwischen verwandten Fraktaltypen, z.B. von Mandelbrot in Julia.

Darüber hinaus gibt es noch zwei weitere Abschnitte, die hier nicht aufgeführt, ich aber dennoch kurz erläutern möchte:

Abschnitt: global

In der Fraktalformel ist dies der erste Abschnitt und wird nur einmal pro Bild ausgeführt. Er kann dazu verwendet werden, Suchtabellen zu füllen und Nur-Lese-Variablen zu initialisieren. Somit können viele wiederholte Berechnungen vermeiden werden.

Abschnitt: builtin

Mit diesem Abschnitt könnt Ihr auf fest eingebaute Fraktalformeln zurückgreifen. Wenn dieser Abschnitt verwendet wird, sind die Abschnitte global, init, loop und bailout nicht zulässig. Der Abschnitt kann folgende Einstellung enthalten: type.

Einsetzen der Variablen in die Formel

Nachdem das Grundgerüst steht, können nun Variablen, Ausdrücke und Formeln in die entsprechenden Abschnitte eingesetzt werden.

Hinweis! Hinsichtlich der Parameter möchte ich auf den Artikel Formel schreiben – Teil 1 verweisen.

Inhalt des init-Abschnitts

z = @start

Die komplexe Variable z wird mittels dem benutzerdefinierten Parameter @start initialisiert. Die Werte können im Karteireiter Formel (Formula) eingegeben werden.

Weitere Informationen zum Parameter @start werden im Parameterblock erläutert.

Inhalt des loop-Abschnitts

if @auswahl == true
  z = z^@power + @myfunc1(z) + @myfunc2(z) + #pixel
else
  z = z^@power + @myfunc1(z) + #pixel
endif

Hier befinden sich zwei Iterationsgleichungen, die fortlaufend die komplexe Variable z berechnen. Die Auswahl der ersten Gleichung erfolgt, wenn der Parameter @auswahl == wahr, also ausgewählt wurde. Falls nicht, wird die zweite Gleichung verwendet.

In den Gleichungen befinden sich die Parameter @power, @myfunc1 sowie @myfunc2 deren Exponent bzw. deren Funktionen durch den Nutzer im Karteireiter Formel (Formula) eingegeben bzw. ausgewählt werden kann.

Weitere Informationen zu den Parametern @power, @myfunc1 sowie @myfunc2 werden in den Parameter- sowie den Funktionsblöcken erläutert.

Desweiteren befindet sich das vordefinierte Symbol #pixel in der Gleichung, welches die komplexen Koordinaten des berechneten Pixels zurückgibt.

Inhalt des bailout-Abschnitts

|z| <= @bailout

Der loop-Abschnitt wird solange iteriert, bis die Bedingung Betrag z kleiner gleich dem benutzerdefinierten Parameterwert @bailout erfüllt ist. Der Wert kann im Karteireiter Formel (Formula) geändert werden.

Nähere Informationen zum Parameter @bailout werden im Parameterblock erläutert.

Inhalt des default-Abschnitts

title = "MeinMandelbrot"
center = (-1, 0)
helpfile = "Formula1.txt"
helptopic = "Hilfe zu MeinMandelbrot"

Die Einstellung title beinhaltet den Namen der Formel, in diesem Fall MeinMandelbrot, der auch im Karteireiter Formel (Formula) angezeigt wird, in der Abbildung gelb markiert.

Die zweite Einstellung center legt die komplexen Koordinaten im Karteireiter Standort (Location) fest.

Mit den Einstellungen helpfile und helptopic könnt Ihr eine Hilfedatei, hier die Datei Formula1.txt, und einen speziellen Hinweistext zur Formel anbieten.

Der Inhalt der Hilfedatei

Die Hilfedatei wird durch Klick auf das Fragezeichen im Karteireiter Formel (Formula) geöffnet, siehe rote Markierung in der folgenden Abbildung.

Formeltitel und Aufruf der Hilfedatei

heading
  caption = "Wähle die Funktion(en)..."
  text = "cosh, sqr and zero für die Standard Mandelbrotmenge."
endheading

Mit Hilfe von Überschriften könnt Ihr Parameter- und Funktionsblöcke logisch mit caption gruppieren und mit Hilfe der Einstellung text genauer beschreiben. Sie werden für den Benutzer angezeigt, siehe folgendes Bild. Überschriften werden mit heading eingeleitet und mit endheading abgeschlossen.

Überschrift und Parameterblöcke im Karteireiter Formel

Anschließend folgt der erste Funktionsblock, der zunächst mit einer Überschrift eingeleitet wird.

heading
  text = "Erste Funktion"
endheading
func @myfunc1
  caption = "Funktion 1"
  default = zero()
  hint = "Wähle eine Funktion aus, um die Formel zu verändern."
endfunc

Funktionen werden in der Form [type] func <Parameter-Bezeichner> eingeleitet und mit endfunc beendet. Die Funktion ist vom Typ entweder ‘complex‘ oder ‘color‘. Wird der Typ nicht angegeben, so wird ‘complex‘ angenommen. Der Parameterbezeichner @myfunc1 ist identisch mit dem benutzerdefinierten Parameter aus dem loop-Abschnitt.

Die Einstellung caption spezifiziert den Parameter @myfunc1 genauer und default setzt den Standardwert der Funktion auf atanh. Mit hint wird ein kleiner Hinweistext erzeugt, der dann sichtbar ist, wenn Ihr den ?-Button oben in der Titelleiste des Werkzeugfensters Ebenen-Eigenschaften (Layer Properties) und anschließend auf den Parameter klickt.

Hinweistext

Der zweite Funktionsblock wird ebenfalls mit einer Überschrift eingeleitet. Im Gegensatz zum ersten Funktionsblock wird der zweite Funktionsblock @myfunc2 nur dann eingeblendet, wenn der Nutzer ein Häkchen in das Kontrollkästchen Funktion 2 nutzen? des Parameterblocks @auswahl macht. Der ist durch default = false standardmäßig ausgeblendet. Durch visible = @auswahl wird das Einblenden gesteuert.

Mit Hilfe der if-Bedingung im loop-Abschnitt wird nun die entsprechende Formel zum Berechnen des Fraktals herangezogen.

param @auswahl
  caption = "Funktion 2 nutzen?"
  default = false
endparam
heading
  text = "Zweite Funktion"
  visible = @auswahl
endheading
func @myfunc2
  caption = "Funktion 2"
  default = exp()
  hint = "Wähle eine Funktion aus, um die Formel zu verändern."
  visible = @auswahl
endfunc

Alle anderen Einstellungen sind wie beim vorangegangenen Funktionsblock. Hier die Liste aller Funktionen in Ultra Fractal.

Auch die Parameterblöck werden in der Form [type] param <Parameter-Bezeichner> eingeleitet und mit endparam beendet.

Die folgenden Parameterblöcke werden der Übersicht halber und in gewohnter Weise mit einer Überschrift eingeleitet.

heading
  caption = "...und Werte"
endheading

Der Parameter @start initialisiert in der Standardeinstellung den Real- und Imaginärteil der komplexe Variable z auf (0, 0). Die anderen Einstellungen wurden bereits weiter oben beschrieben.

param @start
  caption = "Startwert"
  default = (0,0)
  hint = "Mit dem Parameter Startwert kann die Mandelbrotmenge \
          verändert werden. Verwende (0, 0) für die Standard- \
          Mandelbrotmenge."
endparam

Der vordefinierte Parameter @power ist für den Exponenten unserer Gleichung zuständig. Für den Realteil beträgt der Exponent 2 und für den Imaginärteil 0.

param @power
  caption = "Exponent"
  default = (2,0)
  hint = "Dieser Parameter wird für den Exponenten der Formel \
          verwendet. Die Eingabe von 3, 4 und größer im Realteil, \
          lässt die Mandelbrotmenge runder werden. \
          Nicht-Integer-Werte sowie Nicht-Null-Werte im \
          Imaginärteil verzerren das Afelmännchen. \
          Benutzen Sie (2, 0) für die Standard-Mandelbrotmenge."
endparam

Der Ausstiegswert @bailout, ab wann die Iteration im loop-Abschnitt abgebrochen werden soll, ist vom Typ her eine Fließkommazahl und somit float. Der Standardwert default ist mit 1.0E20 und der Minimalwert min mit 1 festgelegt.

float param @bailout
  caption = "Bailout"
  default = 1.0e20
  min = 1.0

Ob ein Fließkommaparameter die exponentielle Interpolation nutzen soll oder nicht, kann mittels exponential eingestellt werden. Standardmäßig ist dieser Wert auf false voreingestellt. Ihr könnt diesen Wert später im Werkzeugfenster Zeitstrahl (Timeline) ändern.

Exponentielle Interpolation

Wenn Eure Formel auch in früheren Versionen von Ultra Fractal laufen soll, in denen die exponential-Einstellung nicht verfügbar war, testet Ihr das mit dem VER40-Symbol. Der Aufruf erfolgt durch die sogenannte Compiler-Direktive.

Mittels $ifdef VER40 wird die Version von Ultra Fractal abgefragt und sichergestellt, dass in Ultra Fractal 4 der Parameter exponentiell interpoliert wird. Beendet wird die Direktive mit $endif.

$ifdef VER40
  exponential = true
  ; In Ultra Fractal 4 stellt Ihr sicher, dass dieser Parameter
  ; exponentiell interpoliert wird.
$endif
  hint = "Dieser Parameter definiert, wie lange die Formel \
          iteriert wird und ob ein Pixel zur Mandelbrotmenge \
          gehört oder nicht. Entsprechend wird er eingefärbt. \
          Größere Werte liefern eine klarere Konturen; \
          Werte kleiner als 4 verzerren die Fraktale."
endparam

Der Vollständigkeit halber sollen die anderen Versionen nicht unerwähnt bleiben: ULTRAFRACTAL, VER20, VER30, VER40 sowie VER50.

Die Compiler-Direktiven lauten: $define, $undef, $ifdef, $else sowie $endif.

Inhalt des switch-Abschnitts

Um vom Fraktaltyp MeinMandelbrot zum Typ MeinJuliabrot schalten zu können, müsst Ihr in der Einstellung type den Formelbezeichner eintragen.

Die Einstellung für den Zielparameter @seed = #pixel sorgt dafür, dass das Schaltfeature abhängig vom Punkt ist, den der Nutzer innerhalb des Fraktalfensters klickte. Der Parameter in der Zielformel muss komplex sein, sonst wird die Einstellung ignoriert.

Abschließend werden die Einstellungen für die Parameter @power, @myfunc1, @myfunc2 und @bailout aus der Quellformel in die Zielformel kopiert. Dabei müsst Ihr sicherstellen, dass Quell- und Zielparameter gleich sind, ansonsten werden die Einstellungen ignoriert.

Parameter, die nicht explizit kopiert werden, erhalten voreingestellte Werte.

type = "MeinJuliabrot"
@seed = #pixel
@power = @power
@auswahl = @auswahl
@myfunc1 = @myfunc1
@myfunc2 = @myfunc2
@bailout = @bailout

Zielformel erstellen

Jetzt müsst Ihr nur noch die Zielformel schreiben. Hört sich kompliziert an, ist aber ganz einfach.

Dazu kopiert Ihr zunächst die Formel MeinMandelbrot und benennt diese in MeinJuliabrot um. Zu ändernde Stellen habe ich rot markiert.

MeinJuliabrot(XAXIS_NOPARM) {

Als nächstes ändert Ihr den Wert der komplexen Variable z im init-Abschnitt von

z = @start

in

z = #pixel

Anschließend werden die Iterationsgleichungen im loop-Abschnitt von

z = z^@power + @myfunc1(z) + @myfunc2(z) + #pixel

und

z = z^@power + @myfunc1(z) + #pixel

in

z = z^@power + @myfunc1(z) + @myfunc2(z) + @seed

und

z = z^@power + @myfunc1(z) + @seed

angepasst.

Als letztes müsst Ihr noch im switch-Abschnitt Änderungen von

type = "MeinJuliabrot"
@seed = #pixel
@power = @power
@auswahl = @auswahl
@myfunc1 = @myfunc1
@myfunc2 = @myfunc2
@bailout = @bailout

in

type = "MeinMandelbrot"
@power = @power
@auswahl = @auswahl
@myfunc1 = @myfunc1
@myfunc2 = @myfunc2
@bailout = @bailout

vornehmen.

Sicherlich fragt Ihr Euch jetzt, wie das Umschalten eigentlich funktioniert?

  1. In der Formel MeinMandelbrot wird zunächst der Startwert initialisiert und danach die Iterationsgleichungen ausgeführt.
  2. Dem vordefinierten Symbol #pixel werden die komplexen Koordinaten zurückgegeben.
  3. Klickt der Nutzer innerhalb des Fraktalfensters, so schaltet er zum Fraktaltyp MeinJuliabrot um, dem als Startwert @seed die komplexen Koordinaten von #pixel übergeben werden.
  4. Der Startwert für die Formel MeinJuliabrot wird mit den komplexen Koordinaten, die von #pixel übergeben wurden, initialisiert.
  5. Anschließend werden wie gewohnt die Iterationsgleichungen ausgeführt. Ein erneutes klicken in das Fraktalfenster schaltet wieder zum Fraktaltyp MeinMandelbrot zurück.

Hier die Datei formula1.ufm sowie die entsprechende Hilfedatei formula1.txt.

Ich wünsche Euch viel Spaß beim Experimentieren!

Dieser Artikel steht unter der Creative Commons Namensnennung-NichtKommerziell-KeineBearbeitung 3.0 Deutschland (CC BY-NC-ND 3.0) – Lizenz.

Creativ Commons