More rayshader decoupling and news.

This commit is contained in:
ryantimpe
2020-03-10 17:11:06 -04:00
parent 4c934e4e36
commit be1084b423
7 changed files with 106 additions and 75 deletions

View File

@@ -13,7 +13,6 @@ addons:
packages:
- libgdal-dev
- libproj-dev
- r-cran-rayshader
#env
env:

View File

@@ -8,6 +8,8 @@
* New shapes! Plates, cheese slopes, round 1x1 bricks, conical 1x1 bricks.
* Removed bricks_from_rayshader() and build_bricks_rayshader() to decrease the complexity of package.
## ggplot Extension
* Removed from brickr. Will be rewritten as its own package.

View File

@@ -3,7 +3,7 @@
#' @param mosaic_list List output from collect_bricks() or image_to_bricks(). Contains an element \code{Img_lego}.
#' @param mosaic_height Number of layers in the 3D image.
#' @param highest_el Brick height is determined by brightness of color. Use \code{highest_el = 'dark'} for darkest bricks to have \code{mosaic_height}.
#' @return A list with elements \code{threed_elevation} and \code{threed_hillshade} to created 3D mosiacs with the \code{rayshader} package.
#' @return A list with elements \code{Img_lego} to pass to \code{collect_bricks()}.
#' @family 3D Models
#' @export
#'

View File

@@ -0,0 +1,100 @@
---
title: "3D Models from mosaics & rayshader"
output: rmarkdown::html_vignette
vignette: >
%\VignetteIndexEntry{models-from-other}
%\VignetteEngine{knitr::rmarkdown}
%\VignetteEncoding{UTF-8}
---
```{r, include = FALSE}
knitr::opts_chunk$set(
collapse = TRUE,
comment = "#>"
)
rgl::setupKnitr()
```
```{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.
## 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, rgl=TRUE, dev='png', echo=TRUE, warning=FALSE, message=FALSE, fig.width=4, fig.height=4}
demo_img = tempfile()
download.file("http://ryantimpe.com/files/mf_unicorn.PNG", demo_img, mode="wb")
mosaic <- png::readPNG(demo_img) %>%
image_to_mosaic()
mosaic %>% build_mosaic()
```
```{r bricks_6a, rgl=TRUE, dev='png', echo=TRUE, warning=FALSE, message=FALSE, fig.width=4, fig.height=4}
mosaic %>%
bricks_from_mosaic(highest_el = "dark") %>%
build_bricks()
#From dput(round(rgl::par3d("userMatrix"),1)) after manual rotation
custom_rotation <- structure(c(0.9, 0.3, -0.3, 0, -0.3, 0.9, -0.3,
0, 0.2, 0.4, 0.9, 0, 0, 0, 0, 1), .Dim = c(4L, 4L))
rgl::par3d(userMatrix = rgl::rotate3d(custom_rotation, 0, 0, pi/4 ,1))
```
## 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_rayshader(theta = 135, phi = 45)
rayshader::render_snapshot(clear = TRUE)
```
This example is rendered using `build_bricks_rayshader()`, which a bit faster for very large sets.

View File

@@ -1,5 +1,5 @@
---
title: "3D Models from mosaics & rayshader"
title: "3D Models from mosaics"
output: rmarkdown::html_vignette
vignette: >
%\VignetteIndexEntry{models-from-other}
@@ -51,50 +51,3 @@ custom_rotation <- structure(c(0.9, 0.3, -0.3, 0, -0.3, 0.9, -0.3,
rgl::par3d(userMatrix = rgl::rotate3d(custom_rotation, 0, 0, pi/4 ,1))
```
## 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_rayshader(theta = 135, phi = 45)
rayshader::render_snapshot(clear = TRUE)
```
This example is rendered using `build_bricks_rayshader()`, which a bit faster for very large sets.

View File

@@ -115,29 +115,6 @@ tree_or_mushroom %>%
rgl::par3d(userMatrix = rgl::rotate3d(rgl::par3d("userMatrix"), 1.1*pi/4, 0, 0 ,1))
```
### Plates instead of bricks
**Currently unavailable in `build_bricks()`. Use `build_bricks_rayshader()`**
That's clearly a tree, right? Why is the data frame called 'tree_or_mushroom'?
Use the input 'brick_type="plate"' to render the 3D model using LEGO plates rather than bricks, which are 1/3 as tall.
```{r bricks_5a, echo=TRUE, warning=FALSE, message=FALSE, fig.width=4, fig.height=4}
brick_colors <- tibble::tribble(
~`.value`, ~Color,
1, "Dark green",
2, "Light nougat",
3, "Bright red"
)
tree_or_mushroom %>%
bricks_from_table(brick_colors) %>%
build_bricks_rayshader(theta = 210, phi = 10, brick_res = "hd", brick_type="plate")
rayshader::render_snapshot(clear = TRUE)
```
## Bricks from Excel
When designing larger models, it is much easier to use a spreadsheet program to lay out the bricks for each level.

View File

@@ -139,13 +139,13 @@ The input `brightness` can be used to scale up or down the RGB values of the ima
## 3D Mosaics
With [rayshader](https://www.rayshader.com/) installed, passing the mosaic object to `bricks_from_mosaic()` will render a 3D object, stacking layers of bricks on each other to create an elevated mosaic. By default, the lightest color bricks will be on top, but this can be changed using the `highest_el = 'dark'` option.
Passing the mosaic object to `bricks_from_mosaic()` will render a 3D object, stacking layers of bricks on each other to create an elevated mosaic. By default, the lightest color bricks will be on top, but this can be changed using the `highest_el = 'dark'` option.
```{r c_threed, rgl=TRUE, dev='png'}
png::readPNG(demo_img) %>%
image_to_mosaic(32) %>%
bricks_from_mosaic(highest_el = "dark") %>%
build_bricks()
build_bricks(outline_bricks = TRUE, rgl_lit = FALSE)
#From dput(round(rgl::par3d("userMatrix"),1)) after manual rotation
custom_rotation <- structure(c(0.9, 0.3, -0.3, 0, -0.3, 0.9, -0.3,