Skip to contents

Creates 3D surfaces from regularly gridded data (like elevation maps). Assumes data is on a regular x,y grid and creates quadrilateral faces.

Usage

stat_surface_3d(
  mapping = NULL,
  data = NULL,
  geom = GeomPolygon3D,
  position = "identity",
  light = lighting(),
  na.rm = FALSE,
  show.legend = NA,
  inherit.aes = TRUE,
  ...
)

Arguments

mapping

Set of aesthetic mappings created by aes().

data

The data to be displayed in this layer.

geom

The geometric object to use display the data. Defaults to GeomPolygon3D for proper 3D depth sorting.

position

Position adjustment, defaults to "identity".

light

A lighting specification object created by lighting()

na.rm

If FALSE, missing values are removed with a warning.

show.legend

Logical indicating whether this layer should be included in legends.

inherit.aes

If FALSE, overrides the default aesthetics.

...

Other arguments passed on to layer().

Aesthetics

stat_surface_3d() requires the following aesthetics:

  • x: X coordinate

  • y: Y coordinate

  • z: Z coordinate (elevation/height)

Computed variables

  • light: Computed lighting value (numeric for most methods, hex color for normal_rgb)

  • normal_x, normal_y, normal_z: Surface normal components

  • slope: Gradient magnitude from original surface calculations

  • aspect: Direction of steepest slope from original surface calculations

  • dzdx, dzdy: Partial derivatives from original surface calculations

Examples

# Generate and visualize a basic surface
d <- dplyr::mutate(tidyr::expand_grid(x = -20:20, y = -20:20),
      z = sqrt(x^2 + y^2) / 1.5,
      z = cos(z) - z)

p <- ggplot(d, aes(x, y, z)) + coord_3d()

# basic surface
p + stat_surface_3d(fill = "dodgerblue", color = "darkblue", linewidth = .2)


# with 3d lighting
p + stat_surface_3d(fill = "darkgreen", color = "darkgreen", linewidth = .2,
      light = lighting(blend = "both"))


# mesh wireframe, without fill, with aes line color
p + stat_surface_3d(aes(color = z), fill = NA) +
  scale_color_viridis_c()


# use `group` to plot data for multiple surfaces
# (depth rendering works fine unless the surfaces intersect)
d <- expand.grid(x = -5:5, y = -5:5)
d$z <- d$x^2 - d$y^2
d$g <- "a"
d2 <- d
d2$z <- d$z + 10
d2$g <- "b"
ggplot(rbind(d, d2),
       aes(x, y, z, group = g, fill = g)) +
  coord_3d() +
  stat_surface_3d(color = "black", alpha = .5)


ggplot(mountain, aes(x, y, z, fill = z, color = z)) +
  stat_surface_3d(light = lighting(method = "diffuse", direction = c(1, 0, .5),
                           blend = "both", blend_mode = "hsv", blend_strength = .9),
               linewidth = .2) +
  coord_3d(ratio = c(1, 1.5, .5)) +
  theme_light() +
  scale_fill_gradientn(colors = c("darkgreen", "rosybrown4", "gray60")) +
  scale_color_gradientn(colors = c("darkgreen", "rosybrown4", "gray60"))