Next release for bricks_from_coords() and updated README.

This commit is contained in:
Ryan Timpe
2019-03-22 09:31:17 -04:00
parent a4f758e9d4
commit bb08271bd9
14 changed files with 122 additions and 35 deletions

7
.gitignore vendored
View File

@@ -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

View File

@@ -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
View File

@@ -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

View File

@@ -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),

View File

@@ -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 %>%

View File

@@ -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/).

View File

@@ -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()
![](README_files/figure-gfm/bricks_5-1.png)<!-- -->
### 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()
```
![](README_files/figure-gfm/bricks_6-1.png)<!-- -->
## Mosaics
The mosaic functions renders an imported JPG or PNG file using LEGO

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 107 KiB

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

View File

@@ -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
}