1.6 Przykłady w języku Julia
Tworząc fraktale pewne operacje musimy powtarzać w nieskończoność, lub przynajmniej bardzo długo. Świetnie się do tego nadają wydajne, elastyczne i bardzo bardzo szybkie języki programowania. Takim właśnie językiem jest Julia. Interpreter tego języka i dokumentację można pobrać ze strony [https://julialang.org/]. Poniżej prezentujemy kilka informacji, które pomogą w zrozumieniu kolejnych przykładów.
- Poniższe przykłady korzystają z biblioteki
Plots
, podstawowej biblioteki dla języka Julia. Funkcjaplot()
z tej biblioteki tworzy pusty wykres. Można do niego dorysować kolejne figury funkcjąplot!()
. W poniższych przykładach tak będziemy tworzyć dodatkowe wypełnione wielokąty, trójkąty i kwadraty. - Julia to język bardzo przyjazny operacjom matematycznym, można bez dodatkowych modułów korzystać z funkcji matematycznych, takich jak
sqrt()
. Operatory arytmetyczne takie jak+
czy/
działają zarówno dla liczb jak i dla wektorów. - Aby kod był bardziej czytelny korzystamy z rekurencji, a więc konstrukcji, w której funkcja, sama się wywołuje. Nowe funkcje definiuje się z użyciem słowa
function
. W przypadku krótszych funkcji można stosować uproszczoną definicje z operatorem=
. Z krótszego sposobu skorzystamy definiując funkcjeline
,triangle
,square
.
1.6.1 Kurz Cantora
Rysowanie fraktali rozpocznijmy od Kurzu Cantora. Wykorzystamy do tego rekurencyjną funkcję dust
, która przyjmuje trzy argumenty: x
– początek fraktala, scale
– wielkość fraktala oraz depth
– aktualny poziom zagnieżdżenia fraktala.
# Pakiet z funkcjami graficznymi.
using Plots
# Funkcja definiująca odcinek.
line(x, scale) = Shape([x, x+scale], [0, 0])
# Rekurencyjna funkcja do rysowania kurzu.
# Jeżeli depth=1, to rysujemy odcinek, jeżeli depth>1,
# to rysujemy dwa kurze Cantora obok siebie.
function dust(x, scale, depth=1)
if depth == 0
plot!(line(x, scale), color=:black, legend=:false)
else
dust(x, scale/3, depth - 1)
dust(x + scale*2/3, scale/3, depth-1)
end
end
# Czyścimy ekran i zaczynamy rysowanie kurzu.
plot(0, xlim=(-0.1,1.1), ylim=(-0.1,0.1), axis=nothing)
dust(0.0, 1.0, 4)
1.6.2 Trójkąt Sierpińskiego
Czas na kultowy trójkąt Sierpińskiego. Aby go narysować wykorzystamy rekurencyjną funkcję sierpinski()
, która przyjmuje trzy argumenty: x
, y
– miejsce od którego należy rysować fraktal, scale
– wielkość fraktalu oraz depth
aktualny poziom zagnieżdżenia fraktala.
triangle(x, y, scale) = Shape([x, x+scale, x+scale/2, x],
y+scale*sqrt(3)/2, y])
[y, y,
# Rekurencyjna funkcja do rysowania trójkąta Sierpińskiego.
# Jeżeli depth=1, to rysujemy trójkąt używając funkcji triangle(),
# jeżeli depth>1. to rysujemy trzy trójkąty Sierpińskiego.
function sierpinski(x, y, scale, depth=1)
if depth==0
plot!(triangle(x,y,scale),color=:black,legend=:false)
else
sierpinski(x, y, scale/2, depth-1)
sierpinski(x+scale/2, y, scale/2, depth-1)
sierpinski(x+scale/4,y+sqrt(3)*scale/4,scale/2,depth-1)
end
end
plot(0, xlim=(0,1), ylim=(0,1), axis=nothing)
sierpinski(0, 0, 1, 6)
1.6.3 Dywan Sierpińskiego
Konstrukcja fraktala zaproponowana przez Wacława Sierpińskiego może być powtórzona dla innych kształtów.
square(x, y, w) = Shape([x, x+w, x+w, x], [y, y, y+w, y+w])
# Wykorzystujemy funkcje square zdefiniowaną powyżej aby narysować kwadrat.
function carpet(x, y, scale, depth=1)
if depth==0
plot!(square(x,y,scale), color=:black, legend=:false)
else
carpet(x, y, scale/3, depth-1)
carpet(x, y+scale, scale/3, depth-1)
carpet(x, y+2scale, scale/3, depth-1)
carpet(x+scale, y, scale/3, depth-1)
carpet(x+scale, y+2scale, scale/3, depth-1)
carpet(x+2scale, y, scale/3, depth-1)
carpet(x+2scale, y+scale, scale/3, depth-1)
carpet(x+2scale, y+2scale, scale/3, depth-1)
end
end
plot(0, xlim=(0,3), ylim=(0,3), axis=nothing)
carpet(0.0, 0.0, 1.0, 5)