Hinweis: Wäre JavaScript aktiviert würden die Bilder in den Fraktal-Galerien als Popup erscheinen und zusätzliche Informationen würden eingeblendet....
Hinweis: Wäre JavaScript aktiviert würden die Bilder in den Fraktal-Galerien als Popup erscheinen und zusätzliche Informationen würden eingeblendet....
Wait...
3D-Fraktale
Julia-, Mandelbrot-,
Mandelbulb- und Mandelbox-Fraktale
Veränderte Mandelbrot & Julia-Fraktale
Im Abschnitt "Mandelbrot- und Julia-Fraktale" wurden die "normalen" Berechnungsformeln für Mandelbrot- und Julia-Fraktale beschrieben. Diese Formeln kann man aber in mehrfacher Hinsicht abwandeln, um noch deutlich anders aussehende 2D-/3D-Fraktale zu erhalten. Dieser Abschnitt wird naturgemäß etwas mathematik-lastiger und ist außerdem recht lang, weshalb ich ihn in eine eigene Seite ausgelagert habe. Zudem ist mir erst kürzlich aufgefallen, dass alle diese Gebilde extrem instabil sind und eigentlich nur durch die Verwendung hinreichend kleiner Werte für die Parameter MaxIter und BailOut überhaupt Punkte der Menge zugordnet werden (also eigentlich fälschlich). Daher sind die angegebenen Formeln mit entsprechender Vorsicht zu genießen...

Eine Möglichkeit besteht darin die Berechnungsformel komplett zu verändern. Ich habe bisher mit folgenden Varianten experimentiert:

Iteratoren:

"Iteratoren" nenne ich die Formeln die iterativ (maximal Max-Iter Schritte) berechnet wird um festzustellen, ob ein Punkt zum Fraktal gehört oder nicht. Ich habe mit folgenden Iteratoren experimentiert.
Name:

Formel:


Anmerkung:
DEFAULT:  
 
Z = (Z * Z) + C
 

 
 
Die normale Formel für Mandelbrot- und Julia-Fraktale
C_POW_Z_Z:
Z = C(Z*Z)



Z_Z_Z_C:
Z = (Z * Z * Z) + C


Z_SQRT_Z_PLUS_C:
Z = Z * sqrt(Z) + C



Z_SPLITPOW_C_POW_2:
Z = splitPow(Z,C) * splitPow(Z,C)

1)
Z_SPLITTANH_POW_2_PLUS_C:
Z = splitTanH(Z) * splitTanH(Z) + C

1)
C_SPLITPOW_Z_POW_2:
Z = splitPow(C,Z) + splitPow(C,C)
1)
Z_SPLITPOW_Z_SPLITLN:
Z = splitPow(Z,C) * splitLn(Z)
1)
C_C_PLUS_Z_SPLITLN:
Z = C * C + splitLn(Z)

1)
Z_SPLITPOW_2:
Z = splitPow(Z, 2) + C
1)
3D-Fraktale mit einem rechteckigen Querschnitt
Z_SPLITSINH_POW_2_PLUS_C:
Z = splitSinH(Z) * splitTanH(Z) + C
1)
Z_Z_SPLITLN_PLUS_C:
Z = Z * splitLn(Z) + C
1)
Z_SPLITSINH_Z_SPLITLN_PLUS_C:
Z = splitSinH(Z) * splitLn(Z) + C
1)
Z_SIN_Z_COS_PLUS_C:
Z = sin(Z) * cos(Z) + C


Z_Z_SPLITSINH_PLUS_C:
Z = Z * splitSinH(Z) + C
1)
Z_Z_SPLITTANH_PLUS_C:
Z = Z * splitTanH(Z) + C

1)
1) Nur für 3D-Fraktale, da die split-Operatoren nur für Quaternion-Zahlen definiert sind (s.u.)

Beispiele:
C_POW_Z_Z
"Starwars"

So interessant es hier auch aussieht, hat es sich leider - wie praktisch alle meine Abwandlungen - als vollkommen instabil erwiesen. Berechnet man mehr als nur ein paar Iterationen, bleibt von dem Fraktal so gut wie nichts mehr übrig... Dieses Fraktal wurde, wie gesagt, mit einer abgewandelten Formel (Z = C^(Z*Z)) und den folgenden weiteren Parametern berechnet:

C = (-0.5, 0.26, -0.35, 0.25)
Z = (x, y, z, 0.05)
Max-Iter = 6
Bailout = 2.0

Z_SPLITPOW_C_POW_2

Z_SPLITPOW_C_POW_2
C_POW_Z_Z
Z_SPLITPOW_C_POW_2
C_C_PLUS_Z_SPLITLN





C = (-0.4, 0-2, -0.2, -0.2); T = 0.005; Iterator = Z_SIN_S_COS_PLUS_C
"Orbit"

Bei diesem Fraktal weiß ich leider überhaupt nicht mehr, wie ich es genau berchnet habe. Vermutlich ist aber auch dieses Fraktal nicht wirklich stabil...



Z_SIN_Z_COS_PLUS_C

Z_Z_SPLITSINH_PLUS_C



Hier wurden einige spezielle Operatoren verwendet, die in den folgenden Kästen erklärt werden:

Split-Operatoren:

Die split-Operatoren zerlegen eine Quaternion-Zahl zunächst in zwei komplexe Zahlen, führen dann den eigentlichen Operator (also z.B. bei splitTanH den Tangens-Hyperbolicus) auf diesen komplexen Zahlen aus und fügen die resultierenden komplexen Zahlen wieder zu einem Quaternion zusammen.

Aus einem Quaternion
Q = (x, y, z, w)
entstehen so zwei komplexe Zahlen:
C1 = (real = x-w, imag = y+z)
und
C2 = (real = x+w, imag = y-z).

Umgekehrt werden aus zwei komplexen Zahlen
C1 = (real1, imag1)
und
C2 = (real2, imag2)
wieder ein Quaternion:
Q = ( x  =
 (real1  +
 real2)  / 2

y  =
 (imag1  +
 imag2)  / 2

z  =
 (imag1  -
 imag2)  / 2

w  =
 (real2  -
 real1)  / 2)

Damit lassen sich dann die normalen Operatoren für komplexe Zahlen anwenden (aus Platzgründen sind diese hier nicht im Detail dargestellt, sind aber im Web leicht zu finden). Im Falle eines Operators mit zwei Parametern (z.B. splitPow(X,Y)) wird jeweils die erste komplexe Zahl aus X mit der ersten komplexen Zahl aus Y und die zweite komplexe Zahl aus X mit der zweiten komplexen Zahl aus Y verrechnet.


Sqrt-Operator (Quadratwurzel) - für Quaternion-Zahlen:

Im Allgemeinen hat die Quadratwurzel aus einem Quaternion zwei mögliche Werte, wobei der eine der negierte Wert des anderen ist. Allerdings hat jedes negative rein-reale Quaternion (also ein Quaternion der Form Q = (x < 0, y = 0, z = 0, w = 0)) sogar eine unendliche Anzahl von Quadratwurzeln. Die verwendete Funktion gibt die positive Quadratwurzel auf der x-Achse für positive rein-reale Quaternion-Zahlen und die positive Quadratwurzel auf der y-Achse für negative rein-reale Quaternion-Zahlen zurück.

Bedinung: Formel:
Mit:
Q = (x > 0, y = 0, z = 0, w = 0) (positiv real):  sqrt(Q) = (sqrt(x), 0, 0, 0)



 
Q = (x < 0, y = 0, z = 0, w = 0) (negativ real): 
 sqrt(Q) = (0, sqrt(-x), 0, 0) 




Q = (x >= 0, y, z, w):
 sqrt(Q) = (m, y t, z t, w t) m = sqrt((r + x) / 2)
l = b / (2 m)
t = l / b

}
b = sqrt(y2 + z2 + w2)
r = sqrt(x2 + b2)
Q = (x < 0, y, z, w) (sonst):
 sqrt(Q) = (m, y t, z t, w t)
l = sqrt((r - x) / 2)
m = b / (2 l)
t = l / b



Power-Operator (Potenz) - für Quaternion-Zahlen:

pow(Q1,Q2) = exp(Q2 ln(Q1)).


Exp-Operator - für Quaternion-Zahlen:

Bedinung:  
 
Formel:
 

Mit:
Q = (x, y = 0, z = 0, w = 0) (real):

exp(Q) = (exp(x), 0, 0, 0)


 

sonst:
exp(Q) = (exp(x) cos(b), t y, t z, t w)
b = sqrt(y2 + z2 + w2)
t = exp(x) sin(b) / b


Ln-Operator (Logarithmus naturalis) - für Quaternion-Zahlen:

Im Allgemeinen hat die Quadratwurzel aus einem Quaternion zwei mögliche Werte, wobei der eine der negierte Wert des anderen ist. Jedes negative rein-reale Quaternion (also ein Quaternion der Form Q = (x < 0, y = 0, z = 0, w = 0)) hat eine unendliche Anzahl von Lösungen für den Logarithmus, die alle die Form ln(Q) = (ln(-x), pi a, pi b, pi c), wobei a, b und c zusammen einen Vektor (a, b, c), der Länge 1 bilden. Hier wurde einfach a = 1, b = 0, c = 0 gesetzt, um genau eine der möglichen Lösungen zu erhalten.

Bedinung:

Formel:


Mit:
Q = (x > 0, y = 0, z = 0, w = 0) (positiv real):  
 
ln(Q) = (ln(x), 0, 0, 0)

 
 

Q = (x < 0, y = 0, z = 0, w = 0) (negativ real):
ln(Q) = (ln(-x), pi, 0, 0)


Q = (x = 0, y = 0, z = 0, w = 0):
ln(Q) = nicht definiert


sonst:
ln(Q) = (ln(r), y t, z t, w t) b = sqrt(y2 + z2 + w2)
r = sqrt(b
2 + x2)
t = atan2(b, x) / b


Sinus- und Cosinus-Operatoren - für Quaternion-Zahlen:

Bedinung:
 
Formel:
 
 
Mit:
Q = (x, y = 0, z = 0, w = 0) (real):  

sin(Q)
 =
(sin(x), 0, 0, 0)




sonst:
sin(Q)
 =
 + 
(e0/2 sin(x), c0 y, c0 z, c0 w)
(e1/2 sin(x), c1 y, c1 z, c1 w)
b = sqrt(y2 + z2 + w2)
e0 = exp(-b)
e1 = exp(b)
c0 = -e0/(2 b) cos(x)
c1 = e1/(2 b) cos(x)

Bedinung:
 
Formel:
 
 
Mit:
Q = (x, y = 0, z = 0, w = 0) (real):  

cos(Q)
 =
(cos(x), 0, 0, 0)




sonst:
cos(Q)
 =
 + 
(e0/2 cos(x), c0 y, c0 z, c0 w)
(e1/2 cos(x), c1 y, c1 z, c1 w)
b = sqrt(y2 + z2 + w2)
e0 = exp(-b)
e1 = exp(b)
c0 = -e0/(2 b) sin(x)
c1 = e1/(2 b) sin(x)


Eine weitere Möglichkeit besteht darin auch die normalerweise verwendeten Operatoren, also den Plus- und  den Mal-Operator anders zu definieren - also eigentlich eine falsche Berechnungsvorschrift anzuwenden. Damit vervielfachen sich die Möglichkeiten nocheinmal und es kommen interessante Ergebnisse heraus. Im folgenden Kasten sind dafür einige willkürliche Beispiele zu finden:

Abgewandelte (falsche) Operatoren - für Quaternion-Zahlen

Multiplikation (C = A * B):
Name:

Fomel:

Mit:
"Inverse":  
 
 C.x = (A.x * B.x - A.w * B.w) / p + (A.y * B.y - A.z * B.z) / q
 C.y = (A.y * B.x + A.z * B.w) / p - (A.x * B.y + A.w * B.z) / q 
 C.z = (A.x * B.z + A.w * B.y) / q + (A.y * B.w + A.z * B.x) / p
 C.w = (A.y * B.z - A.z * B.y) / q - (A.x * B.w - A.w * B.x) / q

 
 
mit p = sqrt(B.x) - sqrt(B.w)
und q = sqrt(B.y) - sqrt(B.z)
"Diagonal-Power":  C.x = (A.x * B.x - A.y * B.y)4 - A.z * B.z - A.w * B.w
 C.y = A.x * B.y + (A.y * B.x + A.z * B.w)4 - A.w * B.z
 C.z = A.x * B.z + A.z * B.x + (A.w * B.y - A.y * B.w)4
 C.w = (A.x * B.w - A.z * B.y)4 + A.w * B.x + A.y * B.z


"Diagonal-Atan":  C.x = atan(A.x * B.x - A.y * B.y) - A.z * B.z - A.w * B.w
 C.y = A.x * B.y + atan(A.y * B.x + A.z * B.w) - A.w * B.z
 C.z = A.x * B.z + A.z * B.x + atan(A.w * B.y - A.y * B.w)
 C.w = atan(A.x * B.w - A.z * B.y) + A.w * B.x + A.y * B.z


"Absolute-Power":  C.x = |A.x||B.x| - |A.y||B.y| - |A.z||B.z| - |A.w||B.w|
 C.y = |A.x||B.y| + |A.y||B.x| + |A.z||B.w| - |A.w||B.z|
 C.z = |A.x||B.z| + |A.z||B.x| + |A.w||B.y| - |A.y||B.w|
 C.w = |A.x||B.w| + |A.w||B.x| + |A.y||B.z| + |A.z||B.y|




Beispiele:
C=(-0.9, 0.2, -0.2, 0.05) Z = (x, y, z, 0.05) x-Operator = diag-ATAN
Diagonal-Atan
"Diagonal-Atan"

Addition (C = A + B)
Name:
 
Formel:
"Inverse":  

 C.x = A.x - B.x 
 C.y = A.y - B.y
 C.z = A.z - B.z
 C.w = A.w - B.w


Für Mandelbrot- und Julia-Fraktale kann ja, wie schon erwähnt, gezeigt werden, dass sich Z immer weiter vom Koordinatenursprung entfernt (gegen unendlich strebt), wenn Z (irgendwann im Laufe der Iteration) einen euklidischen Abstand von 2.0 zum Koordinatenursprung überschreitet. Man kann die Iteration daher in einem solchen Fall abbrechen - der Berechnete Punkt gehört sicher nicht der Fraktalmenge an. Sobald man die Formel verändert gilt das natürlich nicht mehr. Da es im allgemeinen aufwändig ist, mathematisch zu beweisen, wohin eine Reihe strebt, um daraus einen "korrekten" Bailout-Parameter abzuleiten, muss hier u.U. mit dem Parameter etwas experimentiert werden. Sieht man ein rundes 2D- bzw. kugelrundes 3D-Fraktal, wurde dessen Berechnung vermutlich nur durch den Bailout-Parameter begrenzt - wählt man diesen größer, wird auch das Fraktal bis weiter entfernt vom Ursprung berechnet. Dennoch können auch solche "Kugelfraktale" hübsch aussehen, wenn sie entsprechend eingefärbt wurden.

Noch eine Variante besteht darin, statt eines einzigen C-Wertes mehrere C-Werte festzulegen und bei der ersten Iteration C0, bei der zweiten Iteration C1, usw. zu verwenden. Ist Max-Iter größer als die Anzahl der C-Werte fängt man einfach wieder bei C0 an. Solange man nicht auch noch eine der anderen Abwandlungen verwendet sollte hier übrigens der Bail-Out-Parameter von 2 weiterhin korrekt sein.
Multi-C

Da ich (aus Faulheit) nur einen C-Wert vorgeben möchte, werden die anderen Werte zurzeit automatisch festgelegt:

Von C0 abgeleitete C-Werte:
C1 = (C0.w, C0.x, C0.y, C0.z)
C2 = (C0.z, C0.w, C0.x, C0.y)
C3 = (C0.y, C0.z, C0.w, C0.x)

C4 = (C0.w, C0.z, C0.y, C0.x)
C5 = (C0.x, C0.w, C0.z, C0.y)
C6 = (C0.y, C0.x, C0.w, C0.z)
C7 = (C0.z, C0.y, C0.x, C0.w)

Beispiele:
Multi-C-Fraktal
Multi-C-Fraktal

Wie alle Fraktale auf dieser Seite, wurde auch dieses noch ohne Abstandsmaß und mit einer alten Version meines Renderers berechnet. Trotzdem sind schon eine leichte Blauverschiebung entfernter Bereiche und eine recht "ordentliche" Tiefenunschärfe enthalten (man gönnt sich ja sonst nichts :-). Denn ansonsten hat der "Multi-C-Ansatz" leider nicht so "tolle" Ergebnisse geliefert, wie ich anfangs gehofft hatte...

"Multi-C-Fraktal"

Patrick Rammelt, 11/2010
)