Skip to contents

Creates 3D surfaces by evaluating a function f(x,y) = z over a regular grid. The function is evaluated at each grid point and the resulting surface is rendered with proper 3D depth sorting and optional lighting effects.

Usage

stat_function_3d(
  mapping = NULL,
  fun = NULL,
  data = NULL,
  geom = GeomPolygon3D,
  position = "identity",
  xlim = NULL,
  ylim = NULL,
  n = 50,
  light = lighting(),
  na.rm = FALSE,
  show.legend = NA,
  inherit.aes = TRUE,
  color = NULL,
  colour = NULL,
  ...
)

Arguments

mapping

Set of aesthetic mappings created by aes(). Since this stat generates its own data, typically only used for additional aesthetics like fill or color based on computed variables.

fun

Function to evaluate. Must accept two arguments (vectors corresponding to x and y axis values) and return a numeric vector of z values. Required parameter.

data

The data to be displayed in this layer. Usually not needed since the stat generates its own data from the function.

geom

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

position

Position adjustment, defaults to "identity". To collapse the result onto one 2D surface, use position_on_face().

xlim, ylim

Numeric vectors of length 2 giving the range for x and y values. If NULL (default), uses the scale ranges from the plot, which can be set via xlim() and ylim(), or trained by supplying data to the plot.

n

Either a single integer specifying grid resolution in both dimensions, or a vector of length 2 specifying c(nx, ny) for different resolutions. Default is 50. Higher values create smoother surfaces but slower rendering.

light

A lighting specification object created by lighting()

na.rm

If TRUE, removes missing values from function evaluation results. If FALSE, missing values will cause an error. Default is FALSE.

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_function_3d() generates its own x, y, z coordinates, so typically no positional aesthetics are needed in the mapping. However, you can use computed variables with after_stat():

Computed variables

  • x, y, z: Grid coordinates and function values

  • 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 surface calculations

  • aspect: Direction of steepest slope from surface calculations

  • dzdx, dzdy: Partial derivatives from surface calculations

See also

stat_surface_3d() for surfaces from existing grid data, lighting() for lighting specifications, coord_3d() for 3D coordinate systems.

Examples

library(ggplot2)

# Basic function surface
ggplot() +
  stat_function_3d(fun = function(x, y) x^2 + y^2,
                   xlim = c(-2, 2), ylim = c(-2, 2)) +
  coord_3d()


# Wave function with lighting
wave_fun <- function(x, y) cos(x) + cos(y) + cos(x+y) + cos(sqrt(x^2 + y^2))
ggplot() +
  stat_function_3d(fun = wave_fun, fill = "steelblue",
                   xlim = c(-3*pi, 3*pi), ylim = c(-3*pi, 3*pi),
                   light = lighting(blend = "fill", blend_mode = "hsl")) +
  coord_3d(scales = "fixed") + theme_dark()


# Higher resolution surface with color mapping
ggplot() +
  stat_function_3d(aes(fill = after_stat(light)),
                   fun = function(x, y) sin(x) * cos(y),
                   xlim = c(-pi, pi), ylim = c(-pi, pi),
                   n = 80) +
  scale_fill_viridis_c(option = "B") +
  coord_3d()


# Complex mathematical surface
saddle <- function(x, y) x^2 - y^2
ggplot() +
  stat_function_3d(aes(fill = after_stat(x)),
                   fun = saddle,
                   xlim = c(-3, 3), ylim = c(-3, 3),
                   n = c(60, 40)) +  # Different resolution in x and y
  scale_fill_viridis_c() +
  coord_3d(scales = "fixed")


# Function with lighting effects
gaussian <- function(a, b) exp(-(a^2 + b^2))
ggplot() +
  stat_function_3d(fun = gaussian, color = "white",
                   light = lighting(method = "direct",
                                  direction = c(1, 1, 0.25),
                                  blend = "both")) +
  scale_fill_viridis_c() + scale_color_viridis_c() +
  coord_3d(scales = "fixed", ratio = c(1, 2, 3), expand = FALSE) +
  xlim(-3, 3) + ylim(-2, 2) + theme_light()