Ultra Fractal bringt von sich aus schon eine Vielzahl an Standardformeln mit. Darüber hinaus können zahlreiche Formeln aus dem Internet geladen werden. Doch irgendwann wollt Ihr Eure eigenen Ideen umsetzen oder einfach nur experimentieren.
Mit diesem Tutorial möchte ich Euch zeigen, wie Ihr mit Hilfe des Formel-Editors Eure eigenen Formeln entwickeln könnt. Je nach Aufgabentyp wird zum Berechnen von Fraktalen zwischen folgenden Formeldateien unterschieden:
- Fraktalformeln
.ufm
(fractal formula files), - Kolorierungsalgorithmen
.ucl
(coloring algorithm files) sowie - Transformationen
.uxf
(transformation files).
Aufgrund dieses Aufgabentyps gliedert sich das Tutorial in folgende Teile:
- Grundlegende Konventionen (Ausdrücke, Variablen, Typen, Schleifen etc.),
- Erstellen von Fraktalformeln,
- Erstellen von Kolorierungsalgorithmen sowie
- Erstellen von Transformationen.
Weitergehende Informationen bekommt Ihr in der Ultra Fractal Hilfe.
Grundlegende Konventionen
Wie in der Umgangssprache gelten für eine Programmiersprachen gewisse grammatikalische Regeln. Wenn Ihr diese Regeln ignoriert, dann ist der Compiler nicht in der Lage, die Anweisungen der Formeldatei korrekt auszuführen und gibt Euch eine Fehlermeldung aus.
Ausdrücke
Einige Abschnitte (init
und loop
) können Anweisungen in Form von Ausdrücken enthalten. Darüber hinaus können auch Variablen, Parameter und Konstanten einen Ausdruck darstellen. Die Kombination von Operatoren und Werten bezeichnet man als Ausdrücke.
Ausdrücke können in Programmen an verschiedenen Stellen verwendet werden:
- auf der rechten Seite von Zuweisungen
- im Aufruf von Funktionen
- in Bedingungen
z = z^@power + #pixel
e1 = sqrt(2 * log(cabs(z1)) * cabs(z1) / cabs(o1)) * @zscale
if(real(z2) > 0.0)
Datentypen und Datentypenkompatibilität
Die oben beschriebenen Ausdrücke können vom verschiedenen Typ sein. In Ultra Fractal gibt es folgende Typen:
b o o l
Wenn zwei Ausdrücke miteinander verglichen werden, so können sie nur zwei Werte annehmen: true
bzw. false
3 < 4 ; true
i n t
Die Integerwerte liegen Werte im Bereich von -2.147.483.648 bis 2.147.483.647 und sie werden zum Zählen sowie für arithmetische Operationen benötigt.
-3, 2
f l o a t
Mithilfe von Fließkommazahlen können gebrochene Zahlen dargestellt werden; ihre Präzision ist praktisch unbegrenzt.
-3.734, 2.5e8
c o m p l e x
Komplexe Zahlen werden durch komplexe Ausdrücke repräsentiert, die aus zwei Fließkommazahlen bestehen. Sie ermöglichen fraktale Berechnungen.
(1.4, 3)
= 1.4+3i
c o l o r
Mit diesem Ausdruck, der eine Farbe repräsentiert, können Operationen durchgeführt und in color-Variablen gespeichert werden. Eine Farbe wird entsprechend den Farbkomponenten Rot, Grün, Blau und Alpha-Kanal (Opazität) intern aus vier Fließkommazahlen zusammengesetzt. Die Werte liegen zwischen 0
und 1
. Dieser Typ ist nur für direkte Kolorierungsalgorithmen vorgesehen.
Wenn zwei Ausdrücke unterschiedlichen Datentyps miteinander berechnet werden, dann erhält das Ergebnis den höherwertigen Datentyp der Einzelausdrücke.
Im folgenden Beispiel ist das Ergebnis von 3 + 2.1
vom Typ float, da der Wert 2.1
(float) höherwertiger ist, als der Wert 3
(int). Der Datentyp complex ist höherwertiger als der Typ float.
Der Compiler kann nur in höhere Datentypen umwandeln. Das folgende Beispiel würde in eine Fehlermeldung münden:
int i = 3 / 2
.
Konstanten
Boole’sche Konstanten
Sie sind vom Typ ‘bool‘ und es gibt zwei Konstanten: true
und false
.
Integer-Konstanten
Sie sind vorzeichenbehaftete Zahlen vom Typ ‘int‘ und liegen im Bereich von -2.147.483.648 bis 2.147.483.647.
-23
Fließkomma-Konstanten
Sie sind vom Typ ‘float‘ und bestehen einer vorzeichenbehafteten Mantisse, optional gefolgt von einem ‘E‘ sowie einem vorzeichenbehafteten Exponent, der die Zehnerpotenz darstellt. Der Exponent liegt im Bereich von -4.931 bis 4.931.
98.283E-3 ; 0,098283
Komplexe Konstanten
Sie sind vom Typ ‘complex‘ und bestehen aus zwei in Klammern stehenden Fließkommazahlen, die durch ein Komma voneinander getrennt sind. Imaginäre Zahlen können alternativ durch ein dahinterstehendes i gekennzeichnet werden.
2 + 1.63i ; (2, 1.63)
Farb-Konstanten
Sie sind vom Typ ‘color‘ und werden erzeugt, indem konstante Argumente den rgb-, rgba-, hsl- und hsla-Funktionen zugewiesen werden.
hsla(0, 0, 0.5, 0.5) ; transparent rot
Variablen
Formeln setzen sich aus einer Vielzahl von Berechnungen zusammen, deren Ergebnisse mit Hilfe von Variablen im Speicher bewahrt werden. Bezeichner, die mit einem Buchstaben beginnen müssen, verweisen auf Variablen.
x
MeineVariable
var_32
Bezeichner können sowohl in Klein- als auch in Großbuchstaben geschrieben werden, es dürfen jedoch keine Schlüsselworte verwendet werden (siehe letzte Überschrift). Diese sind ausschließlich für den Compiler reserviert und erzeugen bei Verwenden eine Fehlermeldung.
Bevor Variablen gelesen werden können, muss in sie hineingeschrieben werden. Dazu wird der Zuweisungsoperator ‘=
‘ verwendet.
z = @start
Eine Variable wird angelegt, wenn zum ersten Mal in sie hineingeschrieben wird. Die Voreinstellung für den Variablentyp ist ‘complex‘. Durch Vorstellen eines Typenschlüsselwortes (bool, int, float oder complex) kann der Variablentyp geändert werden. Es ist auch möglich, eine Variable vor dem Benutzen zu deklarieren.
int i
i = 10
complex y = (0,0)
Zuweisungen können ihrerseits wieder Ausdrücke sein, deren Resultate wiederum zugewiesen werden können. Den Werten x
und y
wird der Wert 1
zugewiesen.
x = y = 1
Um Variablen auszulesen, wird der Bezeichner des Ausruckes verwendet. Der Wert x
wird ausgelesen und im Wert y
gespeichert.
y = x
Auch folgende Berechnung ist möglich:
y = x * 3 + 7
Parameter
Damit ihr die Formeln anpassen könnt, ohne sie neu zu schreiben, werden Parameter benutzt. Diese werden wie Variablen benutzt, allerdings mit zwei Ausnahmen: es kann nicht in sie hineingeschrieben werden und es muss das @
vorangestellt werden, damit der Compiler sie als Parameter erkennt.
MeinMandelbrot(XAXIS_NOPARM) {
init:
z = @start
loop:
z = z^@power + #pixel
bailout:
|z| <= @bailout
Die hier benutzten Parameter @start
, @power
und @bailout
erscheinen nun im Karteireiter Formel (Formula), in denen ihr entsprechende Werte eintragen und somit das Aussehen des Fraktals beeinflussen könnt.
Der Parametertyp ist auf ‘complex‘ voreingestellt, der jedoch im param
-Block des default
-Abschnitts der Formel verändert werden kann. In diesen param
-Blöcken könnt ihr weitere Parameteraufzählungen spezifizieren.
default:
title = "MeinMandelbrot"
center = (-0.5, 0)
helpfile = "Uf*.chm"
helptopic = "Html\formulas\standard\mandelbrot.html"
param start
caption = "Starting point"
default = (0,0)
hint = "The starting point parameter..."
endparam
param power
caption = "Power"
default = (2,0)
hint = "This parameter sets the exponent..."
endparam
float param bailout
caption = "Bailout value"
default = 4.0
min = 1.0
hint = "This parameter defines..."
endparam
}
Auf diese Weise könnt ihr Parameter für Benutzerfunktionen erstellen, die wie normale Funktionen angewendet werden können, jedoch mit der Ausnahme, dass ihr die aktuelle Funktion aus einer Liste weiterer Funktionen auswählen könnt.
Hier eine Beispiel mit geändertem loop
-Block:
loop:
z = z^@power + @myfunc(z) + #pixel
Der hier verwendete Parameter @myfunc
sorgt im Karteireiter Formel (Formula) dafür, dass nun eine Drop-Down-Liste mit einer Reihe weiterer Funktionen (sin, sqr, ident etc.) erscheint.
Die Parameteraufzählungen werden im func
-Block des default
-Abschnitts genauer spezifiziert.
heading
caption = "Change Function"
endheading
func myfunc
caption = "first"
default = atanh()
hint = "Select a function to change the formula."
endfunc
Zum Abschluss seien noch einige Hinweise aus der Hilfedatei von Ultra Fractal zitiert:
- Es ist zwar möglich in Parameter hineinzuschreiben, aber dies wird nicht empfohlen und kann Ihre Formel langsamer machen. Diese Möglichkeit wird nur aus Kompatibilitätsgründen zu alten Fractint-Formeln bereitgestellt.
- Es gibt sechs vordefinierte Parameter: p1…p6, dazu vier vordefinierte Funktionen: fn1…fn4. Sie brauchen bei diesen Parametern und Benutzerfunktionen das Präfix ‘@’ nicht benutzen. Es wird dennoch empfohlen, dass Sie stattdessen ihre eigenen Namen benutzen (mit dem ‘@’-Präfix), damit die Formeln besser zu verstehen sind.
- Die ‘param’ und ‘func’-Blöcke stellen zusätzlich Einstellungen zum Ändern der Werte für Benutzerfunktionen und der Parameter ‘caption’, ‘minimum’ und ‘maximum’ bereit. Zusätzlich können kleine Hilfe-Texte angegeben werden.
- Parameter werden im User-Interface solange alphabetisch sortiert, bis Sie einen ‘param’-Block für jeden Parameter angeben. In diesem Fall erscheinen die Parameter in der Reihenfolge der ‘param’-Blocks in der Formel-Datei.
- Im User-Interface können Sie durch zusätzliche Überschriften ebenfalls Parameter gruppieren.
Arrays
Ein Array ist eine Datenstruktur, die vom Programmierer selbst definiert wird und in der er mehrere Werte eines Datentyps ablegen kann. Bevor ihr das Array nutzen könnt, müsst ihr es deklarieren.
Der in eckigen Klammern stehende Index muss ein Integerwert zwischen 0
und der Anzahl der Elemente minus 1
sein.
int MeinArray[23]
Die Elemente in diesem Array könnt ihr wie normale Variablen nutzen. Es können auch mehrdimensionale Arrays deklariert warden, indem mehrere Werte innerhalb der eckigen Klammern stehen. Der Wert jeder Dimension muss ein konstanter Integerausdruck sein.
Parameter und die meisten vordefinierten Symbole sind als Konstaten verwendbar.
Farbe[255, 255, 255]
bool flags[#width, #height]
a[5, 10 – 2] = 1.5
Zu beachten ist, dass das Array nicht bei der Deklaration initialisiert wird. Stattdessen müssen die Elemente des Arrays explizit initialisiert werden, bevor auf sie zugegriffen wird.
Bedingungen
Gewisse Programmteile sollen nur ausgeführt werden, wenn bestimmte Kriterien erfüllt sind. Basis dieser Entscheidungen sind die sogenannten if-Statements.
Die Syntax lautet wie folgt:
if <Boole'scher Ausdruck>
<Statements>
[elseif <Boole'scher Ausdruck>
<Statements>]
[else
<Statements>]
endif
Der Teil zwischen den eckigen Klammern ist optional.
Bool’sche Ausdrücke können mittels Vergleichsoperatoren verglichen bzw. durch logische Operatoren miteinander verknüpft werden. (siehe Operatoren)
if 8 > 4 && 8 > 2
x = 8
elseif 4 > 2
x = 4
else
x = 2
endif
Die obige Konstruktion kann so gelesen werden: “Wenn die Bedingung 8 größer 4 UND 8 größer 2 erfüllt ist, dann (und nur dann) ist x gleich 8. Sonst wenn die Bedingung 4 größer 2 erfüllt ist, dann (und nur dann) ist x gleich 4, sonst ist x gleich 2.”
Ihr könnt auch if-Statements so oft ineinander verschachteln wir ihr wollt, nur verliert dabei nicht irgendwann den Überblick.
Schleifen
In Ultra Fractal existieren zwei Konstrukte für Schleifen, zum Einen die while-Schleife und zum Anderen die repeat-Schleife.
Die Syntax beider Schleifen lautet wie folgt:
while <Boole'scher Ausdruck>
<Statements>
endwhile
repeat
<Statements>
until <Boole'scher Ausdruck>
Im Gegensatz zum if-Statement, das die Anweisung bei erfüllter Bedingung nur einmal ausgeführt und anschließend das Programm fortsetzt, wird bei der while-Schleife nach Ausführen der Anweisung wieder zurück zur Schleifenbedingung gesprungen und so lange wiederholt, wie der Bool’sche Ausdruck wahr ist. Ist der Bool’sche Ausdruck dagegen falsch, werden die Anweisungen gar nicht erst ausgeführt.
Die repeat-Schleife wiederholt die Anweisung so lange, bis der Bool’sche Ausdruck wahr wird.
Es ist wichtig dafür zu sorgen, dass Schleifen nicht nur bei Bedarf aufgerufen, sondern vor allem auch wieder abgebrochen werden.
Nachfolgend zwei Beispiele zum Ermitteln der Fakultät von 23.
int n = 23
float x = 1
while (n > 1)
x = x * n
n = n - 1
endwhile
int n = 23
float x = 1
if n > 1
repeat
x = x * n
n = n - 1
until n == 1
endif
Auch Schleifen könnt ihr beliebig oft verschachteln.
Schlüsselworte
Schlüsselworte sind Wörter, die ausschließlich dem Compiler vorbehalten sind und dürfen in Parametern sowie Variablen nicht verwendet werden. Hier die Liste der Schlüsselworte:
bool
color
complex
else
elseif
endfunc
endheading
endif
endparam
endwhile
false
float
func
heading
if
int
param
repeat
true
until
while
Ich wünsche Euch viel Spaß!
Formeln schreiben – Teil 1 by Oliver Konow is licensed under CC BY-NC-ND 4.0
Schreibe einen Kommentar