diff --git a/DESCRIPTION b/DESCRIPTION index c132123..a88e2c1 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: brickr Title: Tools to emulate the LEGO® System in R -Version: 0.1.0.9012 +Version: 0.1.0.9014 Authors@R: person(given = "Ryan", family = "Timpe", @@ -34,6 +34,7 @@ Collate: 'bricks-from-rayshader.R' 'bricks-from-tables.R' 'build-bricks.R' + 'build-instructions.R' 'build-mosaic.R' 'collect-bricks.R' 'colors-and-themes.R' diff --git a/NEWS.md b/NEWS.md index 511e514..1b8ff4f 100644 --- a/NEWS.md +++ b/NEWS.md @@ -7,9 +7,7 @@ ## Documentation * pkgdown site -* Vignettes: - - Mosaics - - ggplot extension +* Vignettes ## Mosaics @@ -27,6 +25,7 @@ * Option to use plates rather than bricks. Combining the two involves some hacking. * Updated brick collection algorithm to allow for custom brick input. * Updated brick collection algorithm staggers bricks over layer, though still prioritizes larger bricks. +* `build_instructions` generates building instructions for 3D models, as well as mosaics. ## ggplot Extension @@ -38,11 +37,8 @@ * ggplot - continuous scale -* 3D model instructions... level by level * Vignettes - - 3D models from tables - - 3D models from coords - - 3D modesl from mosaics + rayshader + - 3D model from mosaics + rayshader - IRL * Website * Check() breaks at the size check diff --git a/R/build-instructions.R b/R/build-instructions.R new file mode 100644 index 0000000..f836c6b --- /dev/null +++ b/R/build-instructions.R @@ -0,0 +1,76 @@ +#' Create instruction manual for 2D image mosaics +#' +#' @param brickr_obj brickr mosaic or 3D model object. +#' @param num_steps Number of discrete steps in instruction manual, for mosaics only +#' @family Resources +#' @export +#' + +build_instructions <- function(brickr_obj, num_steps=6) { + in_list <- brickr_obj + image <- in_list$Img_bricks + type <- in_list$brickr_object + + #Mosaic instructions ---- + if(type == "mosaic"){ + num_steps <- min(abs(round(num_steps)), 40) + + rows_per_step <- ceiling((max(image$ymax)-0.5) / (num_steps+1)) + + create_steps <- function(a, n_steps) { + if(a < n_steps){ + image %>% + dplyr::group_by(brick_name) %>% + dplyr::filter(min(ymin) <= a*rows_per_step+(min(image$ymin)+0.5)) %>% + dplyr::ungroup() %>% + dplyr::mutate(Step = paste("Step", stringr::str_pad(a, 2, pad = "0"))) + } else { + image %>% + dplyr::mutate(Step = paste("Step", stringr::str_pad(a, 2, pad = "0"))) + } + } + + steps_for_plot <- 1:num_steps %>% + purrr::map_df(create_steps, num_steps) %>% + dplyr::mutate(alpha = 1) + + } #end mosaics + + else if(type == "3dmodel"){ + num_steps <- length(unique(image$Level)) + + create_steps <- function(a, n_steps) { + image %>% + dplyr::filter(between(Level, a-1, a)) %>% + dplyr::mutate(alpha = ifelse(Level == a, 1, 0.5)) %>% + dplyr::mutate(Step = paste("Step", stringr::str_pad(a, 2, pad = "0"))) + + } + + steps_for_plot <- 1:num_steps %>% + purrr::map_df(create_steps, num_steps) + + } + + #Plot ---- + coord_ratio <- 1 + + steps_for_plot %>% + ggplot2::ggplot() + + ggplot2::geom_rect(ggplot2::aes(xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, + fill = Lego_color, alpha = alpha), color = "#333333") + + ggplot2::scale_fill_identity() + + ggplot2::scale_alpha_identity() + + ggplot2::coord_fixed(ratio = coord_ratio, expand = TRUE) + + ggplot2::facet_wrap(~Step) + + ggplot2::theme_minimal() + + ggplot2::theme( panel.background = ggplot2::element_rect(fill = "#7EC0EE"), + strip.background = ggplot2::element_rect(fill = "#F7F18D"), + strip.text = ggplot2::element_text(color = "#333333", face = "bold"), + axis.line = ggplot2::element_blank(), + axis.title.x = ggplot2::element_blank(), + axis.text.x = ggplot2::element_blank(), + axis.title.y = ggplot2::element_blank(), + axis.text.y = ggplot2::element_blank(), + legend.position = "none") +} diff --git a/R/build-mosaic.R b/R/build-mosaic.R index 0883b3d..f7499fa 100644 --- a/R/build-mosaic.R +++ b/R/build-mosaic.R @@ -1,21 +1,19 @@ #' Display 2D LEGO mosaic as a plot image #' -#' @param image_list List output from collect_bricks() or image_to_bricks(). Contains an element \code{Img_lego}. +#' @param brick_obj List output from image_to_bricks(). Contains an element \code{Img_lego}. #' @param title Optional title to include above plotted mosaic. #' @family Mosaics #' @export #' -build_mosaic <- function(image_list, title=NULL){ - in_list <- image_list +build_mosaic <- function(brick_obj, title=NULL){ + in_list <- brick_obj image <- in_list$Img_bricks type <- in_list$mosaic_type coord_x <- c(min(image$xmin)+0.5, max(image$xmax)-0.5) coord_y <- c(min(image$ymin)+0.5, max(image$ymax)-0.5) - - if(type == "stacked") stop("Stacked mosaics have been removed from brickr. Only flat / 'knobs-up' mosaics are supported.") - + img <- ggplot2::ggplot(in_list$Img_lego, ggplot2::aes(x=x, y=y)) + geom_brick_rect(ggplot2::aes(fill = Lego_color), color = "#333333")+ ggplot2::scale_fill_identity() + @@ -28,56 +26,3 @@ build_mosaic <- function(image_list, title=NULL){ return(img) } -#' Create instruction manual for 2D image mosaics -#' -#' @param image_list Mosaic object from image_to_mosaic(). -#' @param num_steps Number of discrete steps in instruction manual -#' @family Mosaics -#' @export -#' - -build_instructions <- function(image_list, num_steps=6) { - in_list <- image_list - image <- in_list$Img_bricks - type <- in_list$mosaic_type - - num_steps <- min(abs(round(num_steps)), 40) - - rows_per_step <- ceiling((max(image$ymax)-0.5) / (num_steps+1)) - - create_steps <- function(a, n_steps) { - if(a < n_steps){ - image %>% - dplyr::group_by(brick_name) %>% - dplyr::filter(min(ymin) <= a*rows_per_step+(min(image$ymin)+0.5)) %>% - dplyr::ungroup() %>% - dplyr::mutate(Step = paste("Step", (if(a<10){paste0('0', a)}else{a}))) - } else { - image %>% - dplyr::mutate(Step = paste("Step", (if(a<10){paste0('0', a)}else{a}))) - } - - } - - #Ratio of the "pixels" is different for flat or stacked bricks - coord_ratio <- 1 - - 1:num_steps %>% - purrr::map(create_steps, num_steps) %>% - dplyr::bind_rows() %>% - ggplot2::ggplot() + - ggplot2::geom_rect(ggplot2::aes(xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, - fill = Lego_color), color = "#333333") + - ggplot2::scale_fill_identity() + - ggplot2::coord_fixed(ratio = coord_ratio, expand = FALSE) + - ggplot2::facet_wrap(~Step) + - ggplot2::theme_minimal() + - ggplot2::theme( panel.background = ggplot2::element_rect(fill = "#7EC0EE"), - strip.background = ggplot2::element_rect(fill = "#F7F18D"), - strip.text = ggplot2::element_text(color = "#333333", face = "bold"), - axis.line = ggplot2::element_blank(), - axis.title.x = ggplot2::element_blank(), - axis.text.x = ggplot2::element_blank(), - axis.title.y = ggplot2::element_blank(), - axis.text.y = ggplot2::element_blank()) -} diff --git a/R/collect-bricks.R b/R/collect-bricks.R index b70c2de..826de1b 100644 --- a/R/collect-bricks.R +++ b/R/collect-bricks.R @@ -111,7 +111,6 @@ collect_bricks <- function(image_list, use_bricks = NULL){ in_list[["Img_bricks"]] <- img2 in_list[["ID_bricks"]] <- bricks_df - in_list[["mosaic_type"]] <- "flat" in_list[["pieces"]] <- pcs return(in_list) diff --git a/R/piece-count.R b/R/piece-count.R index cc4ad1d..9398588 100644 --- a/R/piece-count.R +++ b/R/piece-count.R @@ -1,12 +1,12 @@ #' Generate required bricks as a data frame. #' -#' @param image_list Mosaic output from image_to_mosaic(). +#' @param brick_obj brickr mosaic or 3D model object. #' @return Data frame of piece counts by LEGO color name and size. #' @family Resources #' @export -build_pieces_table <- function(image_list){ - pcs <- image_list$pieces +build_pieces_table <- function(brick_obj){ + pcs <- brick_obj$pieces pcs %>% dplyr::select(-Lego_color) %>% @@ -14,26 +14,25 @@ build_pieces_table <- function(image_list){ dplyr::rename(`LEGO Brick Color` = Lego_name) } -#' Graphically display required bricks. +#' Display bricks required to build model or mosaic. #' -#' @param image_list Mosaic output from image_to_mosaic(). +#' @param brick_obj brickr mosaic or 3D model object. #' @return Plot object of required bricks by color and size. #' @family Resources #' @export #' -build_pieces <- function(image_list){ - in_list <- image_list +build_pieces <- function(brick_obj){ + in_list <- brick_obj pcs <- in_list$pieces - - pcs_coords <- dplyr::tibble( - Brick_size = c("1 x 1", "2 x 1", "3 x 1", "4 x 1", "2 x 2", "4 x 2"), - xmin = c(0, 0, 0, 0, 6, 6), - xmax = c(1, 2, 3, 4, 8, 8), - ymin = c(0, 2, 4, 6, 0, 3), - ymax = c(1, 3, 5, 7, 2, 7) - ) + pcs_coords <- dplyr::tibble( + Brick_size = c("1 x 1", "2 x 1", "3 x 1", "4 x 1", "2 x 2", "4 x 2"), + xmin = c(0, 0, 0, 0, 6, 6), + xmax = c(1, 2, 3, 4, 8, 8), + ymin = c(0, 2, 4, 6, 0, 3), + ymax = c(1, 3, 5, 7, 2, 7) + ) #This function creates nodes in each brick for stud placement pcs_coords <- pcs_coords %>% @@ -45,33 +44,28 @@ build_pieces <- function(image_list){ pcs2 <- pcs %>% dplyr::arrange(Lego_color) %>% dplyr::mutate(Lego_name = factor(Lego_name, - levels = c("Black", - unique(Lego_name)[!(unique(Lego_name) %in% c("Black", "White"))], - "White"))) %>% + levels = c("Black", + unique(Lego_name)[!(unique(Lego_name) %in% c("Black", "White"))], + "White"))) %>% dplyr::left_join(pcs_coords, by = "Brick_size") - coord_xlim <- c(-0.5, 10) - facet_cols <- 5 - + coord_xlim <- c(-0.5, 10) + facet_cols <- 5 + pcs2 %>% ggplot2::ggplot() + ggplot2::geom_rect(ggplot2::aes(xmin=xmin, xmax=xmax, ymin=-ymin, ymax=-ymax, - fill = Lego_color), color = "#333333")+ + fill = Lego_color), color = "#333333")+ ggplot2::scale_fill_identity() + ggplot2::geom_point(data = pcs2 %>% tidyr::unnest(studs), ggplot2::aes(x=x, y=-y), color = "#cccccc", alpha = 0.25, - shape = 1, size = 2) + + shape = 1, size = 2) + ggplot2::geom_text( - ggplot2::aes(x = xmax + 0.25, y = -(ymin+ymax)/2, label = paste0("x", n)), - hjust = 0, vjust = 0.5, size = 3.5) + + ggplot2::aes(x = xmax + 0.25, y = -(ymin+ymax)/2, label = paste0("x", n)), + hjust = 0, vjust = 0.5, size = 3.5) + ggplot2::coord_fixed(xlim = coord_xlim) + - ggplot2::labs(title = (if(in_list$mosaic_type == "stacked"){ - "Suggested LEGO Bricks" - }else{"Suggested LEGO Plates"}), - caption = (if(in_list$mosaic_type == "stacked"){ - "Mosaic is 2-bricks deep. Can substitute 2-stud bricks for 1-stud alternatives for a thinner mosaic."}else{""}) - ) + + ggplot2::labs(title = "Suggested LEGO Bricks") + ggplot2::facet_wrap(~Lego_name, ncol=facet_cols) + ggplot2::theme_minimal() + ggplot2::theme( panel.background = ggplot2::element_rect(fill = "#7EC0EE"), diff --git a/README.Rmd b/README.Rmd index 3661c41..377dfd8 100644 --- a/README.Rmd +++ b/README.Rmd @@ -174,10 +174,7 @@ sphere_coords %>% bricks_from_coords() %>% build_bricks(phi = 30, theta = 30) -rayshader::render_snapshot() -``` -```{r, echo=FALSE} - rgl::rgl.clear() +rayshader::render_snapshot(clear = TRUE) ``` ### Examples diff --git a/README.md b/README.md index ec3bad0..ae71442 100644 --- a/README.md +++ b/README.md @@ -136,7 +136,7 @@ brick %>% bricks_from_table() %>% build_bricks(brick_res = "uhd") -rayshader::render_snapshot() +rayshader::render_snapshot( clear = TRUE) ``` ![](README_files/figure-gfm/bricks_1-1.png) @@ -185,7 +185,7 @@ my_first_model %>% bricks_from_table(brick_colors) %>% build_bricks(theta = 210, brick_res = "hd") -rayshader::render_snapshot() +rayshader::render_snapshot(clear = TRUE) ``` ![](README_files/figure-gfm/bricks_5-1.png) @@ -218,7 +218,7 @@ sphere_coords %>% bricks_from_coords() %>% build_bricks(phi = 30, theta = 30) -rayshader::render_snapshot() +rayshader::render_snapshot(clear = TRUE) ``` ![](README_files/figure-gfm/bricks_6-1.png) diff --git a/README_files/figure-gfm/geom_brick2-1.png b/README_files/figure-gfm/geom_brick2-1.png index 6fa750b..71c8df2 100644 Binary files a/README_files/figure-gfm/geom_brick2-1.png and b/README_files/figure-gfm/geom_brick2-1.png differ diff --git a/README_files/figure-gfm/m1_instructions-1.png b/README_files/figure-gfm/m1_instructions-1.png index aa82670..28ec7ff 100644 Binary files a/README_files/figure-gfm/m1_instructions-1.png and b/README_files/figure-gfm/m1_instructions-1.png differ diff --git a/README_files/figure-gfm/m1_pieces-1.png b/README_files/figure-gfm/m1_pieces-1.png index 9f10081..cb5fd2f 100644 Binary files a/README_files/figure-gfm/m1_pieces-1.png and b/README_files/figure-gfm/m1_pieces-1.png differ diff --git a/_pkgdown.yml b/_pkgdown.yml index 52a00a2..0cb5cda 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -26,4 +26,4 @@ reference: - build_colors - build_instructions - starts_with("build_pieces") - - build_themes \ No newline at end of file + - build_themes diff --git a/docs/LICENSE-text.html b/docs/LICENSE-text.html index 7172b10..3ad2e03 100644 --- a/docs/LICENSE-text.html +++ b/docs/LICENSE-text.html @@ -70,7 +70,7 @@ brickr - 0.1.0.9011 + 0.1.0.9014 @@ -95,6 +95,15 @@
  • ggplot with brickr
  • +
  • + 3D Models from mosaics & rayshader +
  • +
  • + 3D Models programmatically +
  • +
  • + 3D models from tables +
  • Mosaics with brickr
  • diff --git a/docs/LICENSE.html b/docs/LICENSE.html index 4a7af25..dc895ad 100644 --- a/docs/LICENSE.html +++ b/docs/LICENSE.html @@ -70,7 +70,7 @@ brickr - 0.1.0.9011 + 0.1.0.9014 @@ -95,6 +95,15 @@
  • ggplot with brickr
  • +
  • + 3D Models from mosaics & rayshader +
  • +
  • + 3D Models programmatically +
  • +
  • + 3D models from tables +
  • Mosaics with brickr
  • diff --git a/docs/articles/graphs.html b/docs/articles/graphs.html index 7b13e9b..b4b2976 100644 --- a/docs/articles/graphs.html +++ b/docs/articles/graphs.html @@ -37,7 +37,7 @@ brickr - 0.1.0.9011 + 0.1.0.9014 @@ -62,6 +62,15 @@
  • ggplot with brickr
  • +
  • + 3D Models from mosaics & rayshader +
  • +
  • + 3D Models programmatically +
  • +
  • + 3D models from tables +
  • Mosaics with brickr
  • @@ -112,7 +121,7 @@ scale_fill_brick() + coord_brick() + theme_brick() -

    +

    brickr also includes tools help users create the Mosaics and 3D model output using real LEGO® elements.

    +
    +

    +What’s the point?

    +

    The goal of {brickr} is to provide a series of tools to integrate the LEGO® system with R by:

    +

    brickr is developed using publicly available information about LEGO® products and is not officially affiliated with The LEGO Group

    +

    Installation

    @@ -172,7 +191,7 @@ bricks_from_table() %>% build_bricks(brick_res = "uhd") -rayshader::render_snapshot()
    +rayshader::render_snapshot( clear = TRUE)

    @@ -213,7 +232,7 @@ bricks_from_table(brick_colors) %>% build_bricks(theta = 210, brick_res = "hd") -rayshader::render_snapshot()

    +rayshader::render_snapshot(clear = TRUE)

    @@ -240,7 +259,7 @@ bricks_from_coords() %>% build_bricks(phi = 30, theta = 30) -rayshader::render_snapshot()
    +rayshader::render_snapshot(clear = TRUE)

    @@ -333,7 +352,7 @@

    Dev status

    diff --git a/docs/index_files/figure-html/geom_brick2-1.png b/docs/index_files/figure-html/geom_brick2-1.png index 0a163a8..1c5748e 100644 Binary files a/docs/index_files/figure-html/geom_brick2-1.png and b/docs/index_files/figure-html/geom_brick2-1.png differ diff --git a/docs/index_files/figure-html/m1_instructions-1.png b/docs/index_files/figure-html/m1_instructions-1.png index 055f56e..dcd71aa 100644 Binary files a/docs/index_files/figure-html/m1_instructions-1.png and b/docs/index_files/figure-html/m1_instructions-1.png differ diff --git a/docs/index_files/figure-html/m1_pieces-1.png b/docs/index_files/figure-html/m1_pieces-1.png index 4908a59..b3cf86c 100644 Binary files a/docs/index_files/figure-html/m1_pieces-1.png and b/docs/index_files/figure-html/m1_pieces-1.png differ diff --git a/docs/news/index.html b/docs/news/index.html index 8297743..d022695 100644 --- a/docs/news/index.html +++ b/docs/news/index.html @@ -70,7 +70,7 @@ brickr - 0.1.0.9011 + 0.1.0.9014 @@ -95,6 +95,15 @@
  • ggplot with brickr
  • +
  • + 3D Models from mosaics & rayshader +
  • +
  • + 3D Models programmatically +
  • +
  • + 3D models from tables +
  • Mosaics with brickr
  • @@ -135,16 +144,12 @@
  • Breaking: Pretty much EVERY function. Seriously, check out the README and start fresh.

  • Breaking: Data “lego_colors.rda” has been updated with more accurate RGB values and new brickrID numbers. This will impact previously created mosaics and 3D models.

  • -
    +

    -Documentations

    +Documentation
    @@ -170,6 +175,8 @@
  • Option to use plates rather than bricks. Combining the two involves some hacking.
  • Updated brick collection algorithm to allow for custom brick input.
  • Updated brick collection algorithm staggers bricks over layer, though still prioritizes larger bricks.
  • +
  • +build_instructions generates building instructions for 3D models, as well as mosaics.
  • @@ -189,13 +196,9 @@ TO DO
    @@ -97,6 +97,15 @@
  • ggplot with brickr
  • +
  • + 3D Models from mosaics & rayshader +
  • +
  • + 3D Models programmatically +
  • +
  • + 3D models from tables +
  • Mosaics with brickr
  • diff --git a/docs/reference/bricks_from_coords.html b/docs/reference/bricks_from_coords.html index 1fa7a18..5e5bf10 100644 --- a/docs/reference/bricks_from_coords.html +++ b/docs/reference/bricks_from_coords.html @@ -72,7 +72,7 @@ brickr - 0.1.0.9011 + 0.1.0.9014
    @@ -97,6 +97,15 @@
  • ggplot with brickr
  • +
  • + 3D Models from mosaics & rayshader +
  • +
  • + 3D Models programmatically +
  • +
  • + 3D models from tables +
  • Mosaics with brickr
  • diff --git a/docs/reference/bricks_from_excel.html b/docs/reference/bricks_from_excel.html index 9e7a622..093a0a4 100644 --- a/docs/reference/bricks_from_excel.html +++ b/docs/reference/bricks_from_excel.html @@ -72,7 +72,7 @@ brickr - 0.1.0.9011 + 0.1.0.9014 @@ -97,6 +97,15 @@
  • ggplot with brickr
  • +
  • + 3D Models from mosaics & rayshader +
  • +
  • + 3D Models programmatically +
  • +
  • + 3D models from tables +
  • Mosaics with brickr
  • diff --git a/docs/reference/bricks_from_mosaic.html b/docs/reference/bricks_from_mosaic.html index fbb399b..4206621 100644 --- a/docs/reference/bricks_from_mosaic.html +++ b/docs/reference/bricks_from_mosaic.html @@ -72,7 +72,7 @@ brickr - 0.1.0.9011 + 0.1.0.9014 @@ -97,6 +97,15 @@
  • ggplot with brickr
  • +
  • + 3D Models from mosaics & rayshader +
  • +
  • + 3D Models programmatically +
  • +
  • + 3D models from tables +
  • Mosaics with brickr
  • diff --git a/docs/reference/bricks_from_rayshader.html b/docs/reference/bricks_from_rayshader.html index 23fb3f3..b0e9227 100644 --- a/docs/reference/bricks_from_rayshader.html +++ b/docs/reference/bricks_from_rayshader.html @@ -72,7 +72,7 @@ brickr - 0.1.0.9011 + 0.1.0.9014 @@ -97,6 +97,15 @@
  • ggplot with brickr
  • +
  • + 3D Models from mosaics & rayshader +
  • +
  • + 3D Models programmatically +
  • +
  • + 3D models from tables +
  • Mosaics with brickr
  • diff --git a/docs/reference/bricks_from_table.html b/docs/reference/bricks_from_table.html index a1e4a69..1fc1107 100644 --- a/docs/reference/bricks_from_table.html +++ b/docs/reference/bricks_from_table.html @@ -72,7 +72,7 @@ brickr - 0.1.0.9011 + 0.1.0.9014 @@ -97,6 +97,15 @@
  • ggplot with brickr
  • +
  • + 3D Models from mosaics & rayshader +
  • +
  • + 3D Models programmatically +
  • +
  • + 3D models from tables +
  • Mosaics with brickr
  • diff --git a/docs/reference/build_bricks.html b/docs/reference/build_bricks.html index f770154..45ab5e6 100644 --- a/docs/reference/build_bricks.html +++ b/docs/reference/build_bricks.html @@ -72,7 +72,7 @@ brickr - 0.1.0.9011 + 0.1.0.9014 @@ -97,6 +97,15 @@
  • ggplot with brickr
  • +
  • + 3D Models from mosaics & rayshader +
  • +
  • + 3D Models programmatically +
  • +
  • + 3D models from tables +
  • Mosaics with brickr
  • diff --git a/docs/reference/build_colors.html b/docs/reference/build_colors.html index 36bb1fc..6b733cb 100644 --- a/docs/reference/build_colors.html +++ b/docs/reference/build_colors.html @@ -72,7 +72,7 @@ brickr - 0.1.0.9011 + 0.1.0.9014 @@ -97,6 +97,15 @@
  • ggplot with brickr
  • +
  • + 3D Models from mosaics & rayshader +
  • +
  • + 3D Models programmatically +
  • +
  • + 3D models from tables +
  • Mosaics with brickr
  • @@ -154,7 +163,8 @@

    See also

    -

    Other Resources: build_pieces_table, +

    Other Resources: build_instructions, + build_pieces_table, build_pieces, build_themes

    diff --git a/docs/reference/build_instructions.html b/docs/reference/build_instructions.html index d57123b..1eb9d0f 100644 --- a/docs/reference/build_instructions.html +++ b/docs/reference/build_instructions.html @@ -72,7 +72,7 @@ brickr - 0.1.0.9011 + 0.1.0.9014
    @@ -97,6 +97,15 @@
  • ggplot with brickr
  • +
  • + 3D Models from mosaics & rayshader +
  • +
  • + 3D Models programmatically +
  • +
  • + 3D models from tables +
  • Mosaics with brickr
  • @@ -127,7 +136,7 @@
    @@ -137,25 +146,26 @@
    -
    build_instructions(image_list, num_steps = 6)
    +
    build_instructions(brickr_obj, num_steps = 6)

    Arguments

    - - + + - +
    image_list

    Mosaic object from image_to_mosaic().

    brickr_obj

    brickr mosaic or 3D model object.

    num_steps

    Number of discrete steps in instruction manual

    Number of discrete steps in instruction manual, for mosaics only

    See also

    -

    Other Mosaics: build_mosaic, - image_to_mosaic

    +

    Other Resources: build_colors, + build_pieces_table, + build_pieces, build_themes

    diff --git a/docs/reference/build_mosaic.html b/docs/reference/build_mosaic.html index 285cf7e..7cec99f 100644 --- a/docs/reference/build_mosaic.html +++ b/docs/reference/build_mosaic.html @@ -72,7 +72,7 @@ brickr - 0.1.0.9011 + 0.1.0.9014 @@ -97,6 +97,15 @@
  • ggplot with brickr
  • +
  • + 3D Models from mosaics & rayshader +
  • +
  • + 3D Models programmatically +
  • +
  • + 3D models from tables +
  • Mosaics with brickr
  • @@ -137,14 +146,14 @@ -
    build_mosaic(image_list, title = NULL)
    +
    build_mosaic(brick_obj, title = NULL)

    Arguments

    - - + + @@ -154,8 +163,7 @@

    See also

    -

    Other Mosaics: build_instructions, - image_to_mosaic

    +

    Other Mosaics: image_to_mosaic

    diff --git a/docs/reference/build_pieces.html b/docs/reference/build_pieces.html index 20879d1..56bf580 100644 --- a/docs/reference/build_pieces.html +++ b/docs/reference/build_pieces.html @@ -6,7 +6,7 @@ -Graphically display required bricks. — build_pieces • brickr +Display bricks required to build model or mosaic. — build_pieces • brickr @@ -37,9 +37,9 @@ - + - + @@ -72,7 +72,7 @@ brickr - 0.1.0.9011 + 0.1.0.9014 @@ -97,6 +97,15 @@
  • ggplot with brickr
  • +
  • + 3D Models from mosaics & rayshader +
  • +
  • + 3D Models programmatically +
  • +
  • + 3D models from tables +
  • Mosaics with brickr
  • @@ -126,25 +135,25 @@
    -

    Graphically display required bricks.

    +

    Display bricks required to build model or mosaic.

    -
    build_pieces(image_list)
    +
    build_pieces(brick_obj)

    Arguments

    image_list

    List output from collect_bricks() or image_to_bricks(). Contains an element Img_lego.

    brick_obj

    List output from image_to_bricks(). Contains an element Img_lego.

    title
    - - + +
    image_list

    Mosaic output from image_to_mosaic().

    brick_obj

    brickr mosaic or 3D model object.

    @@ -155,6 +164,7 @@

    See also

    Other Resources: build_colors, + build_instructions, build_pieces_table, build_themes

    diff --git a/docs/reference/build_pieces_table.html b/docs/reference/build_pieces_table.html index 84a6184..69dfbd9 100644 --- a/docs/reference/build_pieces_table.html +++ b/docs/reference/build_pieces_table.html @@ -72,7 +72,7 @@ brickr - 0.1.0.9011 + 0.1.0.9014 @@ -97,6 +97,15 @@
  • ggplot with brickr
  • +
  • + 3D Models from mosaics & rayshader +
  • +
  • + 3D Models programmatically +
  • +
  • + 3D models from tables +
  • Mosaics with brickr
  • @@ -137,14 +146,14 @@ -
    build_pieces_table(image_list)
    +
    build_pieces_table(brick_obj)

    Arguments

    - - + +
    image_list

    Mosaic output from image_to_mosaic().

    brick_obj

    brickr mosaic or 3D model object.

    @@ -155,6 +164,7 @@

    See also

    Other Resources: build_colors, + build_instructions, build_pieces, build_themes

    diff --git a/docs/reference/build_themes.html b/docs/reference/build_themes.html index 1643c48..73c620a 100644 --- a/docs/reference/build_themes.html +++ b/docs/reference/build_themes.html @@ -72,7 +72,7 @@ brickr - 0.1.0.9011 + 0.1.0.9014 @@ -97,6 +97,15 @@
  • ggplot with brickr
  • +
  • + 3D Models from mosaics & rayshader +
  • +
  • + 3D Models programmatically +
  • +
  • + 3D models from tables +
  • Mosaics with brickr
  • @@ -159,6 +168,7 @@

    See also

    Other Resources: build_colors, + build_instructions, build_pieces_table, build_pieces

    diff --git a/docs/reference/collect_bricks.html b/docs/reference/collect_bricks.html index cbd0f9e..fe7fd1b 100644 --- a/docs/reference/collect_bricks.html +++ b/docs/reference/collect_bricks.html @@ -72,7 +72,7 @@ brickr - 0.1.0.9011 + 0.1.0.9014 @@ -97,6 +97,15 @@
  • ggplot with brickr
  • +
  • + 3D Models from mosaics & rayshader +
  • +
  • + 3D Models programmatically +
  • +
  • + 3D models from tables +
  • Mosaics with brickr
  • diff --git a/docs/reference/coord-brick.html b/docs/reference/coord-brick.html index fe01073..b6e477c 100644 --- a/docs/reference/coord-brick.html +++ b/docs/reference/coord-brick.html @@ -73,7 +73,7 @@ Use coord_brick_flip() for horizontal bars." /> brickr - 0.1.0.9011 + 0.1.0.9014 @@ -98,6 +98,15 @@ Use coord_brick_flip() for horizontal bars." />
  • ggplot with brickr
  • +
  • + 3D Models from mosaics & rayshader +
  • +
  • + 3D Models programmatically +
  • +
  • + 3D models from tables +
  • Mosaics with brickr
  • diff --git a/docs/reference/geom_brick_col.html b/docs/reference/geom_brick_col.html index f71db2a..d21e240 100644 --- a/docs/reference/geom_brick_col.html +++ b/docs/reference/geom_brick_col.html @@ -73,7 +73,7 @@ Bar height is determined by values in the data using the y aesthetic. With the e brickr - 0.1.0.9011 + 0.1.0.9014 @@ -98,6 +98,15 @@ Bar height is determined by values in the data using the y aesthetic. With the e
  • ggplot with brickr
  • +
  • + 3D Models from mosaics & rayshader +
  • +
  • + 3D Models programmatically +
  • +
  • + 3D models from tables +
  • Mosaics with brickr
  • diff --git a/docs/reference/geom_brick_rect.html b/docs/reference/geom_brick_rect.html index e529c1b..daf2f50 100644 --- a/docs/reference/geom_brick_rect.html +++ b/docs/reference/geom_brick_rect.html @@ -72,7 +72,7 @@ brickr - 0.1.0.9011 + 0.1.0.9014 @@ -97,6 +97,15 @@
  • ggplot with brickr
  • +
  • + 3D Models from mosaics & rayshader +
  • +
  • + 3D Models programmatically +
  • +
  • + 3D models from tables +
  • Mosaics with brickr
  • diff --git a/docs/reference/image_to_mosaic.html b/docs/reference/image_to_mosaic.html index 4092837..bcbba41 100644 --- a/docs/reference/image_to_mosaic.html +++ b/docs/reference/image_to_mosaic.html @@ -72,7 +72,7 @@ brickr - 0.1.0.9011 + 0.1.0.9014 @@ -97,6 +97,15 @@
  • ggplot with brickr
  • +
  • + 3D Models from mosaics & rayshader +
  • +
  • + 3D Models programmatically +
  • +
  • + 3D models from tables +
  • Mosaics with brickr
  • @@ -198,8 +207,7 @@ Use "bw" for only grayscale bricks. Ignored if a color_table is sup

    See also

    -

    Other Mosaics: build_instructions, - build_mosaic

    +

    Other Mosaics: build_mosaic

    diff --git a/docs/reference/image_to_scaled.html b/docs/reference/image_to_scaled.html index 505830a..a5fc787 100644 --- a/docs/reference/image_to_scaled.html +++ b/docs/reference/image_to_scaled.html @@ -72,7 +72,7 @@ brickr - 0.1.0.9011 + 0.1.0.9014 @@ -97,6 +97,15 @@
  • ggplot with brickr
  • +
  • + 3D Models from mosaics & rayshader +
  • +
  • + 3D Models programmatically +
  • +
  • + 3D models from tables +
  • Mosaics with brickr
  • diff --git a/docs/reference/index.html b/docs/reference/index.html index 571c045..6e964bf 100644 --- a/docs/reference/index.html +++ b/docs/reference/index.html @@ -70,7 +70,7 @@ brickr - 0.1.0.9011 + 0.1.0.9014 @@ -95,6 +95,15 @@
  • ggplot with brickr
  • +
  • + 3D Models from mosaics & rayshader +
  • +
  • + 3D Models programmatically +
  • +
  • + 3D models from tables +
  • Mosaics with brickr
  • @@ -261,7 +270,7 @@

    build_pieces()

    -

    Graphically display required bricks.

    +

    Display bricks required to build model or mosaic.

    diff --git a/docs/reference/layer_from_bricks.html b/docs/reference/layer_from_bricks.html index e71ff6c..422a313 100644 --- a/docs/reference/layer_from_bricks.html +++ b/docs/reference/layer_from_bricks.html @@ -72,7 +72,7 @@ brickr - 0.1.0.9011 + 0.1.0.9014 @@ -97,6 +97,15 @@
  • ggplot with brickr
  • +
  • + 3D Models from mosaics & rayshader +
  • +
  • + 3D Models programmatically +
  • +
  • + 3D models from tables +
  • Mosaics with brickr
  • diff --git a/docs/reference/pipe.html b/docs/reference/pipe.html index 07a0b8b..ef3e7ff 100644 --- a/docs/reference/pipe.html +++ b/docs/reference/pipe.html @@ -72,7 +72,7 @@ brickr - 0.1.0.9011 + 0.1.0.9014 @@ -97,6 +97,15 @@
  • ggplot with brickr
  • +
  • + 3D Models from mosaics & rayshader +
  • +
  • + 3D Models programmatically +
  • +
  • + 3D models from tables +
  • Mosaics with brickr
  • diff --git a/docs/reference/scale_fill_brick.html b/docs/reference/scale_fill_brick.html index 38fc878..fb895b2 100644 --- a/docs/reference/scale_fill_brick.html +++ b/docs/reference/scale_fill_brick.html @@ -72,7 +72,7 @@ brickr - 0.1.0.9011 + 0.1.0.9014 @@ -97,6 +97,15 @@
  • ggplot with brickr
  • +
  • + 3D Models from mosaics & rayshader +
  • +
  • + 3D Models programmatically +
  • +
  • + 3D models from tables +
  • Mosaics with brickr
  • diff --git a/docs/reference/scaled_to_colors.html b/docs/reference/scaled_to_colors.html index 6314772..fa2ae10 100644 --- a/docs/reference/scaled_to_colors.html +++ b/docs/reference/scaled_to_colors.html @@ -72,7 +72,7 @@ brickr - 0.1.0.9011 + 0.1.0.9014 @@ -97,6 +97,15 @@
  • ggplot with brickr
  • +
  • + 3D Models from mosaics & rayshader +
  • +
  • + 3D Models programmatically +
  • +
  • + 3D models from tables +
  • Mosaics with brickr
  • diff --git a/docs/reference/theme_brick.html b/docs/reference/theme_brick.html index 30cfe41..0b0c285 100644 --- a/docs/reference/theme_brick.html +++ b/docs/reference/theme_brick.html @@ -72,7 +72,7 @@ brickr - 0.1.0.9011 + 0.1.0.9014 @@ -97,6 +97,15 @@
  • ggplot with brickr
  • +
  • + 3D Models from mosaics & rayshader +
  • +
  • + 3D Models programmatically +
  • +
  • + 3D models from tables +
  • Mosaics with brickr
  • diff --git a/docs/sitemap.xml b/docs/sitemap.xml index 6948177..d0fb054 100644 --- a/docs/sitemap.xml +++ b/docs/sitemap.xml @@ -78,6 +78,15 @@ http://brickr.org/articles/graphs.html + + http://brickr.org/articles/models-from-other.html + + + http://brickr.org/articles/models-from-program.html + + + http://brickr.org/articles/models-from-tables.html + http://brickr.org/articles/mosaics.html diff --git a/man/build_colors.Rd b/man/build_colors.Rd index 9973c56..1445c90 100644 --- a/man/build_colors.Rd +++ b/man/build_colors.Rd @@ -23,7 +23,8 @@ build_colors() build_colors(TRUE) } \seealso{ -Other Resources: \code{\link{build_pieces_table}}, +Other Resources: \code{\link{build_instructions}}, + \code{\link{build_pieces_table}}, \code{\link{build_pieces}}, \code{\link{build_themes}} } \concept{Resources} diff --git a/man/build_instructions.Rd b/man/build_instructions.Rd index 2690cb3..68caf9f 100644 --- a/man/build_instructions.Rd +++ b/man/build_instructions.Rd @@ -1,21 +1,22 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/build-mosaic.R +% Please edit documentation in R/build-instructions.R \name{build_instructions} \alias{build_instructions} \title{Create instruction manual for 2D image mosaics} \usage{ -build_instructions(image_list, num_steps = 6) +build_instructions(brickr_obj, num_steps = 6) } \arguments{ -\item{image_list}{Mosaic object from image_to_mosaic().} +\item{brickr_obj}{brickr mosaic or 3D model object.} -\item{num_steps}{Number of discrete steps in instruction manual} +\item{num_steps}{Number of discrete steps in instruction manual, for mosaics only} } \description{ Create instruction manual for 2D image mosaics } \seealso{ -Other Mosaics: \code{\link{build_mosaic}}, - \code{\link{image_to_mosaic}} +Other Resources: \code{\link{build_colors}}, + \code{\link{build_pieces_table}}, + \code{\link{build_pieces}}, \code{\link{build_themes}} } -\concept{Mosaics} +\concept{Resources} diff --git a/man/build_mosaic.Rd b/man/build_mosaic.Rd index 738d8b5..0f85cd1 100644 --- a/man/build_mosaic.Rd +++ b/man/build_mosaic.Rd @@ -4,10 +4,10 @@ \alias{build_mosaic} \title{Display 2D LEGO mosaic as a plot image} \usage{ -build_mosaic(image_list, title = NULL) +build_mosaic(brick_obj, title = NULL) } \arguments{ -\item{image_list}{List output from collect_bricks() or image_to_bricks(). Contains an element \code{Img_lego}.} +\item{brick_obj}{List output from image_to_bricks(). Contains an element \code{Img_lego}.} \item{title}{Optional title to include above plotted mosaic.} } @@ -15,7 +15,6 @@ build_mosaic(image_list, title = NULL) Display 2D LEGO mosaic as a plot image } \seealso{ -Other Mosaics: \code{\link{build_instructions}}, - \code{\link{image_to_mosaic}} +Other Mosaics: \code{\link{image_to_mosaic}} } \concept{Mosaics} diff --git a/man/build_pieces.Rd b/man/build_pieces.Rd index 4b1820d..27ab599 100644 --- a/man/build_pieces.Rd +++ b/man/build_pieces.Rd @@ -2,21 +2,22 @@ % Please edit documentation in R/piece-count.R \name{build_pieces} \alias{build_pieces} -\title{Graphically display required bricks.} +\title{Display bricks required to build model or mosaic.} \usage{ -build_pieces(image_list) +build_pieces(brick_obj) } \arguments{ -\item{image_list}{Mosaic output from image_to_mosaic().} +\item{brick_obj}{brickr mosaic or 3D model object.} } \value{ Plot object of required bricks by color and size. } \description{ -Graphically display required bricks. +Display bricks required to build model or mosaic. } \seealso{ Other Resources: \code{\link{build_colors}}, + \code{\link{build_instructions}}, \code{\link{build_pieces_table}}, \code{\link{build_themes}} } diff --git a/man/build_pieces_table.Rd b/man/build_pieces_table.Rd index 8fef7af..0b8f9cf 100644 --- a/man/build_pieces_table.Rd +++ b/man/build_pieces_table.Rd @@ -4,10 +4,10 @@ \alias{build_pieces_table} \title{Generate required bricks as a data frame.} \usage{ -build_pieces_table(image_list) +build_pieces_table(brick_obj) } \arguments{ -\item{image_list}{Mosaic output from image_to_mosaic().} +\item{brick_obj}{brickr mosaic or 3D model object.} } \value{ Data frame of piece counts by LEGO color name and size. @@ -17,6 +17,7 @@ Generate required bricks as a data frame. } \seealso{ Other Resources: \code{\link{build_colors}}, + \code{\link{build_instructions}}, \code{\link{build_pieces}}, \code{\link{build_themes}} } \concept{Resources} diff --git a/man/build_themes.Rd b/man/build_themes.Rd index ee1b9fd..e8ff5ca 100644 --- a/man/build_themes.Rd +++ b/man/build_themes.Rd @@ -27,6 +27,7 @@ build_themes(.names_only = TRUE) } \seealso{ Other Resources: \code{\link{build_colors}}, + \code{\link{build_instructions}}, \code{\link{build_pieces_table}}, \code{\link{build_pieces}} } diff --git a/man/image_to_mosaic.Rd b/man/image_to_mosaic.Rd index be38cfe..d54de0a 100644 --- a/man/image_to_mosaic.Rd +++ b/man/image_to_mosaic.Rd @@ -42,7 +42,6 @@ A list with element \code{Img_lego} containing a data frame of the x- & y-coordi Create a 2D LEGO mosaic from an image array } \seealso{ -Other Mosaics: \code{\link{build_instructions}}, - \code{\link{build_mosaic}} +Other Mosaics: \code{\link{build_mosaic}} } \concept{Mosaics} diff --git a/vignettes/dem_01.tif b/vignettes/dem_01.tif new file mode 100644 index 0000000..4f9011d Binary files /dev/null and b/vignettes/dem_01.tif differ diff --git a/vignettes/models-from-other.Rmd b/vignettes/models-from-other.Rmd new file mode 100644 index 0000000..cbc2480 --- /dev/null +++ b/vignettes/models-from-other.Rmd @@ -0,0 +1,89 @@ +--- +title: "3D Models from mosaics & rayshader" +output: rmarkdown::html_vignette +vignette: > + %\VignetteIndexEntry{graphs} + %\VignetteEngine{knitr::rmarkdown} + %\VignetteEncoding{UTF-8} +--- + +```{r, include = FALSE} +knitr::opts_chunk$set( +collapse = TRUE, +comment = "#>" +) +``` + +```{r setup, include = FALSE} +library(brickr) +``` + +## Getting started + +The `bricks_from_*` series of functions creates 3D models of LEGO bricks from a variety of input formats. These models are rendered using [Tyler Morgan-Wall](https://twitter.com/tylermorganwall)'s [rayshader](https://www.rayshader.com/) package. This package must be installed. + +## 3D mosaics + +Begin with a brickr mosaic from an image. Rather than graphically rendering the mosaic using `build_mosaic()`, use `bricks_from_mosaic()`. This function takes two other inputs: + +* `mosaic_height` is the number of bricks stacked at the mosaic's highest point. The default is 6. +* `highest_el` specifies if 'light' or 'dark' color bricks should be the tallest in the model. The default is 'light'. + +```{r bricks_6, echo=TRUE, warning=FALSE, message=FALSE, fig.width=4, fig.height=4} +mosaic <- png::readPNG("../Images/mf_unicorn.PNG") %>% + image_to_mosaic() + +mosaic %>% build_mosaic() + +mosaic %>% + bricks_from_mosaic(highest_el = "dark") %>% + build_bricks(phi = 60, theta = 15) + +rayshader::render_snapshot(clear = TRUE) +``` + +## Models from rayshader + +[rayshader](https://www.rayshader.com/) by [Tyler Morgan-Wall](https://twitter.com/tylermorganwall) is an open source package for producing 2D and 3D data visualizations in R. rayshader uses elevation data in a base R matrix and a combination of raytracing, spherical texture mapping, overlays, and ambient occlusion to generate beautiful topographic 2D and 3D maps. (Note: text lifted straight from [rayshader.com](https://www.rayshader.com/).) + +3D models in **brickr** are rendered using the functions in **rayshader**. Using `bricks_from_rayshader()`, you can convert rayshader map output into a brickr model. This function takes three inputs: + +* `hillshade` is topographic image matrix with an RGB channel (much like the mosaics). +* `heightmap` is a two-dimensional matrix specifiying the height of the image at each location. +* `max_height` is the number of bricks stacked at the mosaic's highest point. The default is 12. +* `img_size` is the number of bricks on each side of the model. The default is 48. + + +```{r bricks_rayshader, echo=TRUE, warning=FALSE, message=FALSE, fig.width=4, fig.height=4} +library(rayshader) + +#Example from rayshader.com + +#Here, I load a map with the raster package. +loadzip = tempfile() +download.file("https://tylermw.com/data/dem_01.tif.zip", loadzip) +localtif = raster::raster(unzip(loadzip, "dem_01.tif")) +unlink(loadzip) + +#And convert it to a matrix: +elmat = matrix(raster::extract(localtif, raster::extent(localtif), buffer = 1000), + nrow = ncol(localtif), ncol = nrow(localtif)) + +rayshader_object <- elmat %>% + sphere_shade(texture = "desert") %>% + add_water(detect_water(elmat), color = "desert") %>% + add_shadow(ray_shade(elmat, zscale = 3, maxsearch = 300), 0.5) + +#Plot with rayshader +rayshader_object %>% + plot_3d(elmat, zscale = 10, fov = 0, theta = 135, zoom = 0.75, phi = 45, windowsize = c(1000, 800)) + +rayshader::render_snapshot(clear = TRUE) + +#Plot as bricks +rayshader_object %>% + bricks_from_rayshader(elmat) %>% + build_bricks(theta = 135, zoom = 0.75, phi = 45) + +rayshader::render_snapshot(clear = TRUE) +``` diff --git a/vignettes/models-from-program.Rmd b/vignettes/models-from-program.Rmd new file mode 100644 index 0000000..26f78f1 --- /dev/null +++ b/vignettes/models-from-program.Rmd @@ -0,0 +1,148 @@ +--- +title: "3D Models programmatically" +output: rmarkdown::html_vignette +vignette: > + %\VignetteIndexEntry{graphs} + %\VignetteEngine{knitr::rmarkdown} + %\VignetteEncoding{UTF-8} +--- + +```{r, include = FALSE} +knitr::opts_chunk$set( +collapse = TRUE, +comment = "#>" +) +``` + +```{r setup, include = FALSE} +library(brickr) +``` + +## Getting started + +The `bricks_from_*` series of functions creates 3D models of LEGO bricks from a variety of input formats. These models are rendered using [Tyler Morgan-Wall](https://twitter.com/tylermorganwall)'s [rayshader](https://www.rayshader.com/) package. This package must be installed. + +Use `bricks_from_coords()` to programmatically build 3D LEGO models rather than manually drawing them in a spreadsheet or table. Prove the function with a data frame with x, y, and z coordinates, along with an official LEGO color name for each point. + +## A simple programmed model + +Below, we create a 8x8x8 cube by expanding a data frame with the array 1:8 as the x-, y-, and z-coordinates. We then assign each row of that data frame one of three colors: Bright blue, Bright yellow, or Bright red. + +```{r bricks_6, echo=TRUE, warning=FALSE, message=FALSE, fig.width=4, fig.height=4} +use_colors <- c("Bright blue", "Bright yellow", "Bright red") + +cube <- expand.grid( + x = 1:8, + y = 1:8, + z = 1:8 +) + +cube$Color <- sample(use_colors, nrow(cube), replace = TRUE, prob = c(5, 3, 1)) + +cube %>% + bricks_from_coords() %>% + build_bricks(brick_res = "hd", phi = 30, theta = 30) + +rayshader::render_snapshot(clear = TRUE) +``` + +Using the same logic, we can build a sphere with a specified radius, and then apply rules to color each brick based on its coordinates. + +```{r bricks_7, echo=TRUE, warning=FALSE, message=FALSE, fig.width=4, fig.height=4} +radius <- 4 +sphere_coords <- expand.grid( + x = 1:round((radius*2.5)), + y = 1:round((radius*2.5)), + z = 1:round((radius/(6/5)*2.5)) #A brick is 6/5 taller than it is wide/deep +) %>% + dplyr::mutate( + #Distance of each coordinate from center + dist = (((x-mean(x))^2 + (y-mean(y))^2 + (z-mean(z))^2)^(1/2)), + Color = dplyr::case_when( + #Yellow stripes on the surface with a 2to4 thickness + dplyr::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() %>% + build_bricks(brick_res = "hd", phi = 30, theta = 30) + +rayshader::render_snapshot(clear = TRUE) +``` + +## It takes a village + +Rather than directly writing a data frame for a model, you can write a function that returns a data frame with x, y, z, and Color coordinates given initial starting parameters. + +Below, the function `brick_house()` creates a LEGO house with randomized colors. The x- and y-coordinates and the size of the house are inputs to the functions. + +```{r bricks_8, echo=TRUE, warning=FALSE, message=FALSE, fig.width=4, fig.height=4} +brick_house <- function(x_coord = 0, y_coord = 0, width=6, length=5, height=6){ + roof_colors <- c("Dark orange", "Dark brown", "Medium nougat", "Medium stone grey") + roof_col <- sample(roof_colors, 1) + + house_colors <- c("Bright blue", "Bright red", "Dark red", "Dark azur", "Nougat", "Bright reddish violet") + house_col <- sample(house_colors, 1) + + house_coords <- expand.grid( + x = 1:width, y = 1:length, z = (1:height)+1 + ) %>% + dplyr::mutate( + roof = (z > round((1/2)*height)), + Color = dplyr::case_when( + #Roof + roof & (abs(y - floor(length/2) -1) <= (height-z)) ~ roof_col, + roof ~ NA_character_, + #Door and windows + x == round(width/2) & z == 1 ~ NA_character_, + dplyr::between(x, 2, width-1) & x %% 2 == 0 & y > 1 & z == 2 ~ NA_character_, + dplyr::between(y, 2, length-1) & y %% 2 == 0 & z == 2 ~ NA_character_, + x %in% c(1, width) | y %in% c(1, length) ~ house_col), + x = x+x_coord, + y = y+y_coord + ) + return(house_coords) +} + +#Build one house +brick_house() %>% bricks_from_coords() %>% + build_bricks(theta = 225) +rayshader::render_snapshot(clear = TRUE) +``` + +Next, we write one more function, `brick_street()` to build a road and grass foundation. The, for an arbitrary number of houses and neighborhood size, use `purrr::pmap_df` to generate many houses and place them along the road. + +```{r bricks_9, echo=TRUE, warning=FALSE, message=FALSE, fig.width=4, fig.height=4} +brick_street <- function(width = 100, length = 40){ + expand.grid(x=1:width, y=1:length, z=1) %>% + dplyr::mutate( + Color = dplyr::case_when( + y == round(length/2) & x %% 4 %in% 1:4 ~ "Bright yellow", + dplyr::between(y, length/2 -5, length/2 +5) ~ "Dark stone grey", + TRUE ~ "Dark green" + )) +} + +#Build a village, houses on 2 sides of a street +n_houses = 14 +sz = c(100, 40) + +list(x_coord = c(sample(seq(10, sz[1]-10, by = 10), n_houses/2), + sample(seq(10, sz[1]-10, by = 10), n_houses/2)), + y_coord = c(rep(sz[2]/2-15, n_houses/2), rep(sz[2]/2+10, n_houses/2)), + width = sample(4:10, n_houses, replace = TRUE), + length = sample(4:8, n_houses, replace = TRUE), + height = sample(5:8, n_houses, replace = TRUE) + ) %>% + purrr::pmap_df(brick_house) %>% + dplyr::bind_rows(brick_street(sz[1], sz[2])) %>% + bricks_from_coords() %>% + build_bricks() + +rayshader::render_camera(theta = 60, phi = 20, zoom = 0.75) +rayshader::render_snapshot(clear = TRUE) + +``` +