suppressPackageStartupMessages({ library(ggplot2) library(magrittr) library(threed) }) knitr::opts_chunk$set( collapse = TRUE, comment = "#>" )
library(ggplot2) library(threed)
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # The `threed` package has some builtin objects in `threed::mesh3dobj` #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ obj <- threed::mesh3dobj$cube #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Define camera 'lookat' matrix i.e. camera-to-world transform #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ camera_to_world <- threed::look_at_matrix(eye = c(1.5, 1.75, 4), at = c(0, 0, 0)) #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Transform the object into camera space and do perspective projection #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ obj <- obj %>% transform_by(invert_matrix(camera_to_world)) %>% perspective_projection()
as.data.frame(obj) %>% knitr::kable()
threed
defines a fortify.mesh3d()
function.mesh3d
object is given as the data for aggplot2
call, ggplot2
will
automatically use fortify()
to convert into a data.frame.threed
defines fortify.mesh3d()
, we can call ggplot2
directly with a mesh3d
object.ggplot(obj, aes(x, y)) + geom_point() + theme_void() + theme(legend.position = 'none') + coord_equal()
element_id
, and this is used as the group
aesthetic
to inform ggplot that it should draw one polygon for each element.fill = NA, colour = 'black'
to draw only the borders of each polygon.ggplot(obj, aes(x, y, group = element_id)) + geom_polygon(fill = NA, colour = 'black', size = 0.2) + theme_void() + theme(legend.position = 'none') + coord_equal()
hidden
variable.hidden
is a boolean variable indicating if a triangle or quad element is facing
away from the camera.linetype
is used for hidden elements ggplot(obj, aes(x, y, group = element_id)) + geom_polygon(fill = NA, colour='black', aes(linetype = hidden, size = hidden)) + scale_linetype_manual(values = c('TRUE' = "dotted", 'FALSE' = 'solid')) + scale_size_manual(values = c('TRUE' = 0.2, 'FALSE' = 0.5)) + theme_void() + theme(legend.position = 'none') + coord_equal()
linetype
is used for hidden elements to hide them.ggplot(obj, aes(x, y, group = element_id)) + geom_polygon(fill = NA, colour = 'black', aes(size = hidden)) + scale_size_manual(values = c('TRUE' = 0, 'FALSE' = 0.5)) + theme_void() + theme(legend.position = 'none') + coord_equal()
ggplot2
will draw them in the order of the group
variable.ggplot(obj, aes(x, y, group = element_id)) + geom_polygon(fill = 'lightblue', colour = 'black', size = 0.2) + theme_void() + theme(legend.position = 'none') + coord_equal()
mesh3d
object to a data.frame, and then filtering
out the hidden elements.obj_df <- as.data.frame(obj) obj_df <- subset(obj_df, !obj_df$hidden) ggplot(obj_df, aes(x, y, group = element_id)) + geom_polygon(fill = 'lightblue', colour = 'black', size = 0.2) + theme_void() + theme(legend.position = 'none') + coord_equal()
NA
so they get drawn invisiblymesh3d
object to a data.frame, and
then manually setting the variables mapped to fill
and colour
to
be NA
for hidden elementsobj_df <- as.data.frame(obj) %>% transform( shade = ifelse(hidden, NA, 'lightblue'), linecolour = ifelse(hidden, NA, 'black') ) ggplot(obj_df, aes(x, y, group = element_id)) + geom_polygon(aes(fill = I(shade), colour = I(linecolour)), size = 0.2) + theme_void() + theme(legend.position = 'none') + coord_equal()
zorder
variable to control draw ordergroup
variable.mesh3d
to a data.frame, a zorder
variable is created starting at
1
for the furtherest element, up to n
for the closest element.group
variable from element_id
to zorder
ggplot(obj, aes(x, y, group = zorder)) + geom_polygon(fill = 'lightblue', colour='black', size = 0.2) + theme_void() + theme(legend.position = 'none') + coord_equal()
fnx, fny, fnz
fny + fnz
to shade the polygons.ggplot(obj, aes(x, y, group = zorder)) + geom_polygon(aes(fill = fny + fnz), colour = 'black', size = 0.2) + theme_void() + theme(legend.position = 'none') + coord_equal()
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.