Next release for bricks_from_coords() and updated README.
7
.gitignore
vendored
@@ -55,3 +55,10 @@ brickrweb2.mp4
|
||||
2_Example_Sphere.R
|
||||
2_Example_StPatricksDay.R
|
||||
98_dput_tribble.R
|
||||
2_Example_Plot_Titanic.R
|
||||
2_Example_RandomForest.R
|
||||
2_Example_Ryan.R
|
||||
ryanmovie.mp4
|
||||
ryanweb.mp4
|
||||
forestmovie.mp4
|
||||
forestweb.mp4
|
||||
|
||||
@@ -5,15 +5,11 @@
|
||||
#Packages Required: dplyr, tidyr, purrrr, ggplot2, readr
|
||||
|
||||
#RUN THIS CODE AFTER DOWNLOADING SOURCE FILES
|
||||
library(jpeg)
|
||||
source("0_Functions.R")
|
||||
library(brickr)
|
||||
|
||||
#This will take a few minutes to run
|
||||
lego_mosaic <- readJPEG("Images/Ryan.jpg") %>%
|
||||
# scale_image(48) %>% #Single value for square,
|
||||
scale_image(c(48, 56), brightness = 1.1) %>% # WIDE - c(W, H) for rectangle
|
||||
legoize() %>%
|
||||
collect_bricks()
|
||||
#This will take a few seconds to run
|
||||
lego_mosaic <- jpeg::readJPEG("Images/goldengirls.jpg") %>%
|
||||
image_to_bricks(48)
|
||||
|
||||
lego_mosaic %>% display_set()
|
||||
|
||||
@@ -24,10 +20,12 @@ lego_mosaic %>%
|
||||
#Get summary of pieces
|
||||
pieces <- lego_mosaic %>% table_pieces()
|
||||
|
||||
sum(lego_mosaic$pieces$n)
|
||||
|
||||
lego_mosaic %>% display_pieces()
|
||||
|
||||
#Save it
|
||||
ggsave("LegoMosaic.png", device = "png", height = 5, width = 5)
|
||||
ggplot2::ggsave("GG_fewer_pieces.png", device = "png", height = 8, width = 8)
|
||||
|
||||
#3D with rayshader ----
|
||||
library(rayshader)
|
||||
@@ -35,8 +33,8 @@ library(rayshader)
|
||||
#mosaic_height is the elevation of the mosaic in LEGO plates... 3 plates = 1 LEGO brick
|
||||
#Set highest_el = "dark" for dark bricks to be tallest... otherwise light bricks are tallest
|
||||
lego_mosaic %>%
|
||||
collect_3d(mosaic_height = 9, highest_el="dark") %>%
|
||||
display_3d(fov=0,theta=-30,phi=30,windowsize=c(1000,800),zoom=0.75)
|
||||
collect_3d(mosaic_height = 6) %>%
|
||||
display_3d(fov=0,theta=0,phi=90,windowsize=c(1000,800),zoom=0.75,shadow=FALSE)
|
||||
|
||||
|
||||
#display_3d() takes all inputs of rayshader::plot_3d() EXCEPT hillshade, heightmap, & zscale
|
||||
|
||||
6
Images/.gitignore
vendored
@@ -10,3 +10,9 @@ torosaurus.JPG
|
||||
UP.PNG
|
||||
brickr.JPG
|
||||
brickr_logo.xlsx
|
||||
GGDepth.tif
|
||||
RyanColor.png
|
||||
RyanColor2.tif
|
||||
RyanDepth.png
|
||||
RyanDepth1.tif
|
||||
goldengirlsDEPTH.JPG
|
||||
|
||||
@@ -102,10 +102,9 @@ bricks_from_table <- function(matrix_table, color_guide = lego_colors, .re_level
|
||||
}
|
||||
|
||||
|
||||
#' Convert a data frame with x, y, & z coordinates into bricks for 3D Model
|
||||
#' Convert a data frame with x, y, & z coordinates & Color into bricks for 3D Model
|
||||
#'
|
||||
#' @param coord_table A data frame of a 3D brick model desigh. Left-most column is level/height/z dimension, with rows as Y axis and columns as X axis. See example. Use \code{tribble} for ease.
|
||||
#' @param color_guide A data frame linking numeric \code{.value} in \code{matrix_table} to official LEGO color names. Defaults to data frame 'lego_colors'.
|
||||
#' @param coord_table A data frame of a 3D brick model design. Contains x, y, and z (vertical height) dimensions, as well as Color from official LEGO color names. See \code{display_colors()}.
|
||||
#' @param increment_level Default '0'. Use in animations. Shift Level/z dimension by an integer.
|
||||
#' @param max_level Default 'Inf'. Use in animations. Any Level/z values above this value will be cut off.
|
||||
#' @param increment_x Default '0'. Use in animations. Shift x dimension by an integer.
|
||||
@@ -131,9 +130,16 @@ bricks_from_coords <- function(coord_table, color_guide = lego_colors,
|
||||
names(bricks_raw)[tolower(names(bricks_raw)) == "color"] <- "Color"
|
||||
|
||||
if(!all(c("x", "y", "z", "Color") %in% names(bricks_raw))){
|
||||
stop("Input 'coord_table' must include the columns x, y, z, and Color. Color uses offical brick color names. See display_colors().")
|
||||
stop("Input 'coord_table' must include the columns x, y, z, and Color. z should be >1. Color uses offical brick color names. See display_colors().")
|
||||
}
|
||||
|
||||
#x, y, z, must be whole numbers and unique
|
||||
bricks_raw <- bricks_raw %>%
|
||||
dplyr::mutate_at(dplyr::vars("x", "y", "z"), round) %>%
|
||||
dplyr::group_by(x, y, z) %>%
|
||||
dplyr::filter(dplyr::row_number() == 1) %>%
|
||||
dplyr::ungroup()
|
||||
|
||||
#Need to assume users might supply NA-supressed or non-cube data. But layer_from_brick() needs cubes.
|
||||
bricks_full <- expand.grid(
|
||||
x = min(bricks_raw$x):max(bricks_raw$x),
|
||||
|
||||
@@ -53,8 +53,8 @@ layer_from_bricks <- function(brick_list, lev=1){
|
||||
stud = ((x-x_mid)^2 + (y-y_mid)^2)^(1/2) < ex_size/3) %>%
|
||||
dplyr::ungroup() %>%
|
||||
dplyr::mutate(elevation = ifelse(stud, elevation+0.5, elevation)) %>%
|
||||
dplyr::mutate_at(dplyr::vars(R_lego, G_lego, B_lego), dplyr::funs(ifelse(stud, .-0.1, .))) %>%
|
||||
dplyr::mutate_at(dplyr::vars(R_lego, G_lego, B_lego), dplyr::funs(ifelse(. < 0, 0, .)))
|
||||
dplyr::mutate_at(dplyr::vars(R_lego, G_lego, B_lego), list(~ifelse(stud, .-0.1, .))) %>%
|
||||
dplyr::mutate_at(dplyr::vars(R_lego, G_lego, B_lego), list(~ifelse(. < 0, 0, .)))
|
||||
|
||||
#Elevation Matrix
|
||||
lego_elmat <- lego_expand2 %>%
|
||||
@@ -73,7 +73,7 @@ layer_from_bricks <- function(brick_list, lev=1){
|
||||
dplyr::group_by(brick_id) %>%
|
||||
#This darkens the edge of each brick, to look like they are separated
|
||||
dplyr::mutate_at(dplyr::vars(R_lego, G_lego, B_lego),
|
||||
dplyr::funs(ifelse((x == min(x) | y == min(y) | x == max(x) | y == max(y)), .*0.9, .))) %>%
|
||||
list(~ifelse((x == min(x) | y == min(y) | x == max(x) | y == max(y)), .*0.9, .))) %>%
|
||||
dplyr::ungroup()
|
||||
|
||||
lego_hillshade_m[,,1] <- lego_expand_color %>%
|
||||
|
||||
48
README.Rmd
@@ -40,15 +40,17 @@ install.packages("rayshader")
|
||||
```
|
||||
## 3D Models
|
||||
|
||||
Building 3D models requires a properly formatted data frames and two functions.
|
||||
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.
|
||||
|
||||
- `display_bricks()` uses **rayshader** to display the 3D output from `bricks_from_table()`.
|
||||
- `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.
|
||||
|
||||
```{r bricks_1, echo=TRUE, warning=FALSE, message=FALSE}
|
||||
Pass the output from any `bricks_from_*()` function to `display_bricks()` to see the 3D model.
|
||||
|
||||
```{r bricks_1, echo=TRUE, warning=FALSE, message=FALSE, fig.width=3, fig.height=3}
|
||||
library(brickr)
|
||||
|
||||
#This is a brick
|
||||
@@ -77,7 +79,7 @@ There are 2 ways to assign the color of the bricks. The `display_colors()` funct
|
||||
|
||||
- Create a table of color assignments and pass this to `bricks_from_table()`
|
||||
|
||||
```{r bricks_2, echo=TRUE, warning=FALSE, message=FALSE}
|
||||
```{r bricks_2, echo=TRUE, warning=FALSE, message=FALSE, fig.width=3, fig.height=3}
|
||||
brick_colors <- data.frame(
|
||||
.value = 1,
|
||||
Color = "Bright blue"
|
||||
@@ -97,7 +99,7 @@ rayshader::render_snapshot()
|
||||
|
||||
The Level column in the input table determines the height of the bricks. `bricks_from_table()` will convert alphanumeric levels into a z coordinate.
|
||||
|
||||
```{r bricks_3, echo=TRUE, warning=FALSE, message=FALSE}
|
||||
```{r bricks_3, echo=TRUE, warning=FALSE, message=FALSE, fig.width=3, fig.height=4}
|
||||
# A is the bottom Level, B is the top
|
||||
brick <- data.frame(
|
||||
Level= c(rep("A",4), rep("B",4)),
|
||||
@@ -117,7 +119,7 @@ rayshader::render_snapshot()
|
||||
|
||||
The same process works with many levels
|
||||
|
||||
```{r bricks_4, echo=TRUE, warning=FALSE, message=FALSE}
|
||||
```{r bricks_4, echo=TRUE, warning=FALSE, message=FALSE, fig.width=6, fig.height=3}
|
||||
#You can stack many bricks ----
|
||||
brick <- data.frame(
|
||||
Level="A",
|
||||
@@ -141,7 +143,7 @@ rayshader::render_snapshot()
|
||||
|
||||
For larger models, use `tibble::tribble()` to more easily visualize the model. For very large models, use MS Excel.
|
||||
|
||||
```{r bricks_5, echo=TRUE, warning=FALSE, message=FALSE}
|
||||
```{r bricks_5, echo=TRUE, warning=FALSE, message=FALSE, fig.width=4, fig.height=4}
|
||||
my_first_model <- tibble::tribble(
|
||||
~Level, ~X1, ~X2, ~X3, ~x4, ~x5, ~X6, ~x7, ~x8,
|
||||
"A", 1, 1, 1, 0, 1, 1, 1, 1,
|
||||
@@ -181,6 +183,38 @@ rayshader::render_snapshot()
|
||||
```{r, echo=FALSE}
|
||||
rgl::rgl.clear()
|
||||
```
|
||||
|
||||
### 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.
|
||||
|
||||
```{r bricks_6, echo=TRUE, warning=FALSE, message=FALSE, fig.width=5, fig.height=5}
|
||||
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()
|
||||
```
|
||||
```{r, echo=FALSE}
|
||||
rgl::rgl.clear()
|
||||
```
|
||||
|
||||
## 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](http://www.ryantimpe.com/post/lego-mosaic1/), this [follow-up post](http://www.ryantimpe.com/post/lego-mosaic2/),and this [third post](http://www.ryantimpe.com/post/lego-mosaic3/).
|
||||
|
||||
48
README.md
@@ -34,8 +34,8 @@ install.packages("rayshader")
|
||||
|
||||
## 3D Models
|
||||
|
||||
Building 3D models requires a properly formatted data frames and two
|
||||
functions.
|
||||
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.**
|
||||
@@ -50,10 +50,15 @@ documentation will be released soon.**
|
||||
y-coordinate. More flexible inputs will be available in a future
|
||||
release.
|
||||
|
||||
- `display_bricks()` uses **rayshader** to display the 3D output from
|
||||
`bricks_from_table()`.
|
||||
- `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.
|
||||
|
||||
<!-- end list -->
|
||||
Pass the output from any `bricks_from_*()` function to
|
||||
`display_bricks()` to see the 3D model.
|
||||
|
||||
``` r
|
||||
library(brickr)
|
||||
@@ -201,6 +206,39 @@ rayshader::render_snapshot()
|
||||
|
||||
<!-- -->
|
||||
|
||||
### 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.
|
||||
|
||||
``` r
|
||||
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()
|
||||
```
|
||||
|
||||
<!-- -->
|
||||
|
||||
## Mosaics
|
||||
|
||||
The mosaic functions renders an imported JPG or PNG file using LEGO
|
||||
|
||||
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 107 KiB After Width: | Height: | Size: 56 KiB |
BIN
README_files/figure-gfm/bricks_6-1.png
Normal file
|
After Width: | Height: | Size: 57 KiB |
@@ -2,7 +2,7 @@
|
||||
% Please edit documentation in R/bricks_from.R
|
||||
\name{bricks_from_coords}
|
||||
\alias{bricks_from_coords}
|
||||
\title{Convert a data frame with x, y, & z coordinates into bricks for 3D Model}
|
||||
\title{Convert a data frame with x, y, & z coordinates & Color into bricks for 3D Model}
|
||||
\usage{
|
||||
bricks_from_coords(coord_table, color_guide = lego_colors,
|
||||
increment_level = 0, max_level = Inf, increment_x = 0,
|
||||
@@ -10,9 +10,7 @@ bricks_from_coords(coord_table, color_guide = lego_colors,
|
||||
exclude_level = NULL)
|
||||
}
|
||||
\arguments{
|
||||
\item{coord_table}{A data frame of a 3D brick model desigh. Left-most column is level/height/z dimension, with rows as Y axis and columns as X axis. See example. Use \code{tribble} for ease.}
|
||||
|
||||
\item{color_guide}{A data frame linking numeric \code{.value} in \code{matrix_table} to official LEGO color names. Defaults to data frame 'lego_colors'.}
|
||||
\item{coord_table}{A data frame of a 3D brick model design. Contains x, y, and z (vertical height) dimensions, as well as Color from official LEGO color names. See \code{display_colors()}.}
|
||||
|
||||
\item{increment_level}{Default '0'. Use in animations. Shift Level/z dimension by an integer.}
|
||||
|
||||
@@ -34,5 +32,5 @@ bricks_from_coords(coord_table, color_guide = lego_colors,
|
||||
A list with elements \code{Img_lego} to pass to \code{collect_bricks()}.
|
||||
}
|
||||
\description{
|
||||
Convert a data frame with x, y, & z coordinates into bricks for 3D Model
|
||||
Convert a data frame with x, y, & z coordinates & Color into bricks for 3D Model
|
||||
}
|
||||
|
||||