forked from ryantimpe/brickr
-
Notifications
You must be signed in to change notification settings - Fork 0
/
README.Rmd
227 lines (162 loc) · 9.99 KB
/
README.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
---
title: "Emulate LEGO Bricks in 2D and 3D"
output:
github_document:
fig_width: 7.5
fig_height: 6
html_preview: false
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
rgl::setupKnitr()
library(brickr)
library(jpeg)
library(tidyverse)
```
# brickr <img src='man/figures/logo.png' align="right" height="138" />
<!-- <!-- badges: start -->
[![CRAN status](https://www.r-pkg.org/badges/version/brickr)](https://CRAN.R-project.org/package=brickr)
[![CRAN downloads](https://cranlogs.r-pkg.org/badges/brickr)](https://cran.r-project.org/package=brickr)
[![Lifecycle: experimental](https://img.shields.io/badge/lifecycle-experimental-orange.svg)](https://www.tidyverse.org/lifecycle/#experimental)
[![Travis build status](https://travis-ci.org/ryantimpe/brickr.svg?branch=master)](https://travis-ci.org/ryantimpe/brickr)
<!-- <!-- badges: end -->
## Overview
**brickr** is a package for bringing the LEGO® experience into the R and [tidyverse](https://www.tidyverse.org/) ecosystem.
The package is divided into 2 systems:
- [**Mosaics**](#mosaics): Convert image files into mosaics that could be built using LEGO bricks.
- [**3D Models**](#3d-models): Build 3D LEGO models from data tables using [rgl](https://CRAN.R-project.org/package=rgl).
brickr also includes tools help users create the Mosaics and 3D model output using real LEGO elements.
Check out [brickr.org](http://brickr.org) for more detail!
### What's the point?
The goal of **brickr** is to provide a series of tools to integrate the LEGO system with R by:
- Enhancing a real world building experience with mosaics, generated instructions, and piece counts.
- Generating interest in R and coding for new audiences with easy-to-create 3D models.
- Embracing pure novelty.
*brickr is developed under the [Fair Play](https://www.lego.com/en-us/legal/notices-and-policies/fair-play/) policy using publicly available information about LEGO products. brickr is not affiliated with The LEGO Group.*
## Installation
``` r
# Install from CRAN
install.packages("brickr")
# To install the latest development version from Github:
# install.packages("remotes")
remotes::install_github("ryantimpe/brickr")
```
## Mosaics
The mosaic functions renders an imported JPG or PNG file using LEGO colors and bricks.
```{r m1_set, fig.width = 3, fig.height=3, echo = TRUE, message = FALSE, warning = FALSE}
demo_img = tempfile()
download.file("http://ryantimpe.com/files/mf_unicorn.PNG", demo_img, mode="wb")
mosaic1 <- png::readPNG(demo_img) %>%
image_to_mosaic(img_size = 36) #Length of each side of mosaic in "bricks"
#Plot 2D mosaic
mosaic1 %>% build_mosaic()
```
In general, any **brickr** function that begins with `build_` generates a graphical output from a **brickr** list object, generated from other functions.
### Customization
`image_to_mosaic()` can take a few important arguments. See `?image_to_mosaic()` for full detail.
- `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` & `color_palette` Options to limit the color of bricks used in mosaics, as not all colors produced by LEGO are readily available. Set `color_palette` to 'universal' or `c('universal', 'generic')` to limit colors to the most common ones. Use a subset of the data frame `lego_colors` as the `color_table` to specify a custom palette.
- `method` Technique used to map image colors into the allowed brick colors. Defaults to 'cie94`, but other options include 'cie2000' and 'euclidean'. Also includes the option 'brickr_classic', used in previous version of the package.
## 3D Models
The `bricks_from_*` series of functions creates 3D models of LEGO bricks from a variety of input formats.
- `bricks_from_table()` & `bricks_from_excel()` convert 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. `bricks_from_excel()` is a wrapper function to more easily build models designed using a Microsoft Excel template. Please see this repo: [brickr toybox](https://github.com/ryantimpe/brickr_toybox).
- `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 `build_colors()`. This format is much more flexible than `bricks_from_table()` and allows the programmatic development of 3D models. For other options, see the "Piece type in 3D Models" vignette.
- `bricks_from_mosaic()` converts a 2D [mosaic](#mosaics) object from an image into 3D LEGO models, respectively.
Pass the output from any `bricks_from_*()` function to `build_bricks()` to see the 3D model.
Models are rendered in **rgl**.
```{r bricks_1, rgl=TRUE, dev='png', echo=TRUE, warning=FALSE, message=FALSE, fig.width=3, fig.height=3}
library(brickr)
#This is a brick
brick <- data.frame(
Level="A",
X1 = rep(3,4), #The number 3 is the brickrID for 'bright red'
X2 = rep(3,4)
)
brick %>%
bricks_from_table() %>%
build_bricks()
#Rotate the default view for a better snapshot
rgl::par3d(userMatrix = rgl::rotate3d(rgl::par3d("userMatrix"), 0.75*pi, 0, 0 ,1))
```
### Stacking bricks
The Level column in the input table determines the elevation of the bricks. `bricks_from_table()` will convert alphanumeric levels into a z coordinate.
For larger models, use `tibble::tribble()` to more easily visualize the model. For very large models, use a csv or Excel.
```{r bricks_5, rgl=TRUE, dev='png', 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,
"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) %>%
build_bricks()
#Rotate the default view for a better snapshot
rgl::par3d(userMatrix = rgl::rotate3d(rgl::par3d("userMatrix"), 1.1*pi, 0, 0 ,1))
```
### 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, rgl=TRUE, dev='png', 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)*2.5)) #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() %>%
build_bricks(outline_bricks = TRUE, rgl_lit = FALSE)
rgl::par3d(userMatrix = rgl::rotate3d(rgl::par3d("userMatrix"), 1.1*pi/4, 0, 0 ,1))
```
The option `outline_bricks = TRUE` adds a black outline around the edges of the bricks. Setting `rgl_lit = FALSE` turns off automated lighting effects from rgl. Changing these two inputs together renders bricks in a more cartoon fashion.
### Examples
More examples using `bricks_from_table()` and `bricks_from_coords()` can be found at the links below.
- [**Baby Yoda**](https://gist.github.com/ryantimpe/3893fdd0f94138d027bae35bf38b57c7) example using `bricks_from_excel()` with an animation.
- [**brickr 0.3 release video**](https://gist.github.com/ryantimpe/b685caaa7f6c001a9a227f48bf9a5852) with a static model and `bricks_from_excel()`.
- [**brickr toybox**](https://github.com/ryantimpe/brickr_toybox) repo for tools and resources to get started.
## IRL
Additional functions assist in the translation of brickr objects into actual LEGO bricks.
### Instructions
Use `build_instructions()` to break the mosaics and 3D models into easier-to-read steps for building the set. This defaults to 6 steps, but passing any integer value will generate that many steps.
```{r m1_instructions, fig.width = 8, fig.height=7, message = FALSE, warning = FALSE}
mosaic1 %>% build_instructions(9)
```
### Piece list and count
Use `build_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](https://shop.lego.com/en-US/Pick-a-Brick) section using the advanced search option. Alternatively, use `table_pieces()` to produce a data frame table of all required bricks.
```{r m1_pieces, fig.width = 8, fig.height=7, message = FALSE, warning = FALSE}
mosaic1 %>% build_pieces()
```
## Acknowledgments
3D models in brickr would not exist without [Tyler Morgan-Wall](https://twitter.com/tylermorganwall) and his [rayshader](https://www.rayshader.com/) package. If you're interested in creating 3D models of literally *anything* in R, check out his [rayrender](https://www.rayrender.net/) package.
All functions in brickr are created with the [tidyverse](https://www.tidyverse.org/) and [rgl](https://CRAN.R-project.org/package=rgl).