51

Lego Mosaics Using R

 5 years ago
source link: https://www.tuicool.com/articles/hit/yyUzQjq
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

LEGO Mosaics in R

brickr 3mqM3mr.png!web

Overview

brickris a package for creating LEGO-esque 2D and 3D models using the R tidyverse and Tyler Morgan-Wall ’s rayshader package.

The package has two key uses:

  • Converting image files in to 2D and 3D LEGO mosaics
  • Building 3D LEGO models from simple data frames

Installation

# To install the latest version from Github:
# install.packages("devtools")
devtools::install_github("ryantimpe/brickr")

#For 3D features, rayshader is also required.
install.packages("rayshader")

3D Models

Currently, 3D models can be built from one of two data input formats: bricks_from_table() or bricks_from_coords() .

These functions are very experimental and will change. Better documentation will be released soon.

  • bricks_from_table() converts a matrix-shaped table of integers into LEGO bricks. For simple models, this table can be made manually using data.frame() or tibble::tribble() . For more advanced models, it’s recommended you use MS Excel or a .csv file. The left-most column in the table is associated with the Level or z-axis of the model. The function by default converts this to numeric for you. Each other column is an x-coordinate and each row is a y-coordinate. More flexible inputs will be available in a future release.

  • bricks_from_coords() takes a data frame with x , y , & z integer values, and Color columns, where each combination of x, y, & z is a point in 3-dimensional space. Color must be an official LEGO color name from display_colors() . This format is much more flexible than bricks_from_table() and allows the programatic development of 3D models.

Pass the output from any bricks_from_*() function to display_bricks() to see the 3D model.

library(brickr)

#This is a brick
brick <- data.frame(
  Level="A",
  X1 = rep(1,4),
  X2 = rep(1,4)
)

brick
##   Level X1 X2
## 1     A  1  1
## 2     A  1  1
## 3     A  1  1
## 4     A  1  1
brick %>% 
  bricks_from_table() %>% 
  display_bricks()

rayshader::render_snapshot()

RBfMzqZ.png!web

Brick Colors

There are 2 ways to assign the color of the bricks. The display_colors() function helps with ID numbers and names

  • Use the brickrID value instead of ‘1’ in the model input table. Values of ‘0’ are blank spaces.

  • Create a table of color assignments and pass this to bricks_from_table()

brick_colors <- data.frame(
  .value = 1,
  Color = "Bright blue"
)

brick %>% 
  bricks_from_table(brick_colors) %>% 
  display_bricks()

rayshader::render_snapshot()

qEryQb6.png!web

Stacking bricks

The Level column in the input table determines the height of the bricks. bricks_from_table() will convert alphanumeric levels into a z coordinate.

# A is the bottom Level, B is the top
brick <- data.frame(
  Level= c(rep("A",4), rep("B",4)),
  X1 = rep(1,4),
  X2 = rep(1,4)
)

brick %>% 
  bricks_from_table(brick_colors) %>% 
  display_bricks()

rayshader::render_snapshot()

3MnQJzi.png!web

The same process works with many levels

#You can stack many bricks ----
brick <- data.frame(
  Level="A",
  X1 = rep(1,4),
  X2 = rep(1,4)
)

#... And they can all be different colors ----
1:10 %>% 
  purrr::map_df(~dplyr::mutate(brick, Level = LETTERS[.x], X1 = .x, X2 = .x)) %>% 
  bricks_from_table() %>% 
  display_bricks()

rayshader::render_snapshot()

NjuMzi3.png!web

Full Models

For larger models, use tibble::tribble() to more easily visualize the model. For very large models, use MS Excel.

my_first_model <- tibble::tribble(
  ~Level, ~X1, ~X2, ~X3, ~x4, ~x5, ~X6, ~x7, ~x8,
  "A", 1, 1, 1, 0, 1, 1, 1, 1,
  "A", 1, 0, 0, 0, 0, 0, 0, 1,
  "A", 1, 0, 0, 0, 0, 0, 0, 1,
  "A", 1, 1, 1, 1, 1, 1, 1, 1,
  "B", 1, 0, 1, 0, 1, 1, 0, 1,
  "B", 1, 0, 0, 0, 0, 0, 0, 1,
  "B", 1, 0, 0, 0, 0, 0, 0, 1,
  "B", 1, 0, 1, 0, 0, 1, 0, 1,
  "C", 1, 1, 1, 1, 1, 1, 1, 1,
  "C", 1, 0, 0, 0, 0, 0, 0, 1,
  "C", 1, 0, 0, 0, 0, 0, 0, 1,
  "C", 1, 1, 1, 1, 1, 1, 1, 1,
  "D", 2, 2, 2, 2, 2, 2, 2, 2,
  "D", 1, 0, 0, 0, 0, 0, 0, 1,
  "D", 1, 0, 0, 0, 0, 0, 0, 1,
  "D", 2, 2, 2, 2, 2, 2, 2, 2,
  "E", 0, 0, 0, 0, 0, 0, 0, 0,
  "E", 2, 2, 2, 2, 2, 2, 2, 2,
  "E", 2, 2, 2, 2, 2, 2, 2, 2,
  "E", 0, 0, 0, 0, 0, 0, 0, 0
)

brick_colors <- tibble::tribble(
  ~`.value`, ~Color,
  1, "Bright blue",
  2, "Dark orange"
)
  
my_first_model %>% 
  bricks_from_table(brick_colors) %>% 
  display_bricks(theta = 210)

rayshader::render_snapshot()

IBf2IvZ.png!web

Programmatically build models

Use bricks_from_coords() to programmatically build 3D LEGO models instead of manually drawing them in a spreadsheet or table. Here you must provide whole number coordinates for x, y, and z, along with an official LEGO color name for each point.

radius <- 4
sphere_coords <- expand.grid(
  x = 1:round((radius*2.5)),
  y = 1:round((radius*2.5)),
  z = 1:round((radius/(6/5)*3)) #A brick is 6/5 taller than it is wide/deep
) %>%
  mutate(
    #Distance of each coordinate from center
    dist = (((x-mean(x))^2 + (y-mean(y))^2 + (z-mean(z))^2)^(1/2)),
    Color = case_when(
      #Yellow stripes on the surface with a 2to4 thickness
      between(dist, (radius-1), radius) & (x+y+z) %% 6 %in% 0:1 ~ "Bright yellow",
      #Otherwise, sphere is blue
      dist <= radius ~ "Bright blue"
  ))

sphere_coords %>% 
  bricks_from_coords() %>% 
  display_bricks(phi = 30, theta = 30)

rayshader::render_snapshot()

ZJz2uiM.png!web

Mosaics

The mosaic functions renders an imported JPG or PNG file using LEGO colors and bricks. The resulting mosaic can be viewed in 2D and 3D. A full explanation can be found on this blog post , this follow-up post ,and this third post .

mosaic1 <- jpeg::readJPEG("Images/goldengirls.jpg") %>% 
  image_to_bricks(img_size = 48) #Length of each side of mosaic in "bricks"

#Plot 2D mosaic
mosaic1 %>% display_set()

6VfQ7rJ.png!web If you had previously created mosaics before the package release, the script below will still work.

mosaic1 <- jpeg::readJPEG("Images/goldengirls.jpg") %>% 
  scale_image(img_size = 48) %>% #Length of each side of mosaic in "bricks"
  legoize() %>%  
  collect_bricks()

2D Mosaics

image_to_bricks() can take a few important arguments:

  • img_size Providing a single value, such as 48 , crops the image to a square. Inputting a 2-element array, c(56, 48) , will output a rectangular image of c(width, height) .

  • color_table Data frame of possible brick colors in the mosaic. Defaults to the included data set lego_colors .

  • brightness adjusts the light of the image. Values greater than 1 will lighten the image, while value less than 1 will darken it.

display_set() creates a ggplot of the image.

3D Mosaics

Two additional functions can convert the image_to_bricks() output into a 3D mosaic using the rayshader package by Tyler Morgan-Wall .

  • collect_3d() translates the 2D LEGO mosaic into two matrices - one for the color image and one for the elevation of each point on the image. By default, the produced image has the height of 6 LEGO plates (2 LEGO bricks) with lighter colors having a higher elevation. Use mosaic_height to change the height of the mosaic and set highest_el = 'dark' to set the darker colors as the tallest bricks.

  • display_3d() simply calls rayshader::plot_3d() , but pulls both the hillshade and elevation matrices from the output of collect_3d() and fixes some of the arguments. See ?rayshader::plot_3d() for more information.

library(rayshader)

mosaic1 %>% 
  collect_3d() %>% 
  display_3d(fov=0,theta=-20,phi=30,windowsize=c(1000,800),zoom=0.7)

render_snapshot()

EFVrqaQ.png!web

LEGO Mosaics IRL

Additional functions assist in the translation from the LEGO mosaic image into a real LEGO set.

Instructions

Use generate_instructions() to break the LEGO mosaic image into easier-to-read steps for building the set. This defaults to 6 steps, but passing any integer value will generate that many steps.

mosaic1 %>% generate_instructions(9)

bINj6nu.png!web

Piece list and count

Use display_pieces() to generate a graphic and count of all required plates or bricks (for stacked mosaics). These are sorted by color and size for easy purchase on LEGO.com’s Pick-a-Brick section using the advanced search option. Alternatively, use table_pieces() to produce a data frame table of all required bricks.

mosaic1 %>% display_pieces()

m6FzYj3.png!web


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK