suppressPackageStartupMessages({
  library(tidyverse)
  library(scales)
  library(glue)
  library(flametree)
})

1 Simple graphs

Let’s start from drawing a random line using ggplot

tibble(x1 = 1,
       y1 = 5,
       x2 = 6,
       y2 = -2) %>% 
  ggplot()+
  geom_segment(aes(x = x1, 
                   y = y1, 
                   xend = x2, 
                   yend = y2))+
  theme_void()

NA

Let’s do many lines

N <- 30

tibble(x1 = runif(N, -1, 1),
       y1 = runif(N, -1, 1), 
       x2 = runif(N, -1, 1),
       y2 = runif(N, -1, 1)) %>% 
  ggplot()+
  geom_segment(aes(x = x1, y = y1, xend = x2, yend = y2))+
  theme_void()+
  labs(subtitle = "Lines")

Now let’s add some random color, thickness and opacity

N <- 30
cols <- rainbow(N)
cols <- c("#EF892D", "#FEC784", "#45555F", "#93ADC5", "#BF49DB")
#set.seed(43)

tibble(line = 1:N %% 5,
       x1 = runif(N, -1, 1),
       y1 = runif(N, -1, 1), 
       x2 = runif(N, -1, 1),
       y2 = runif(N, -1, 1), 
       size = runif(N, 0, 3),
       alpha = runif(N, 0.1, 0.9)) %>% 
  ggplot()+
  geom_segment(aes(x = x1, y = y1, xend = x2, yend = y2, size = size, alpha = alpha, color = as.factor(line)),show.legend = FALSE)+
  scale_color_manual(values = cols)+
  scale_size_continuous(range = c(2,20))+
  theme_void()+
  labs(subtitle = "Rainbow Lines")

2 Using Grid and Trigonometric Functions

Let’s create a simple grid first

seq(-2,2, by = 0.2) %>% 
  expand.grid(x=., y=.) %>% 
  ggplot(aes(x = x, y = y))+
  geom_point(size = 0)+
  theme_bw()

What happens if we switch to polar coordinates

seq(-2,2, by = 0.2) %>% 
  expand.grid(x=., y=.) %>% 
  ggplot(aes(x = x, y = y))+
  geom_point(size = 0)+
  coord_polar()+    # x becomes an angle and y becomes radius
  theme_bw()

We can use more complex trigonometric functions to generate really intricate and beautiful patterns (source)

seq(-2,2, by = 0.01) %>% 
  expand.grid(x=., y=.) %>% 
  ggplot(aes(x = x^3 - sin(y), y = y^3 - cos(x)))+
  geom_point(alpha = 0.05, color = "black", shape = 20, size = 0)+
  theme_void()+
  coord_polar()+
  labs(subtitle = "Dandelion")

seq(-3,3, by = 0.01) %>% 
  expand.grid(x=., y=.) %>% 
  ggplot(aes(x = 1- x-sin(y^2), y = 1 + y - cos(x^2)))+
  geom_point(alpha = 0.05, color = "blue", shape = 20, size = 0)+
  theme_void()+
  coord_polar()+
  labs(subtitle = "Flower")

seq(-12,12, by = 0.04) %>% 
  expand.grid(x=., y=.) %>% 
  ggplot(aes(x = x+pi*sin(y), y = y+ pi*sin(x)))+
  geom_point(alpha = 0.05, color = "red", shape = 20, size = 0)+
  theme_void()+
  coord_polar()+
  labs(subtitle = "Rose")

seq(-9,9, by = 0.025) %>% 
  expand.grid(x=., y=.) %>% 
  ggplot(aes(x = sin(x)^2 - log(abs(y)), y = -sin(y)^2 + log(abs(x))))+
  geom_point(alpha = 0.01, color = "black", shape = 20, size = 0)+
  theme_void()+
  coord_equal()+
  labs(subtitle = "Stingray")

Here is an example of generating a tree (source)

dat <- flametree_grow(seed = 4, time = 12, split = 2,angle = seq(-20,30,5), prune = 0.1) 
flametree_plot(tree = dat,palette = "scico::berlin") +         
  annotate(geom = "text",x = 0, y = -1, label = "Made in R using `flametree` package", color = "white")

NA
LS0tCnRpdGxlOiAiQ3JlYXRpbmcgR2VuZXJhdGl2ZSBBcnQgd2l0aCBSIgphdXRob3I6ICdBbGV4JwpkYXRlOiAnYHIgZm9ybWF0KFN5cy50aW1lKCksICIlQiAlZCwgJVkgJUg6JU06JVMiLCB0ej0iQW1lcmljYS9Mb3NfQW5nZWxlcyIsdXNldHo9VFJVRSlgJyAKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6CiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKICAgIG51bWJlcl9zZWN0aW9uczogeWVzCiAgICB0aGVtZTogY2VydWxlYW4KICAgIHRvYzogeWVzCi0tLQoKYGBge3J9CnN1cHByZXNzUGFja2FnZVN0YXJ0dXBNZXNzYWdlcyh7CiAgbGlicmFyeSh0aWR5dmVyc2UpCiAgbGlicmFyeShzY2FsZXMpCiAgbGlicmFyeShnbHVlKQogIGxpYnJhcnkoZmxhbWV0cmVlKQp9KQpgYGAKCgoKIyBTaW1wbGUgZ3JhcGhzCgpMZXQncyBzdGFydCBmcm9tIGRyYXdpbmcgYSByYW5kb20gbGluZSB1c2luZyBnZ3Bsb3QKCmBgYHtyfQp0aWJibGUoeDEgPSAxLAogICAgICAgeTEgPSA1LAogICAgICAgeDIgPSA2LAogICAgICAgeTIgPSAtMikgJT4lIAogIGdncGxvdCgpKwogIGdlb21fc2VnbWVudChhZXMoeCA9IHgxLCAKICAgICAgICAgICAgICAgICAgIHkgPSB5MSwgCiAgICAgICAgICAgICAgICAgICB4ZW5kID0geDIsIAogICAgICAgICAgICAgICAgICAgeWVuZCA9IHkyKSkrCiAgdGhlbWVfdm9pZCgpCiAgCmBgYAoKTGV0J3MgZG8gbWFueSBsaW5lcwoKYGBge3J9Ck4gPC0gMzAKCnRpYmJsZSh4MSA9IHJ1bmlmKE4sIC0xLCAxKSwKICAgICAgIHkxID0gcnVuaWYoTiwgLTEsIDEpLCAKICAgICAgIHgyID0gcnVuaWYoTiwgLTEsIDEpLAogICAgICAgeTIgPSBydW5pZihOLCAtMSwgMSkpICU+JSAKICBnZ3Bsb3QoKSsKICBnZW9tX3NlZ21lbnQoYWVzKHggPSB4MSwgeSA9IHkxLCB4ZW5kID0geDIsIHllbmQgPSB5MikpKwogIHRoZW1lX3ZvaWQoKSsKICBsYWJzKHN1YnRpdGxlID0gIkxpbmVzIikKYGBgCgpOb3cgbGV0J3MgYWRkIHNvbWUgcmFuZG9tIGNvbG9yLCB0aGlja25lc3MgYW5kIG9wYWNpdHkKCmBgYHtyLCBmaWcud2lkdGg9MTUsIGZpZy5oZWlnaHQgPSA2fQpOIDwtIDMwCmNvbHMgPC0gcmFpbmJvdyhOKQpjb2xzIDwtIGMoIiNFRjg5MkQiLCAiI0ZFQzc4NCIsICIjNDU1NTVGIiwgIiM5M0FEQzUiLCAiI0JGNDlEQiIpCiNzZXQuc2VlZCg0MykKCnRpYmJsZShsaW5lID0gMTpOICUlIDUsCiAgICAgICB4MSA9IHJ1bmlmKE4sIC0xLCAxKSwKICAgICAgIHkxID0gcnVuaWYoTiwgLTEsIDEpLCAKICAgICAgIHgyID0gcnVuaWYoTiwgLTEsIDEpLAogICAgICAgeTIgPSBydW5pZihOLCAtMSwgMSksIAogICAgICAgc2l6ZSA9IHJ1bmlmKE4sIDAsIDMpLAogICAgICAgYWxwaGEgPSBydW5pZihOLCAwLjEsIDAuOSkpICU+JSAKICBnZ3Bsb3QoKSsKICBnZW9tX3NlZ21lbnQoYWVzKHggPSB4MSwgeSA9IHkxLCB4ZW5kID0geDIsIHllbmQgPSB5Miwgc2l6ZSA9IHNpemUsIGFscGhhID0gYWxwaGEsIGNvbG9yID0gYXMuZmFjdG9yKGxpbmUpKSxzaG93LmxlZ2VuZCA9IEZBTFNFKSsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gY29scykrCiAgc2NhbGVfc2l6ZV9jb250aW51b3VzKHJhbmdlID0gYygyLDIwKSkrCiAgdGhlbWVfdm9pZCgpKwogIGxhYnMoc3VidGl0bGUgPSAiUmFpbmJvdyBMaW5lcyIpCmBgYAoKCgoKCiMgVXNpbmcgR3JpZCBhbmQgVHJpZ29ub21ldHJpYyBGdW5jdGlvbnMKCkxldCdzIGNyZWF0ZSBhIHNpbXBsZSBncmlkIGZpcnN0CgpgYGB7cn0Kc2VxKC0yLDIsIGJ5ID0gMC4yKSAlPiUgCiAgZXhwYW5kLmdyaWQoeD0uLCB5PS4pICU+JSAKICBnZ3Bsb3QoYWVzKHggPSB4LCB5ID0geSkpKwogIGdlb21fcG9pbnQoc2l6ZSA9IDApKwogIHRoZW1lX2J3KCkKYGBgCgpXaGF0IGhhcHBlbnMgaWYgd2Ugc3dpdGNoIHRvIHBvbGFyIGNvb3JkaW5hdGVzCgpgYGB7cn0Kc2VxKC0yLDIsIGJ5ID0gMC4yKSAlPiUgCiAgZXhwYW5kLmdyaWQoeD0uLCB5PS4pICU+JSAKICBnZ3Bsb3QoYWVzKHggPSB4LCB5ID0geSkpKwogIGdlb21fcG9pbnQoc2l6ZSA9IDApKwogIGNvb3JkX3BvbGFyKCkrICAgICMgeCBiZWNvbWVzIGFuIGFuZ2xlIGFuZCB5IGJlY29tZXMgcmFkaXVzCiAgdGhlbWVfYncoKQpgYGAKCldlIGNhbiB1c2UgbW9yZSBjb21wbGV4IHRyaWdvbm9tZXRyaWMgZnVuY3Rpb25zIHRvIGdlbmVyYXRlIHJlYWxseSBpbnRyaWNhdGUgYW5kIGJlYXV0aWZ1bCBwYXR0ZXJucyAoW3NvdXJjZV0oaHR0cHM6Ly90d2l0dGVyLmNvbS9hc2NoaW5jaG9uKSkKCmBgYHtyLCBmaWcuaGVpZ2h0PSA2LCBmaWcud2lkdGg9Nn0Kc2VxKC0yLDIsIGJ5ID0gMC4wMSkgJT4lIAogIGV4cGFuZC5ncmlkKHg9LiwgeT0uKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0geF4zIC0gc2luKHkpLCB5ID0geV4zIC0gY29zKHgpKSkrCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuMDUsIGNvbG9yID0gImJsYWNrIiwgc2hhcGUgPSAyMCwgc2l6ZSA9IDApKwogIHRoZW1lX3ZvaWQoKSsKICBjb29yZF9wb2xhcigpKwogIGxhYnMoc3VidGl0bGUgPSAiRGFuZGVsaW9uIikKYGBgCgoKYGBge3IsZmlnLmhlaWdodD0gNiwgZmlnLndpZHRoPTZ9CnNlcSgtMywzLCBieSA9IDAuMDEpICU+JSAKICBleHBhbmQuZ3JpZCh4PS4sIHk9LikgJT4lIAogIGdncGxvdChhZXMoeCA9IDEtIHgtc2luKHleMiksIHkgPSAxICsgeSAtIGNvcyh4XjIpKSkrCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuMDUsIGNvbG9yID0gImJsdWUiLCBzaGFwZSA9IDIwLCBzaXplID0gMCkrCiAgdGhlbWVfdm9pZCgpKwogIGNvb3JkX3BvbGFyKCkrCiAgbGFicyhzdWJ0aXRsZSA9ICJGbG93ZXIiKQpgYGAKCgoKYGBge3IsZmlnLmhlaWdodD0gNiwgZmlnLndpZHRoPTZ9CnNlcSgtMTIsMTIsIGJ5ID0gMC4wNCkgJT4lIAogIGV4cGFuZC5ncmlkKHg9LiwgeT0uKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0geCtwaSpzaW4oeSksIHkgPSB5KyBwaSpzaW4oeCkpKSsKICBnZW9tX3BvaW50KGFscGhhID0gMC4wNSwgY29sb3IgPSAicmVkIiwgc2hhcGUgPSAyMCwgc2l6ZSA9IDApKwogIHRoZW1lX3ZvaWQoKSsKICBjb29yZF9wb2xhcigpKwogIGxhYnMoc3VidGl0bGUgPSAiUm9zZSIpCmBgYAoKYGBge3IsZmlnLmhlaWdodD0gNiwgZmlnLndpZHRoPTZ9CnNlcSgtOSw5LCBieSA9IDAuMDI1KSAlPiUgCiAgZXhwYW5kLmdyaWQoeD0uLCB5PS4pICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBzaW4oeCleMiAtIGxvZyhhYnMoeSkpLCB5ID0gLXNpbih5KV4yICsgbG9nKGFicyh4KSkpKSsKICBnZW9tX3BvaW50KGFscGhhID0gMC4wMSwgY29sb3IgPSAiYmxhY2siLCBzaGFwZSA9IDIwLCBzaXplID0gMCkrCiAgdGhlbWVfdm9pZCgpKwogIGNvb3JkX2VxdWFsKCkrCiAgbGFicyhzdWJ0aXRsZSA9ICJTdGluZ3JheSIpCmBgYAoKSGVyZSBpcyBhbiBleGFtcGxlIG9mIGdlbmVyYXRpbmcgYSB0cmVlIChbc291cmNlXShodHRwczovL2ZsYW1ldHJlZS5kam5hdmFycm8ubmV0LykpCgpgYGB7ciwgZmlnLmhlaWdodCA9IDgsIGZpZy53aWR0aCA9IDh9CmRhdCA8LSBmbGFtZXRyZWVfZ3JvdyhzZWVkID0gNCwgdGltZSA9IDEyLCBzcGxpdCA9IDIsYW5nbGUgPSBzZXEoLTIwLDMwLDUpLCBwcnVuZSA9IDAuMSkgCmZsYW1ldHJlZV9wbG90KHRyZWUgPSBkYXQscGFsZXR0ZSA9ICJzY2ljbzo6YmVybGluIikgKyAgICAgICAgIAogIGFubm90YXRlKGdlb20gPSAidGV4dCIseCA9IDAsIHkgPSAtMSwgbGFiZWwgPSAiTWFkZSBpbiBSIHVzaW5nIGBmbGFtZXRyZWVgIHBhY2thZ2UiLCBjb2xvciA9ICJ3aGl0ZSIpCiAgCmBgYAoKCg==