Here I experiment with creating contours of Truchet tiles after seeing some really cool examples (see: https://twitter.com/_sayo_y/status/1488504770755440640).

I will use these packages:

library(bezier)
library(imager)
library(lwgeom)
library(MexBrewer) 
library(sf)
library(tidyverse)
library(truchet)

Try function:

st_truchet_flex(type = "Al", b = 1/2) %>%
  plot()

Design data frame with alternating values of b according to a checkerboard pattern. This is identical to the 2-by-2 arrangement of AC-CA called "design C" by Truchet (see p. 122 of Bosch and Colley, 2013):

df <- data.frame(expand.grid(x = 1:10, 
                             y = 1:10))

df <- df %>% 
  # The modulus of x + y can be used to create a checkerboard pattern
  mutate(tiles = case_when((x + y) %% 2 == 0 ~ "Al",
                           (x + y) %% 2 == 1 ~ "Cl"),
         b = 1/2)
# b = ifelse((x + y) %% 2 == 1, 1/3, 2/3))

Create mosaic:

mosaic <- st_truchet_fm(df = df)

Plot:

mosaic %>%
  ggplot() + 
  geom_sf(aes(fill = color),
          color = "white") +
  scale_fill_distiller(direction = 1)

Data frame with random values of b:

df <- data.frame(expand.grid(x = 1:10, 
                             y = 1:10))

df <- df %>% 
  # The modulus of x + y can be used to create a checkerboard pattern
  mutate(tiles = case_when((x + y) %% 2 == 0 ~ "Al",
                           (x + y) %% 2 == 1 ~ "Cl"),
         b = runif(n(), 1/3, 1/2))

Create mosaic:

mosaic <- st_truchet_fm(df = df)

Plot:

mosaic %>%
  st_truchet_dissolve() %>%
  ggplot() + 
  geom_sf(aes(fill = color),
          color = "white") +
  scale_fill_distiller(direction = 1)

"Design D" is as follows: $$ \begin{array}\ B & A\ C & D \end{array} $$ Recreate this design:

df <- data.frame(expand.grid(x = 1:10, 
                             y = 1:10))

df <- df %>% 
  # The modulus of x + y can be used to create the desired pattern
  mutate(tiles = case_when(x %% 2 == 1 & y %% 2 == 0 ~ "Bl",
                           x %% 2 == 0 & y %% 2 == 0 ~ "Al",
                           x %% 2 == 1 & y %% 2 == 1 ~ "Cl",
                           x %% 2 == 0 & y %% 2 == 1 ~ "Dl"),
         b = 1/2)

Create mosaic:

mosaic <- st_truchet_fm(df = df)

Plot:

ggplot() +
  geom_sf(data = mosaic,
          aes(fill = color),
          color = "white",
          size = 0.5) + 
  scale_fill_distiller(direction = 1)

"Design E" appears in the article as: $$ \begin{array}\ C & B\ D & A \end{array} $$ Recreate this design:

df <- data.frame(expand.grid(x = 1:10, 
                             y = 1:10))

df <- df %>% 
  # The modulus of x + y can be used to create the desired pattern
  mutate(tiles = case_when(x %% 2 == 1 & y %% 2 == 0 ~ "Al",
                           x %% 2 == 0 & y %% 2 == 0 ~ "Dl",
                           x %% 2 == 1 & y %% 2 == 1 ~ "Bl",
                           x %% 2 == 0 & y %% 2 == 1 ~ "Cl"),
         b = 1/2)

Create mosaic:

mosaic <- st_truchet_fm(df = df)

Plot (notice the difference with figure 2 in Bosch and Colley):

ggplot() +
  geom_sf(data = mosaic,
          aes(fill = color),
          color = "white",
          size = 0.5) + 
  scale_fill_distiller(direction = 1)

The mosaic above looks different because "Design E" in Figure 2 in Bosch and Colley is actually a 4 by 4 matrix: $$ \begin{array}\ B & C & D & A\ A & D & C & B\ D & A & B & C\ C & B & D & A\ \end{array} $$

Recreate this design:

df <- data.frame(expand.grid(x = 1:12, 
                             y = 1:12))

df <- df %>% 
  mutate(tiles = case_when(y %% 4 == 1 & x %% 4 == 1 ~ "Bl",
                           y %% 4 == 1 & x %% 4 == 2 ~ "Cl",
                           y %% 4 == 1 & x %% 4 == 3 ~ "Dl",
                           y %% 4 == 1 & x %% 4 == 0 ~ "Al",
                           # Second Row
                           y %% 4 == 2 & x %% 4 == 1 ~ "Al",
                           y %% 4 == 2 & x %% 4 == 2 ~ "Dl",
                           y %% 4 == 2 & x %% 4 == 3 ~ "Cl",
                           y %% 4 == 2 & x %% 4 == 0 ~ "Bl",
                           # Third Row
                           y %% 4 == 3 & x %% 4 == 1 ~ "Dl",
                           y %% 4 == 3 & x %% 4 == 2 ~ "Al",
                           y %% 4 == 3 & x %% 4 == 3 ~ "Bl",
                           y %% 4 == 3 & x %% 4 == 0 ~ "Cl",
                           # Fourth Row
                           y %% 4 == 0 & x %% 4 == 1 ~ "Cl",
                           y %% 4 == 0 & x %% 4 == 2 ~ "Bl",
                           y %% 4 == 0 & x %% 4 == 3 ~ "Al",
                           y %% 4 == 0 & x %% 4 == 0 ~ "Dl"),
         b = 1/2)

Create mosaic:

mosaic <- st_truchet_fm(df = df)

Plot:

ggplot() +
  geom_sf(data = mosaic,
          aes(fill = color),
          color = "white",
          size = 0.5) + 
  scale_fill_distiller(direction = 1)

"Design 1" attributed to Douat by Bosch and Colley is based on a 2 by 4 matrix: $$ \begin{array}\ D & A & C & B\ A & D & B & C\ \end{array} $$

Recreate this design:

df <- data.frame(expand.grid(x = 1:12, 
                             y = 1:12))

df <- df %>% 
  mutate(tiles = case_when(y %% 2 == 1 & x %% 4 == 1 ~ "Dl",
                           y %% 2 == 1 & x %% 4 == 2 ~ "Al",
                           y %% 2 == 1 & x %% 4 == 3 ~ "Cl",
                           y %% 2 == 1 & x %% 4 == 0 ~ "Bl",
                           # Second Row
                           y %% 2 == 0 & x %% 4 == 1 ~ "Al",
                           y %% 2 == 0 & x %% 4 == 2 ~ "Dl",
                           y %% 2 == 0 & x %% 4 == 3 ~ "Bl",
                           y %% 2 == 0 & x %% 4 == 0 ~ "Cl"),
         b = 1/2)

Create mosaic:

mosaic <- st_truchet_fm(df = df)

Plot:

ggplot() +
  geom_sf(data = mosaic,
          aes(fill = color),
          color = "white",
          size = 0.5) + 
  scale_fill_distiller(direction = 1)

"Design 6" attributed to Douat by Bosch and Colley is based on a 4 by 4 matrix: $$ \begin{array}\ C & B & C & B\ B & D & A & C\ A & C & B & D\ D & A & D & A\ \end{array} $$

Recreate this design:

df <- data.frame(expand.grid(x = 1:12, 
                             y = 1:12))

df <- df %>% 
  mutate(tiles = case_when(y %% 4 == 1 & x %% 4 == 1 ~ "Cl",
                           y %% 4 == 1 & x %% 4 == 2 ~ "Bl",
                           y %% 4 == 1 & x %% 4 == 3 ~ "Cl",
                           y %% 4 == 1 & x %% 4 == 0 ~ "Bl",
                           # Second Row
                           y %% 4 == 2 & x %% 4 == 1 ~ "Bl",
                           y %% 4 == 2 & x %% 4 == 2 ~ "Dl",
                           y %% 4 == 2 & x %% 4 == 3 ~ "Al",
                           y %% 4 == 2 & x %% 4 == 0 ~ "Cl",
                           # Third Row
                           y %% 4 == 3 & x %% 4 == 1 ~ "Al",
                           y %% 4 == 3 & x %% 4 == 2 ~ "Cl",
                           y %% 4 == 3 & x %% 4 == 3 ~ "Bl",
                           y %% 4 == 3 & x %% 4 == 0 ~ "Dl",
                           # Fourth Row
                           y %% 4 == 0 & x %% 4 == 1 ~ "Dl",
                           y %% 4 == 0 & x %% 4 == 2 ~ "Al",
                           y %% 4 == 0 & x %% 4 == 3 ~ "Dl",
                           y %% 4 == 0 & x %% 4 == 0 ~ "Al"),
         b = 1/2)

Create mosaic:

mosaic <- st_truchet_fm(df = df)

Plot:

ggplot() +
  geom_sf(data = mosaic,
          aes(fill = color),
          color = "white",
          size = 0.5) + 
  scale_fill_distiller(direction = 1)

Try with buffers:

ggplot() +
  geom_sf(data = mosaic,
          aes(fill = color),
          color = NA,
          size = 0.5) + 
  geom_sf(data = mosaic %>%
            st_truchet_dissolve() %>%
            st_buffer(dist = c(-0.1)) %>%
            filter(color == 2),
          fill = NA,
          color = "white",
          size = 0.5) + 
  geom_sf(data = mosaic %>%
            st_truchet_dissolve() %>%
            st_buffer(dist = c(-0.2)) %>%
            filter(color == 2),
          fill = NA,
          color = "white",
          size = 0.5) + 
  scale_fill_distiller(direction = 1) + 
  theme_void() +
  theme(legend.position = "none")

Take a 2 by 2 mosaic and assign tiles randomly:

# Set seed
seed <- 84467
set.seed(seed)

# Coordinates for tiles
df <- data.frame(expand.grid(x = 1:4, 
                             y = 1:4))

# Randomly select tiles
tiles <- sample(c("Al", "Bl", "Cl", "Dl"), size = 4, replace = TRUE)

# Design the mosaic
df <- df %>% 
  # The modulus of x + y can be used to create the desired pattern
  mutate(tiles = case_when(x %% 2 == 1 & y %% 2 == 0 ~ tiles[1],
                           x %% 2 == 0 & y %% 2 == 0 ~ tiles[2],
                           x %% 2 == 1 & y %% 2 == 1 ~ tiles[3],
                           x %% 2 == 0 & y %% 2 == 1 ~ tiles[4]),
         b = 1/2)

# Assemble mosaic
mosaic <- st_truchet_fm(df = df)

# Plot:
ggplot() +
  geom_sf(data = mosaic %>%
            st_truchet_dissolve(),
          aes(fill = color),
          color = NA,
          size = 0.5) + 
  geom_sf(data = mosaic %>%
            st_truchet_dissolve() %>%
            st_buffer(dist = c(-0.15)) %>%
            filter(color == 2),
          fill = NA,
          color = "white",
          size = 0.5) + 
  scale_fill_distiller(direction = 1) + 
  theme_void() +
  theme(legend.position = "none")

#ggsave(glue::glue("truchet_2x2_{seed}.png"))

Take a 4 by 4 mosaic and assign tiles randomly:

# Set seed
seed <- 298265805
set.seed(seed)

# Coordinates for tiles
df <- data.frame(expand.grid(x = 1:10, 
                             y = 1:10))

# Randomly select tiles
tiles_1 <- sample(c("Al", "Bl", "Cl", "Dl"), size = 4, replace = TRUE)
tiles_2 <- sample(c("Al", "Bl", "Cl", "Dl"), size = 4, replace = TRUE)
tiles_3 <- sample(c("Al", "Bl", "Cl", "Dl"), size = 4, replace = TRUE)
tiles_4 <- sample(c("Al", "Bl", "Cl", "Dl"), size = 4, replace = TRUE)

df <- data.frame(expand.grid(x = 1:12, 
                             y = 1:12))

df <- df %>% 
  mutate(tiles = case_when(y %% 4 == 1 & x %% 4 == 1 ~ tiles_1[1],
                           y %% 4 == 1 & x %% 4 == 2 ~ tiles_1[2],
                           y %% 4 == 1 & x %% 4 == 3 ~ tiles_1[3],
                           y %% 4 == 1 & x %% 4 == 0 ~ tiles_1[4],
                           # Second Row
                           y %% 4 == 2 & x %% 4 == 1 ~ tiles_2[1],
                           y %% 4 == 2 & x %% 4 == 2 ~ tiles_2[2],
                           y %% 4 == 2 & x %% 4 == 3 ~ tiles_2[3],
                           y %% 4 == 2 & x %% 4 == 0 ~ tiles_2[4],
                           # Third Row
                           y %% 4 == 3 & x %% 4 == 1 ~ tiles_3[1],
                           y %% 4 == 3 & x %% 4 == 2 ~ tiles_3[2],
                           y %% 4 == 3 & x %% 4 == 3 ~ tiles_3[3],
                           y %% 4 == 3 & x %% 4 == 0 ~ tiles_3[4],
                           # Fourth Row
                           y %% 4 == 0 & x %% 4 == 1 ~ tiles_4[1],
                           y %% 4 == 0 & x %% 4 == 2 ~ tiles_4[2],
                           y %% 4 == 0 & x %% 4 == 3 ~ tiles_4[3],
                           y %% 4 == 0 & x %% 4 == 0 ~ tiles_4[4]),
         b = 1/2)

# Assemble mosaic
mosaic <- st_truchet_fm(df = df)

# Plot:
ggplot() +
  geom_sf(data = mosaic %>%
            st_truchet_dissolve(),
          aes(fill = color),
          color = NA,
          size = 0.5) + 
  geom_sf(data = mosaic %>%
            st_truchet_dissolve() %>%
            st_buffer(dist = c(-0.15)) %>%
            filter(color == 2),
          fill = NA,
          color = "white",
          size = 0.5) + 
  scale_fill_distiller(direction = 1) + 
  theme_void() +
  theme(legend.position = "none")

ggsave(glue::glue("truchet_4x4_{seed}.png"))

Figurative mosaics

Load package to work with images:

library(imager)

Read the image using imager::load.image():

elvis <- load.image("elvis.jpg")

Image info:

elvis
plot(elvis)

Resize image:

elvis_rs <- imresize(elvis, scale = 1/10, interpolation = 6)

Convert to grayscale and to data frame:

elvis_df <- elvis_rs %>%
  grayscale() %>% 
  as.data.frame()

Use this data frame to design truchet mosaic:

df <- elvis_df %>% 
  # Reverse the y axis
  mutate(y = -(y - max(y)),
         # The modulus of x + y can be used to create a checkerboard pattern
         tiles = case_when((x + y) %% 2 == 0 ~ "Al",
                           (x + y) %% 2 == 1 ~ "Cl"),
         b = case_when((x + y) %% 2 == 0 ~ 1 - value,
                       (x + y) %% 2 == 1 ~ value))

Create mosaic and time process (it takes about 4 minutes to process an image of 200 by 300 pixels or so):

# Start a timer
start_time <- Sys.time()

# Assemble mosaic
mosaic <- st_truchet_fm(df = df %>% mutate(b = b * 0.99 + 0.001))

# End timer
end_time <- Sys.time()

# Calculate time
end_time - start_time

Plot:

mosaic %>%
  ggplot() + 
  geom_sf(aes(fill = color),
          color = NA) +
  scale_fill_distiller(direction = 1) + 
  theme_void() +
  theme(legend.position = "none")

ggsave("elvis-truchet.png")

Read another image:

frida <- load.image("frida.jpg")

Image info:

frida
plot(frida)
frida_sel <- imsub(frida,x %inr% c(109,500))

Resize image:

frida_rs <- imresize(frida_sel, scale = 1/4, interpolation = 6)

Convert to grayscale and to data frame:

frida_df <- frida_rs %>%
  grayscale() %>% 
  as.data.frame()

Use this data frame to design truchet mosaic according to the pattern "Design A":

df <- frida_df %>% 
  # Reverse the y axis
  mutate(y = -(y - max(y)),
         tiles = "Al",
         b = 1 - value)

Create mosaic:

# Start a timer
start_time <- Sys.time()

# Assemble mosaic
mosaic <- st_truchet_fm(df = df %>% mutate(b = b * 0.80 + 0.001))

# End timer
end_time <- Sys.time()

# Calculate time
end_time - start_time

Plot:

mosaic %>%
  ggplot() + 
  geom_sf(aes(fill = color),
          color = NA) +
  scale_fill_gradientn(colors = mex.brewer("Frida")) + 
  theme_void() +
  theme(legend.position = "none")

ggsave("frida-truchet-design-a.png")

Use this data frame to design truchet mosaic using Design C:

df <- frida_df %>% 
  # Reverse the y axis
  mutate(y = -(y - max(y)),
         # The modulus of x + y can be used to create a checkerboard pattern
         tiles = case_when((x + y) %% 2 == 0 ~ "Al",
                           (x + y) %% 2 == 1 ~ "Cl"),
         b = case_when((x + y) %% 2 == 0 ~ 1 - value,
                       (x + y) %% 2 == 1 ~ value))

Create mosaic:

# Start a timer
start_time <- Sys.time()

# Assemble mosaic
mosaic <- st_truchet_fm(df = df %>% mutate(b = b * 0.80 + 0.001))

# End timer
end_time <- Sys.time()

# Calculate time
end_time - start_time

Plot:

mosaic %>%
  ggplot() + 
  geom_sf(aes(fill = color),
          color = NA) +
  scale_fill_gradientn(colors = mex.brewer("Frida")) + 
  theme_void() +
  theme(legend.position = "none")

ggsave("frida-truchet-design-c.png")

Frida in Design D:

df <- frida_df %>% 
  # Reverse the y axis
  mutate(y = -(y - max(y)),
         # The modulus can be used to create a checkerboard pattern
         tiles = case_when(x %% 2 == 1 & y %% 2 == 0 ~ "Bl",
                           x %% 2 == 0 & y %% 2 == 0 ~ "Al",
                           x %% 2 == 1 & y %% 2 == 1 ~ "Cl",
                           x %% 2 == 0 & y %% 2 == 1 ~ "Dl"),
         b = case_when(x %% 2 == 1 & y %% 2 == 0 ~ 1 - value,
                       x %% 2 == 0 & y %% 2 == 0 ~ 1 - value,
                       x %% 2 == 1 & y %% 2 == 1 ~ value,
                       x %% 2 == 0 & y %% 2 == 1 ~ value))

Create mosaic:

# Start a timer
start_time <- Sys.time()

# Assemble mosaic
mosaic <- st_truchet_fm(df = df %>% mutate(b = b * 0.80 + 0.001))

# End timer
end_time <- Sys.time()

# Calculate time
end_time - start_time

Plot:

mosaic %>%
  ggplot() + 
  geom_sf(aes(fill = color),
          color = NA) +
  scale_fill_gradientn(colors = mex.brewer("Frida")) + 
  theme_void() +
  theme(legend.position = "none")

ggsave("frida-truchet-design-d.png")

Frida in the (mistaken) Design E:

df <- frida_df %>% 
  # Reverse the y axis
  mutate(y = -(y - max(y)),
         # The modulus of x + y can be used to create a checkerboard pattern
         tiles = case_when(x %% 2 == 1 & y %% 2 == 0 ~ "Al",
                           x %% 2 == 0 & y %% 2 == 0 ~ "Dl",
                           x %% 2 == 1 & y %% 2 == 1 ~ "Bl",
                           x %% 2 == 0 & y %% 2 == 1 ~ "Cl"),
         b = case_when(x %% 2 == 1 & y %% 2 == 0 ~ 1 - value,
                       x %% 2 == 0 & y %% 2 == 0 ~ value,
                       x %% 2 == 1 & y %% 2 == 1 ~ 1 - value,
                       x %% 2 == 0 & y %% 2 == 1 ~ value))

Create mosaic:

# Start a timer
start_time <- Sys.time()

# Assemble mosaic
mosaic <- st_truchet_fm(df = df %>% mutate(b = b * 0.99 + 0.001))

# End timer
end_time <- Sys.time()

# Calculate time
end_time - start_time

Plot (notice the difference with figure 2 in Bosch and Colley):

mosaic %>%
  ggplot() + 
  geom_sf(aes(fill = color),
          color = NA) +
  scale_fill_gradientn(colors = mex.brewer("Frida")) + 
  theme_void() +
  theme(legend.position = "none")

ggsave("frida-truchet-design-wrong-e.png")

Garalicious

Read another image:

gara <- load.image("gara-one.jpg")

Image info:

gara
plot(gara)
gara_sel <- imsub(gara,
                  x %inr% c(250, 849), 
                  y %inr% c(0, 900))

Resize image:

gara_rs <- imresize(gara_sel, scale = 1/7, interpolation = 6)

Convert to grayscale and to data frame:

gara_df <- gara_rs %>%
  grayscale() %>% 
  as.data.frame()

Use this data frame to design truchet mosaic according to the pattern "Design A":

df <- gara_df %>% 
  # Reverse the y axis
  mutate(y = -(y - max(y)),
         tiles = "Al",
         b = 1 - value)

Create mosaic:

# Start a timer
start_time <- Sys.time()

# Assemble mosaic
mosaic <- st_truchet_fm(df = df %>% mutate(b = b * 0.80 + 0.001))

# End timer
end_time <- Sys.time()

# Calculate time
end_time - start_time

Plot:

mosaic %>%
  ggplot() + 
  geom_sf(aes(fill = color),
          color = NA) +
  scale_fill_gradientn(colors = mex.brewer("Frida")) + 
  theme_void() +
  theme(legend.position = "none")

ggsave("gara-truchet-design-a.png")

Use this data frame to design truchet mosaic using Design C:

df <- gara_df %>% 
  # Reverse the y axis
  mutate(y = -(y - max(y)),
         # The modulus of x + y can be used to create a checkerboard pattern
         tiles = case_when((x + y) %% 2 == 0 ~ "Al",
                           (x + y) %% 2 == 1 ~ "Cl"),
         b = case_when((x + y) %% 2 == 0 ~ 1 - value,
                       (x + y) %% 2 == 1 ~ value))

Create mosaic:

# Start a timer
start_time <- Sys.time()

# Assemble mosaic
mosaic <- st_truchet_fm(df = df %>% mutate(b = b * 0.80 + 0.001))

# End timer
end_time <- Sys.time()

# Calculate time
end_time - start_time

Plot:

mosaic %>%
  ggplot() + 
  geom_sf(aes(fill = color),
          color = NA) +
  scale_fill_gradientn(colors = mex.brewer("Frida")) + 
  theme_void() +
  theme(legend.position = "none")

ggsave("gara-truchet-design-c.png")

Gara in Design D:

df <- gara_df %>% 
  # Reverse the y axis
  mutate(y = -(y - max(y)),
         # The modulus can be used to create a checkerboard pattern
         tiles = case_when(x %% 2 == 1 & y %% 2 == 0 ~ "Bl",
                           x %% 2 == 0 & y %% 2 == 0 ~ "Al",
                           x %% 2 == 1 & y %% 2 == 1 ~ "Cl",
                           x %% 2 == 0 & y %% 2 == 1 ~ "Dl"),
         b = case_when(x %% 2 == 1 & y %% 2 == 0 ~ 1 - value,
                       x %% 2 == 0 & y %% 2 == 0 ~ 1 - value,
                       x %% 2 == 1 & y %% 2 == 1 ~ value,
                       x %% 2 == 0 & y %% 2 == 1 ~ value))

Create mosaic:

# Start a timer
start_time <- Sys.time()

# Assemble mosaic
mosaic <- st_truchet_fm(df = df %>% mutate(b = b * 0.80 + 0.001))

# End timer
end_time <- Sys.time()

# Calculate time
end_time - start_time

Plot:

mosaic %>%
  ggplot() + 
  geom_sf(aes(fill = color),
          color = NA) +
  #scale_fill_gradientn(colors = mex.brewer("Frida")) +
  scale_fill_distiller(palette = "PuBu", direction = 1) +
  theme_void() +
  theme(legend.position = "none")

ggsave("gara-truchet-design-d.png")

Gara in the (mistaken) Design E:

df <- gara_df %>% 
  # Reverse the y axis
  mutate(y = -(y - max(y)),
         # The modulus of x + y can be used to create a checkerboard pattern
         tiles = case_when(x %% 2 == 1 & y %% 2 == 0 ~ "Al",
                           x %% 2 == 0 & y %% 2 == 0 ~ "Dl",
                           x %% 2 == 1 & y %% 2 == 1 ~ "Bl",
                           x %% 2 == 0 & y %% 2 == 1 ~ "Cl"),
         b = case_when(x %% 2 == 1 & y %% 2 == 0 ~ 1 - value,
                       x %% 2 == 0 & y %% 2 == 0 ~ value,
                       x %% 2 == 1 & y %% 2 == 1 ~ 1 - value,
                       x %% 2 == 0 & y %% 2 == 1 ~ value))

Create mosaic:

# Start a timer
start_time <- Sys.time()

# Assemble mosaic
mosaic <- st_truchet_fm(df = df %>% mutate(b = b * 0.99 + 0.001))

# End timer
end_time <- Sys.time()

# Calculate time
end_time - start_time

Plot (notice the difference with figure 2 in Bosch and Colley):

mosaic %>%
  ggplot() + 
  geom_sf(aes(fill = color),
          color = NA) +
  scale_fill_gradientn(colors = mex.brewer("Frida")) + 
  theme_void() +
  theme(legend.position = "none")

ggsave("gara-truchet-design-wrong-e.png")

Belen

Read another image:

belen <- load.image("belen.jpg")

Image info:

belen
plot(belen)
belen_sel <- imsub(belen,
                   x %inr% c(100, 500), 
                   y %inr% c(22, 622))

Resize image:

belen_rs <- imresize(belen_sel, scale = 1/7, interpolation = 6)

Convert to grayscale and to data frame:

belen_df <- belen_rs %>%
  grayscale() %>% 
  as.data.frame()

Use this data frame to design truchet mosaic according to the pattern "Design A":

df <- belen_df %>% 
  # Reverse the y axis
  mutate(y = -(y - max(y)),
         tiles = "Al",
         b = 1 - value)

Create mosaic:

# Start a timer
start_time <- Sys.time()

# Assemble mosaic
mosaic <- st_truchet_fm(df = df %>% mutate(b = b * 0.80 + 0.001))

# End timer
end_time <- Sys.time()

# Calculate time
end_time - start_time

Plot:

mosaic %>%
  ggplot() + 
  geom_sf(aes(fill = color),
          color = NA) +
  #scale_fill_gradientn(colors = mex.brewer("Frida")) + 
  scale_fill_distiller(direction = 1) + 
  theme_void() +
  theme(legend.position = "none")

ggsave("belen-truchet-design-a.png")

Use this data frame to design truchet mosaic using Design C:

df <- belen_df %>% 
  # Reverse the y axis
  mutate(y = -(y - max(y)),
         # The modulus of x + y can be used to create a checkerboard pattern
         tiles = case_when((x + y) %% 2 == 0 ~ "Al",
                           (x + y) %% 2 == 1 ~ "Cl"),
         b = case_when((x + y) %% 2 == 0 ~ 1 - value,
                       (x + y) %% 2 == 1 ~ value))

Create mosaic:

# Start a timer
start_time <- Sys.time()

# Assemble mosaic
mosaic <- st_truchet_fm(df = df %>% mutate(b = b * 0.80 + 0.001))

# End timer
end_time <- Sys.time()

# Calculate time
end_time - start_time

Plot:

mosaic %>%
  ggplot() + 
  geom_sf(aes(fill = color),
          color = NA) +
  #scale_fill_gradientn(colors = mex.brewer("Frida")) + 
  scale_fill_distiller(direction = 1) + 
  theme_void() +
  theme(legend.position = "none")

ggsave("belen-truchet-design-c.png")

Belen in Design D:

df <- belen_df %>% 
  # Reverse the y axis
  mutate(y = -(y - max(y)),
         # The modulus can be used to create a checkerboard pattern
         tiles = case_when(x %% 2 == 1 & y %% 2 == 0 ~ "Bl",
                           x %% 2 == 0 & y %% 2 == 0 ~ "Al",
                           x %% 2 == 1 & y %% 2 == 1 ~ "Cl",
                           x %% 2 == 0 & y %% 2 == 1 ~ "Dl"),
         b = case_when(x %% 2 == 1 & y %% 2 == 0 ~ 1 - value,
                       x %% 2 == 0 & y %% 2 == 0 ~ 1 - value,
                       x %% 2 == 1 & y %% 2 == 1 ~ value,
                       x %% 2 == 0 & y %% 2 == 1 ~ value))

Create mosaic:

# Start a timer
start_time <- Sys.time()

# Assemble mosaic
mosaic <- st_truchet_fm(df = df %>% mutate(b = b * 0.80 + 0.001))

# End timer
end_time <- Sys.time()

# Calculate time
end_time - start_time

Plot:

mosaic %>%
  ggplot() + 
  geom_sf(aes(fill = color),
          color = NA) +
  #scale_fill_gradientn(colors = mex.brewer("Frida")) + 
  scale_fill_distiller(direction = 1) + 
  theme_void() +
  theme(legend.position = "none")

ggsave("belen-truchet-design-d.png")

Belen in the (mistaken) Design E:

df <- belen_df %>% 
  # Reverse the y axis
  mutate(y = -(y - max(y)),
         # The modulus of x + y can be used to create a checkerboard pattern
         tiles = case_when(x %% 2 == 1 & y %% 2 == 0 ~ "Al",
                           x %% 2 == 0 & y %% 2 == 0 ~ "Dl",
                           x %% 2 == 1 & y %% 2 == 1 ~ "Bl",
                           x %% 2 == 0 & y %% 2 == 1 ~ "Cl"),
         b = case_when(x %% 2 == 1 & y %% 2 == 0 ~ 1 - value,
                       x %% 2 == 0 & y %% 2 == 0 ~ value,
                       x %% 2 == 1 & y %% 2 == 1 ~ 1 - value,
                       x %% 2 == 0 & y %% 2 == 1 ~ value))

Create mosaic:

# Start a timer
start_time <- Sys.time()

# Assemble mosaic
mosaic <- st_truchet_fm(df = df %>% mutate(b = b * 0.99 + 0.001))

# End timer
end_time <- Sys.time()

# Calculate time
end_time - start_time

Plot (notice the difference with figure 2 in Bosch and Colley):

mosaic %>%
  ggplot() + 
  geom_sf(aes(fill = color),
          color = NA) +
  #scale_fill_gradientn(colors = mex.brewer("Frida")) + 
  scale_fill_distiller(direction = 1) + 
  theme_void() +
  theme(legend.position = "none")

ggsave("belen-truchet-design-wrong-e.png")

Random placement of tiles?

# Set seed
seed <- 84467
set.seed(seed)

# Coordinates for tiles
df <- data.frame(expand.grid(x = 1:2, 
                             y = 1:2))

# Randomly select tiles
tiles <- sample(c("Al", "Bl", "Cl", "Dl"), size = 4, replace = TRUE)

value <- 3/4
# Design the mosaic
df <- df %>% 
  # The modulus of x + y can be used to create the desired pattern
  mutate(tiles = case_when(x %% 2 == 1 & y %% 2 == 0 ~ tiles[1],
                           x %% 2 == 0 & y %% 2 == 0 ~ tiles[2],
                           x %% 2 == 1 & y %% 2 == 1 ~ tiles[3],
                           x %% 2 == 0 & y %% 2 == 1 ~ tiles[4]),
         # Important! Notice the adjustment to the values to ensure that the area correctly reflects the underlying darkness value
         b = case_when(tiles == "Al" ~ value, 
                       tiles == "Bl" ~ value, 
                       tiles == "Cl" ~ 1 - value, 
                       tiles == "Dl" ~ 1 - value))

# Assemble mosaic
mosaic <- st_truchet_fm(df = df)

# Plot:
ggplot() +
  geom_sf(data = mosaic,
          aes(fill = color),
          color = NA,
          size = 0.5) + 
  scale_fill_distiller(direction = 1) + 
  theme_void() +
  theme(legend.position = "none")

#ggsave(glue::glue("truchet_2x2_{seed}.png"))

Belen with a random mosaic:

# Set seed
seed <- 1085
set.seed(seed)

# Randomly select tiles
tiles <- sample(c("Al", "Bl", "Cl", "Dl"), size = 4, replace = TRUE)

value <- 3/4
# Design the mosaic
df <- belen_df %>% 
  # Reverse the y axis
  mutate(y = -(y - max(y)),
         tiles = case_when(x %% 2 == 1 & y %% 2 == 0 ~ tiles[1],
                           x %% 2 == 0 & y %% 2 == 0 ~ tiles[2],
                           x %% 2 == 1 & y %% 2 == 1 ~ tiles[3],
                           x %% 2 == 0 & y %% 2 == 1 ~ tiles[4]),
         # Important! Notice the adjustment to the values to ensure that the area correctly reflects the underlying darkness value
         b = case_when(tiles == "Al" ~ 1- value, 
                       tiles == "Bl" ~ 1- value, 
                       tiles == "Cl" ~ value, 
                       tiles == "Dl" ~ value))

Create mosaic:

# Start a timer
start_time <- Sys.time()

# Assemble mosaic
mosaic <- st_truchet_fm(df = df %>% mutate(b = b * 0.99 + 0.001))

# End timer
end_time <- Sys.time()

# Calculate time
end_time - start_time

Plot (notice the difference with figure 2 in Bosch and Colley):

mosaic %>%
  st_truchet_dissolve() %>%
  ggplot() + 
  geom_sf(aes(fill = color),
          color = NA) +
  #scale_fill_gradientn(colors = mex.brewer("Frida")) + 
  scale_fill_distiller(direction = 1) + 
  theme_void() +
  theme(legend.position = "none")

ggsave(glue::glue("belen-truchet-{seed}.png"))

Random placement of tiles?

# Tiles types
tile_types <- data.frame(type = c("Al", "Bl", "Cl", "Dl")) %>%
  mutate(x = c(1, 2.5, 1, 2.5),
         y = c(2.5, 2.5, 1, 1),
         b = 1/2)

# Elements for assembling the mosaic
x_c <- tile_types$x
y_c <- tile_types$y
type <- as.character(tile_types$type)
b <- tile_types$b

pmap_dfr(list(x_c, y_c, type, b), st_truchet_flex) %>%
  ggplot() + 
  geom_sf(aes(fill = color),
          color = "black",
          size = 2) +
  geom_text(data = tile_types,
            aes(x = x,
                y = y,
                label = c("A", "B", "C", "D")),
            nudge_y = 0.6) + 
  scale_fill_distiller(direction = 1) +
  theme_void() +
  theme(legend.position = "none")


#ggsave(glue::glue("truchet_2x2_{seed}.png"))
# Tiles types
tile_types <- data.frame(type = c("Al", "Al", "Al", "Al")) %>%
  mutate(x = c(1, 2, 1, 2),
         y = c(2, 2, 1, 1),
         b = 1/2)

# Elements for assembling the mosaic
x_c <- tile_types$x
y_c <- tile_types$y
type <- as.character(tile_types$type)
b <- tile_types$b

pmap_dfr(list(x_c, y_c, type, b), st_truchet_flex) %>%
  ggplot() + 
  geom_sf(aes(fill = color),
          color = "black",
          size = 2) +
  geom_text(data = tile_types,
            aes(x = x,
                y = y,
                label = c("Design A", "", "", "")),
            nudge_y = 0.6) + 
  scale_fill_distiller(direction = 1) +
  theme_void() +
  theme(legend.position = "none")
# Tiles types
tile_types <- data.frame(type = c("Al", "Cl", "Cl", "Al")) %>%
  mutate(x = c(1, 2, 1, 2),
         y = c(2, 2, 1, 1),
         b = 1/2)

# Elements for assembling the mosaic
x_c <- tile_types$x
y_c <- tile_types$y
type <- as.character(tile_types$type)
b <- tile_types$b

pmap_dfr(list(x_c, y_c, type, b), st_truchet_flex) %>%
  ggplot() + 
  geom_sf(aes(fill = color),
          color = "black",
          size = 2) +
  geom_text(data = tile_types,
            aes(x = x,
                y = y,
                label = c("Design C", "", "", "")),
            nudge_y = 0.6) + 
  scale_fill_distiller(direction = 1) +
  theme_void() +
  theme(legend.position = "none")
# Tiles types
tile_types <- data.frame(type = c("Al", "Dl", "Bl", "Cl")) %>%
  mutate(x = c(1, 2, 1, 2),
         y = c(2, 2, 1, 1),
         b = 1/2)

# Elements for assembling the mosaic
x_c <- tile_types$x
y_c <- tile_types$y
type <- as.character(tile_types$type)
b <- tile_types$b

pmap_dfr(list(x_c, y_c, type, b), st_truchet_flex) %>%
  ggplot() + 
  geom_sf(aes(fill = color),
          color = "black",
          size = 2) +
  geom_text(data = tile_types,
            aes(x = x,
                y = y,
                label = c("Matrix [A, D; B, C]", "", "", "")),
            nudge_y = 0.6) + 
  scale_fill_distiller(direction = 1) +
  theme_void() +
  theme(legend.position = "none")
paezha/truchet documentation built on April 27, 2022, 9:53 a.m.