3.6 Przykłady w języku Julia

3.6.1 Trójkąt Sierpińskiego raz jeszcze

Poniższy kod odtwarza konstrukcję trójkąta Sierpińskiego przedstawioną w tym rozdziale. W macierzy triangle definiujemy trzy wierzchołki trójkąta, a w obiekcie point umieszczamy współrzędne punktu startowego dla konstrukcji fraktala. Następnie w pętli przesuwamy punkt w kierunku losowego wierzchołka.

  1. \(x' = x/2\), \(y' = y/2\) (lewy róg)
  2. \(x' = x/2 + \frac 12\), \(y' = y/2\) (prawy róg)
  3. \(x' = x/2 + \frac 14\), \(y' = y/2 + \frac{\sqrt{3}}2\) (górny róg)
using Plots

# Liczba kroków, wierzchołki trójkąta i kolory dla transformacji.
N = 100000 
triangle = [0 0; 0.5 2; 1.5 0.5] 
col = ["red" "green" "blue"]
point = [0.1 0]

# Macierz na kolejne punkty trójkąta Sierpińskiego.
points = zeros(N, 2) 
cols = String[]

# Wektor cols zbiera kolory odpowiadające wylosowanym
# transformacjom a macierz coords zbiera współrzędne 
# pióra po każdym skoku.
for i in 1:N
  ind = rand(1:3,1)
  append!(cols, col[ind]) 
  point = (point + triangle[ind, :])/2
  coords[i,:] = point
end

scatter(coords[:,1], coords[:,2], color=cols, 
        legend=:false, markersize=2, axis=nothing)

3.6.2 Paproć Barnsleya

using StatsBase

# Kolejne transformacje są zapisane jako osobne funkcje, 
# które później złożą się na wektor funkcji trans.
trans1(x) = [   0.   0.; 0.    0.16]*x
trans2(x) = [0.85  0.04; -0.04 0.85]*x + [0; 1.6]
trans3(x) = [0.2  -0.26;  0.23 0.22]*x + [0; 0.8]
trans4(x) = [-0.15 0.28;  0.26 0.24]*x + [0; 0.44]
trans = [trans1, trans2, trans3, trans4]
point = [0 0]'

col = ["red" "green" "blue" "orange"]
probs = [0.01, 0.79, 0.1, 0.1]

N = 200000
coords = zeros(N, 2)
cols = String[]

for i in 1:N
  # Losujemy transformacje wykorzystując wektor *probs* z częstościami 
  # występowania poszczególnych transformacji. Funkcja sample 
  # jest dostępna w bibliotece StatsBase.
  ind = sample(1:length(probs), Weights(probs)) 
  selected_trans = trans[ind[1]]
  point = selected_trans(point)
  coords[i,:] = point
  push!(cols, col[ind])
end

scatter(coords[:,1], coords[:,2], color=cols,
      legend=:false, markersize=1, axis=nothing,
      markerstrokecolor=cols)

3.6.3 Liść klonu

# Kolejne transformacje zapisujemy jako macierze 3x3 przekształceń
# liniowych. Przez co zapis jest bardziej kompaktowy.
affines = [[0.14  0.01  -0.08; 0.0  0.51  -1.31; 0 0 1],
      [0.43   0.52   1.49; -0.45  0.5  -0.75 ; 0 0 1],
      [0.45  -0.49  -1.62;  0.47  0.47  -0.74; 0 0 1],
      [0.49   0.0    0.02;  0.0   0.51  1.62 ; 0 0 1]]
probs = [0.25, 0.25, 0.25, 0.25]
col = ["red", "green", "blue", "orange"]

N = 200000
point = [0 0 1]'
coords = zeros(N, 2)
cols = String[]

for i in 1:N  
  # W przeciwieństwie do poprzednich rozdziałów, tutaj nie
  # korzystamy z rekurencji. Iteracyjnie liczymy pozycje dla 
  # N skoków a później wszystkie wyznaczone punkty rysujemy 
  # jedną instrukcją scatter.
  ind = sample(1:length(probs), Weights(probs))
  point = affines[ind[1]] * point
  coords[i,:] = point[1:2]
  push!(cols, col[ind])
end

scatter(coords[:,1], coords[:,2], color=cols,
  legend=:false, markersize=1, axis=nothing,
  markerstrokecolor=cols)

3.6.4 Spirala

Transformacje tworzące spiralę.

affines = [
  [0.7878 -0.4242 1.7586; 0.2424 0.8598 1.408; 0 0 1],
  [-0.1212 0.2575 -6.7216; 0.1515 0.0530 1.3772; 0 0 1],
  [0.1818 -0.1363  6.0861; 0.0909 0.1818 1.5680; 0 0 1]]
probs = [0.9, 0.05, 0.05]