1.5 Przykłady w języku R

Drogi Czytelniku, możesz opisywane fraktale odtworzyć na swoim komputerze, wystarczy tylko zainstalowany interpreter języka R, który można bezpłatnie pobrać i zainstalować ze strony [https://cran.r-project.org/]. Nie jest niezbędna wcześniejsza znajomość tego języka, choć oczywiście byłaby przydatna. Poniżej kilka informacji, które pomogą w zrozumieniu tego kodu.

  1. Poniższe przykłady korzystają z podstawowej biblioteki graficznej dla R, czyli graphics. Nie trzeba jej wczytywać, ponieważ jest dostępna od razu po uruchomieniu R. Funkcja plot.new() tworzy pusty wykres. Jest on wypełniany przez użycie funkcji polygon() do rysowania wypełnionych wielokątów, tutaj trójkąta i kwadratu.
  2. R to język dla matematyków i statystyków, więc większość operacji matematycznych jest dostępna od razu po uruchomieniu konsoli, tak jak funkcja sqrt() potrzebna do wyliczenia wysokości trójkąta równobocznego.
  3. Program R działa natywnie na wektorach, co znaczy, że możemy używać arytmetycznych operatorów takich jak + czy / zarówno do liczb, jak i do wektorów.
  4. 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 kluczowego function. Przedstawione funkcje mają argument depth, określający, ile jeszcze razy funkcja ma wywołać samą siebie.

1.5.1 Kurz Cantora

Rysowanie fraktali rozpocznijmy od kurzu Cantora. Wykorzystamy do tego rekurencyjną funkcję dust, która przyjmuje trzy argumenty: x – miejsce, od którego należy rysować fraktal, scale – informację o wielkości fraktala oraz depth – aktualny poziom zagnieżdżenia fraktala.

# Rekurencyjna funkcja do rysowania kurzu. Jeżeli depth=1 
# to rysuje odcinek, jeżeli depth>1 to rysujemy dwa 
# kurze Cantora obok siebie.
dust = function(x, y, scale, depth = 1) { 
  if (depth == 0) {
    lines(c(x, x + scale), c(y, y))
  } else {
    dust(x, y, scale/3, depth - 1)
    dust(x + scale*2/3, y, scale/3, depth - 1)
  }
}

# Czyścimy ekran i zaczynamy rysowanie kurzu.
plot.new() 
dust(0, 0, scale = 1, depth = 4)

Wynik wykonania powyższych instrukcji

1.5.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 – miejsce, od którego należy rysować fraktal, scale – informację o wielkości fraktala oraz depth – aktualny poziom zagnieżdżenia fraktala.

triangle <- function(x, y, scale) {
  polygon(x + scale*c(0, 1, 1/2), 
          y + scale*c(0, 0, sqrt(3)/2), col = "black")
}

# 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 obok siebie.
sierpinski <- function(x, y, scale, depth = 1) { 
  if (depth == 0) {
    triangle(x, y, scale)
  } 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)
  }
}

plot.new()
sierpinski(0, 0, scale = 1, depth = 6)

Wynik wykonania powyższych instrukcji

1.5.3 Dywan Sierpińskiego

Konstrukcja fraktala zaproponowana przez Wacława Sierpińskiego może być powtórzona dla innych kształtów.

# Rekurencyjna funkcja do rysowania dywanu. 
# W zależności od aktualnej głębokości albo rysuje kwadrat 
# albo, rekurencyjnie ośmiokrotnie wywołuje samą siebie
carpet = function(x, y, scale, depth = 1) { 
  if (depth == 1) {
    rect(x, y, x + scale, y + scale, col = "black")
  } else {
    carpet(x, y, scale/3, depth - 1)
    carpet(x+scale*1/3, y, scale/3, depth - 1)
    carpet(x+scale*2/3, y, scale/3, depth - 1)
    carpet(x, y+scale*1/3, scale/3, depth - 1)
    carpet(x+scale*2/3, y+scale*1/3, scale/3, depth - 1)
    carpet(x, y+scale*2/3, scale/3, depth - 1)
    carpet(x+scale*1/3, y+scale*2/3, scale/3, depth - 1)
    carpet(x+scale*2/3, y+scale*2/3, scale/3, depth - 1)  
  }
}

plot.new()
carpet(0, 0, scale = 1, depth = 4)

Wynik wykonania powyższych instrukcji