The hardware and bandwidth for this mirror is donated by dogado GmbH, the Webhosting and Full Service-Cloud Provider. Check out our Wordpress Tutorial.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]dogado.de.
{oblicubes}
is an extension for coolbutuseless’s {isocubes} that
supports 3D graphics in {grid}
and {ggplot2}
by rendering cubes/cuboids with an oblique
projection (instead of an isometric
projection). As a special case we also support “primary view
orthographic projections” as well. Like {isocubes}
the
{oblicubes}
package only supports rendering non-rotated
cubes (and cuboids) placed at integer coordinates. If you need to do
more complex oblique projections you’ll need to use a package like {piecepackr} which
supports additional shapes, supports adding art/text to their faces,
rotating shapes, placing shapes at non-integer coordinates, etc. Lots of other R packages provide high quality
3D render support for other projections.
{oblicubes} |
{isocubes} |
---|---|
oblique projection, “primary view orthographic projection” | isometric projection |
right-handed coordinate system with z vertical | left-handed coordinate system with y vertical |
Use xyz_heightmap() to create x,y,z coordinates |
Use coord_heightmap() to create x,y,z coordinates |
Use oblicubesGrob() , grid.oblicubes() , or
geom_oblicubes() to render image |
Use isocubesGrob() to render image |
Fast culling of non-visible cubes for “primary view orthographic projection”. Slower and less thorough culling of non-visible cubes for “oblique projection”. | Fast culling of non-visible cubes. |
Inspired by cj-holmes’s {isocuboids} package this package also supports drawing cuboids in addition to cubes. Using cuboids instead of cubes can provide significant speed advantages when rendering “height map” style images.
{oblicubes} |
{isocuboids} |
---|---|
oblique projection, “primary view orthographic projection” | isometric projection |
right-handed coordinate system with z vertical | left-handed coordinate system with y vertical |
Use xyz_heightmap(solid = FALSE) to create x,y,z
coordinates |
Coordinates generated within image rendering functions |
Use oblicuboidsGrob() , grid.oblicuboids() ,
or geom_oblicuboids() to render image |
Use cuboid_matrix() , cuboid_image() to
render image |
::install_github("trevorld/oblicubes") remotes
{oblicubes}
supports different oblique projection
angles:
library("grid")
library("oblicubes")
<- c(135, 90, 45, 180, 45, 0, -135, -90, -45)
angles <- c(0.5, 0.5, 0.5, 0.5, 0.0, 0.5, 0.5, 0.5, 0.5)
scales <- matrix(c(1, 2, 1, 2, 3, 2, 1, 2, 1), nrow = 3, ncol = 3)
mat <- xyz_heightmap(mat, col = c("red", "yellow", "green"))
coords <- rep(1:3/3 - 1/6, 3)
vp_x <- rep(3:1/3 - 1/6, each = 3)
vp_y for (i in 1:9) {
pushViewport(viewport(x=vp_x[i], y=vp_y[i], width=1/3, height=1/3))
grid.rect(gp = gpar(lty = "dashed"))
grid.oblicubes(coords, width = 0.15, xo = 0.25, yo = 0.15,
angle = angles[i], scale = scales[i],
gp = gpar(lwd=4))
if (i != 5)
grid.text(paste("angle =", angles[i]), y=0.92, gp = gpar(cex = 1.2))
else
grid.text(paste("scale = 0"), y=0.92, gp = gpar(cex = 1.2))
popViewport()
}
scale
of
0.5 and an angle
of 45. This is also known as a “cabinet
projection”.library("grDevices")
library("ggplot2")
library("oblicubes")
data("volcano", package = "datasets")
<- xyz_heightmap(volcano, scale = 0.3, min = 1, solid = FALSE)
df <- ggplot(df, aes(x, y, z = z, fill = raw)) +
g geom_oblicuboids(light = FALSE) +
coord_fixed() +
scale_fill_gradientn(name = "Height (m)",
colours=terrain.colors(256)) +
labs(x = "East (10m)", y = "North (10m)",
title = "Maungawhau (`datasets::volcano`)")
plot(g)
flipx
, flipy
,
ground
arguments in xyz_coords()
it is also
possible to generate views from different sides of the object.scale
of 0 gives you a “primary view orthographic
projection”.library("grDevices")
library("grid")
library("oblicubes")
data("volcano", package = "datasets")
<- 0.3 * (volcano - min(volcano)) + 1.0
mat
grid.rect(gp=gpar(col=NA, fill="grey5"))
<- convertWidth(unit(0.007, "snpc"), "cm")
width
# Top view
pushViewport(viewport(width = 0.7, height = 0.7, x = 0.65, y = 0.65))
<- xyz_heightmap(mat, col = terrain.colors, solid = FALSE)
coords grid.oblicubes(coords, scale = 0, width = width, gp = gpar(col=NA))
popViewport()
# South view
pushViewport(viewport(width = 0.7, height = 0.3, x = 0.65, y = 0.15))
<- xyz_heightmap(mat, col = terrain.colors, ground = "xz")
coords grid.oblicubes(coords, scale = 0, width = width, gp = gpar(col=NA))
popViewport()
# West view
pushViewport(viewport(width = 0.3, height = 0.7, x = 0.15, y = 0.65))
<- xyz_heightmap(mat, col = terrain.colors, ground = "zy")
coords grid.oblicubes(coords, scale = 0, width = width, gp = gpar(col=NA))
popViewport()
{isocubes}
you can use {oblicubes}
as an alternate renderer.library("isocubes") # remotes::install_github("coolbutuseless/isocubes")
library("oblicubes")
<- sdf_sphere() |> sdf_scale(40)
sphere <- sdf_box() |> sdf_scale(32)
box <- sdf_cyl() |> sdf_scale(16)
cyl <- sdf_subtract_smooth(
scene sdf_intersect(box, sphere),
sdf_union(
cyl,sdf_rotatey(cyl, pi/2),
sdf_rotatex(cyl, pi/2)
)
)<- sdf_render(scene, 50)
coords grid.oblicubes(coords, fill = "lightgreen")
library("ambient")
library("oblicubes")
<- 72
n set.seed(72)
<- noise_perlin(c(n, n), frequency = 0.042) |>
mat cut(8L, labels = FALSE) |>
matrix(nrow = n, ncol = n)
<- xyz_heightmap(mat, col = grDevices::topo.colors, solid = FALSE)
coords grid.oblicuboids(coords, gp = gpar(col = NA))
library("bittermelon") |> suppressPackageStartupMessages()
library("oblicubes")
<- system.file("fonts/spleen/spleen-8x16.hex.gz", package = "bittermelon")
font_file <- read_hex(font_file)
font <- as_bm_list("RSTATS", font = font)
bml # Add a shadow effect and border
<- (3 * bml) |>
bm bm_pad(sides = 2L) |>
bm_shadow(value = 2L) |>
bm_call(cbind) |>
bm_extend(sides = 1L, value = 1L)
<- apply(bm + 1L, c(1, 2), function(i) {
col switch(i, "white", "grey20", "lightblue", "darkblue")
})<- xyz_heightmap(bm, col = col, flipy = FALSE)
coords grid.oblicubes(coords)
{oblicubes}
library("grDevices")
library("grid")
library("magick") |> suppressPackageStartupMessages()
library("oblicubes")
# Ivory model of half a human head, half a skull, Europe, undated
# Science Museum, London / CC BY 4.0
# https://wellcomecollection.org/works/z3syda8c
<- "https://iiif.wellcomecollection.org/image/L0057080/full/760%2C/0/default.jpg"
url if (!file.exists("ivory-skull.jpg"))
::download.file(url, "ivory-skull.jpg")
utils<- image_read("ivory-skull.jpg") |>
img image_scale("20%") |>
image_crop("100x150+26+18")
<- as.matrix(as.raster(img))
col # height by luminosity
<- function(x) (0.2126 * x[1] + 0.7152 * x[2] + 0.0722 * x[3]) / 255
rgb2lum <- col2rgb(col) |>
mat apply(2, rgb2lum) |>
matrix(nrow = nrow(col), ncol = ncol(col))
<- xyz_heightmap(mat, col, scale = 20, min = 1, solid = FALSE)
df grid.newpage()
grid.rect(gp=gpar(fill="black"))
grid.raster(img, vp = viewport(x=0.25, width=0.5, just=c(0.5, 0.67)))
grid.text(paste("Ivory model of half a human head, half a skull",
"Europe, undated",
"Science Museum, London",
"Attribution 4.0 International (CC BY 4.0)",
sep = "\n"),
x=0.26, y = 0.75, gp = gpar(col = "white"))
grid.oblicuboids(df, scale=0.5, gp=gpar(col=NA),
vp = viewport(x=0.75, width=0.5))
grid.text("Pseudo 3D derivative (based on luminosity)",
x=0.76, y = 0.75, gp = gpar(col = "white"))
{oblicubes}
to make a 3D bar chart? With some work…yoffset
and zoffset
parameters
to shift cubes so the top/bottom of the cubes lie on integer values
(instead of the center of the cubes)library("dplyr") |> suppressPackageStartupMessages()
library("ggplot2")
library("oblicubes")
<- as.data.frame(datasets::Titanic) |>
df filter(Age == "Child", Freq > 0) |>
group_by(Sex, Survived, Class) |>
summarize(Freq = seq.int(sum(Freq)), .groups = "drop")
ggplot(df, aes(x = Survived, y = Freq, fill = Survived)) +
facet_grid(cols = vars(Class, Sex)) +
coord_fixed() +
geom_oblicubes(yoffset = -0.5, zoffset = -0.5, angle = -45, scale = 0.7) +
scale_fill_manual(values = c("Yes" = "lightblue", "No" = "red")) +
scale_y_continuous(expand = expansion(), name = "") +
scale_x_discrete(name = "", breaks = NULL) +
labs(title = "Children on the Titanic (by ticket class)")
{oblicubes}
it supports more
shapes, adding art/text to their faces, rotating shapes, placing shapes
at non-integer coordinates, etc. Specializes in the production of board
game graphics.{oblicubes}
.{oblicubes}
cuboid support.These packages usually default to a “perspective” projection but can usually be configured to also support various “orthographic” projections as well:
These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.
Health stats visible at Monitor.