Eines meiner Dokumente, was sich mit Fraktalen beschäftigt, behandelt IFS-Fraktale (Iterated Function Systems). Ein iteriertes Funktionensystem bedeutet wiederholte Abbildungen eines Raumes in sich selbst, auf diese Weise lassen sich bekannte Fraktale wie das Sierpinski Dreieck, die Koch-Kurve und der Barnsley-Farn erzeugen.

Da ich in LaTeX schreibe, stellt sich mir die Frage: wie lassen sich IFS-Fraktale direkt in LaTeX erzeugen und ausgeben?

Mögliche Tools wären beispielsweise LuaTeX, expl3, PGF und PostScript für die Berechnung sowie TikZ, PSTricks, pgfplots und mplib für die Ausgabe. Es ließen sich natürlich auch MetaPost und Asymptote integrieren, auch wenn "ein bisschen extern".

Ich werde mit einer Antwort mit LuaTeX und pgfplots für den Barnsley-Farn beginnen.

Wer schafft alternative Wege für dieses und andere IFS-Fraktale?

gefragt 29 Jun '14, 12:29

stefan's gravatar image

stefan ♦♦
18.4k163148
Akzeptiert-Rate: 50%


Das folgende kleine Dokument berechnet und druckt einen Barnsley-Farn mittels des sog. Chaos Games: zufällig ausgewählte Transformationen werden wiederholt angewendet.

Hier verwende ich Lua zur Berechnung und pgfplots für die Ausgabe. Daher wird LuaLaTeX benötigt. Die Matrix m enthält die Koordinaten für die affinen Transformationen sowie ihre Wahrscheinlichkeiten, die dann summiert separat in der Wahrscheinlichkeitsmatrix pm abgelegt werden, damit ich nicht in der Schleife mehr addieren muss. Die Matrix-Schreibweise vereinfacht Veränderungen der Parameter.

Vorsicht, das Übersetzen dauert sehr lang! Ich habe 100000 Punkte berechnen lassen, wer das hier mal laufen lassen will, sollte zunächst einen viel kleineren Wert nehmen.

Open in writeLaTeX
Code, hier editierbar zum Übersetzen:
\documentclass[tikz]{standalone}
\usepackage{pgfplots}
\usepackage{luacode}
\begin{luacode*}
function barnsley(iterations,options)
local x = math.random()
local y = math.random()
local m = {
0.0, 0.0, 0.0, 0.16, 0.0, 0.0, 0.01,
0.85, 0.04, -0.04, 0.85, 0.0, 1.6, 0.85,
0.2, -0.26, 0.23, 0.22, 0.0, 1.6, 0.07,
-0.15, 0.28, 0.26, 0.24, 0.0, 0.44, 0.07
}
local pm = { m[7], m[7] + m[14], m[7] + m[14] + m[21] }
if options ~= [[]] then
tex.sprint("\\begin{axis}[hide axis]\\addplot["
.. options .. "] coordinates{")
else
tex.sprint("\\addplot coordinates{")
end
for i=1, iterations do
p = math.random()
if p < pm[1] then
case = 0
elseif p < pm[2] then
case = 1
elseif p < pm[3] then
case = 2
else
case = 3
end
newx = (m[7*case+1] * x) + (m[7*case+2] * y) + m[7*case+5]
y = (m[7*case+3] * x) + (m[7*case+4] * y) + m[7*case+6]
x = newx
tex.sprint("("..x..","..y..")")
end
tex.sprint("};\\end{axis}")
end
\end{luacode*}
\begin{document}
\begin{tikzpicture}
 
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Barnsley-Farn

Die Matrix kann man verändern, um Fraktale zu erhalten, die mehr einem Baum, einem Busch oder anderen Farnen ähneln. Beispielsweise mit Werten von der oben verlinkten Wikipedia-Seite (m.E. original von David Nicolls)

Open in writeLaTeX
0.0, 0.0, 0.0, 0.25, 0.0, -0.14, 0.02,
0.85, 0.02, -0.02, 0.83, 0.0, 1.0, 0.84,
0.09, -0.28, 0.3, 0.11, 0.0, 0.6, 0.07,
-0.09, 0.28, 0.3, 0.09, 0.0, 0.7, 0.07
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Leptosporangiate-Farn

Open in writeLaTeX
0.0, 0.0, 0.0, 0.25, 0.0, -0.4, 0.02,
0.95, 0.005, -0.005, 0.93, -0.002, 0.5, 0.84,
0.035, -0.2, 0.16, 0.04, -0.09, 0.02, 0.07,
-0.04, 0.2, 0.16, 0.04, 0.083, 0.12, 0.07
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Thelypteridaceae-Farn

Mit einer einfacheren Matrix und damit leicht verkürztem Code erhält man ein Sierpinski-Dreieck:

Open in writeLaTeX
Code, hier editierbar zum Übersetzen:
\documentclass[tikz]{standalone}
\usepackage{pgfplots}
\usepackage{luacode}
\begin{luacode*}
function ifs(iterations,options)
local x = math.random()
local y = math.random()
local m = {
0.5, 0, 0, 0.5, 0, 0, 0.3333,
0.5, 0, 0, 0.5, 0.25, 0.5, 0.3333,
0.5, 0, 0, 0.5, 0.5, 0, 0.3333,
}
local pm = { m[7], m[7] + m[14], m[7] + m[14] }
if options ~= [[]] then
tex.sprint("\\begin{axis}[hide axis]\\addplot["
.. options .. "] coordinates{")
else
tex.sprint("\\addplot coordinates{")
end
for i=1, iterations do
p = math.random()
if p < pm[1] then
case = 0
elseif p < pm[2] then
case = 1
else
case = 2
end
newx = (m[7*case+1] * x) + (m[7*case+2] * y) + m[7*case+5]
y = (m[7*case+3] * x) + (m[7*case+4] * y) + m[7*case+6]
x = newx
tex.sprint("("..x..","..y..")")
end
tex.sprint("};\\end{axis}")
end
\end{luacode*}
\begin{document}
\begin{tikzpicture}
\directlua{ifs(20000, [[color=black, only marks,
mark size = 0.05pt]])}
\end{tikzpicture}
 
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Sierpinski-Dreieck

Analog kann man einen Sierpinski-Teppich erhalten, und in 3D einen Menger-Schwamm aka Menger sponge. Bei letzterem stellt sich dann die Frage einer guten dreidimensionalen Darstellung.

Permanenter link

beantwortet 29 Jun '14, 12:39

stefan's gravatar image

stefan ♦♦
18.4k163148
Akzeptiert-Rate: 50%

bearbeitet 29 Jun '14, 14:35

PSTricks bietet auch einen Barnsley-Farn, in Postscript samt darin codierten Transformations-Parameter und Wahrscheinlichkeiten. Direkt in LaTeX lässt sich daher nicht so leicht experimentieren, doch es ist eine sehr gute Demonstration. Und man kann ja selber auch den Postscript-Code übernehmen und ändern.

Anwendung, einfach mit XeLaTeX zu übersetzen oder auch durch LaTeX im DVI Modus mit nachfolgendem dvips und ggf. ps2pdf:

Open in writeLaTeX
Code, hier editierbar zum Übersetzen:
\documentclass{standalone}
\usepackage{pstricks}
\usepackage{pst-fractal}
\begin{document}
\begin{pspicture}(-3,0)(3,11)
\psFern[scale=30, maxIter=200000, linecolor=green]
\end{pspicture}
\end{document}
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Der eigentliche Code steht in pst-fractal.pro:

Open in writeLaTeX
/tx@Fern { %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% \pst@fractal@scale
% \pst@tempA
% \pst@fractal@maxIter
% \pst@fractal@radius
% \pst@number\pslinewidth
% { \pst@usecolor\pslinecolor }
/setColor ED
SLW
/radius ED
/maxIter ED
translate
dup scale
/m1 [ 0.00 0.00 0.00 0.16 0.00 0.00 ] def
/m2 [ 0.85 -0.04 0.04 0.85 0.00 1.60 ] def
/m3 [ 0.20 0.23 -0.26 0.22 0.00 1.60 ] def
/m4 [ -0.15 0.26 0.28 0.24 0.00 0.44 ] def
1 setlinecap
setColor
0 0 % start point
maxIter cvi {
% get a transformation matrix probabilistically
/r rand 100 mod def
r 1 lt { /m m1 def }{ r 86 lt
{ /m m2 def }{ r 93 lt {
/m m3 def }{ /m m4 def } ifelse } ifelse } ifelse
% Make a linear transformation, then
% plot a point at current location
m transform 2 copy radius 0 360 arc
stroke
} repeat
} def
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Barnsley-Farn

Permanenter link

beantwortet 29 Jun '14, 12:50

stefan's gravatar image

stefan ♦♦
18.4k163148
Akzeptiert-Rate: 50%

bearbeitet 29 Jun '14, 12:55

Deine Antwort
[Vorschau ausblenden]

Folgen dieser Frage

Per E-Mail:

Wenn sie sich anmelden, kommen Sie für alle Updates hier in Frage

Per RSS:

Antworten

Antworten und Kommentare

Frage-Themen:

×731
×298
×28
×5

gestellte Frage: 29 Jun '14, 12:29

Frage wurde gesehen: 13,966 Mal

zuletzt geändert: 29 Jun '14, 14:35

Willkommen, erstes Mal hier? Schau mal unter FAQ!

×