# Statistical and annotation WebGL layers

This vignette covers statistical summaries, curve/contour layers, filled regions, raster grids, annotations, and fixed-scale facets. Evaluation is disabled during CRAN, package checks, and CI unless explicitly enabled with `GGWEBGL_EVAL_COVERAGE_VIGNETTE=true` or `NOT_CRAN=true`. Live WebGL widgets are additionally disabled unless `GGWEBGL_EVAL_LIVE_WIDGETS=true` is set; rich local or pkgdown builds should set both `GGWEBGL_EVAL_COVERAGE_VIGNETTE=true` and `GGWEBGL_EVAL_LIVE_WIDGETS=true`.

> Example chunks are shown but not evaluated in this build. Set `GGWEBGL_EVAL_COVERAGE_VIGNETTE=true` or `NOT_CRAN=true` to evaluate them during a local non-CI render.

# Curves and Contours

Frequency polygons, density curves, two-dimensional density contours, and regular contour lines all serialize to line/path primitives. The statistical work remains with `ggplot2`.

## Applet: Frequency polygons

    p <- ggplot(mtcars, aes(mpg, colour = factor(cyl))) +
      geom_freqpoly_webgl(binwidth = 4, linewidth = 1.1) +
      labs(title = "Frequency polygons")
    ggplot_webgl(p, height = 420)

## Applet: Density curves

    p <- ggplot(mtcars, aes(mpg, colour = factor(cyl))) +
      geom_density_webgl(linewidth = 1.1) +
      labs(title = "Density curves")
    ggplot_webgl(p, height = 420)

## Code-only: Two-dimensional density contours

`geom_density2d_webgl()` uses `ggplot2`’s two-dimensional density statistic, which requires `MASS` at render time. The chunk is skipped when that optional runtime dependency is unavailable.

    p <- ggplot(mtcars, aes(wt, mpg)) +
      geom_density2d_webgl(linewidth = 0.8) +
      labs(title = "Two-dimensional density contours")
    ggplot_webgl(p, height = 420)

## Code-only: Gridded contour lines

    volcano_df <- as.data.frame(as.table(volcano))
    names(volcano_df) <- c("x", "y", "z")
    volcano_df$x <- as.numeric(volcano_df$x)
    volcano_df$y <- as.numeric(volcano_df$y)

    p <- ggplot(volcano_df, aes(x, y, z = z)) +
      geom_contour_webgl(bins = 8) +
      labs(title = "Gridded contour lines")

    ggplot_webgl(p, height = 420)

# Ranges and Summaries

Range and summary geoms combine segment, point, and rectangle primitives.

## Applet: Linerange and pointrange

    summary_df <- data.frame(
      group = factor(c("a", "b", "c")),
      y = c(4.1, 5.3, 6.0),
      ymin = c(3.6, 4.7, 5.4),
      ymax = c(4.8, 6.1, 6.8)
    )

    p <- ggplot(summary_df, aes(group, y, ymin = ymin, ymax = ymax)) +
      geom_linerange_webgl(linewidth = 1.2) +
      geom_pointrange_webgl(colour = "#2563eb") +
      labs(title = "Linerange and pointrange")
    ggplot_webgl(p, height = 420)

## Applet: Error bars and crossbars

    p <- ggplot(summary_df, aes(group, y, ymin = ymin, ymax = ymax)) +
      geom_errorbar_webgl(width = 0.25) +
      geom_crossbar_webgl(aes(fill = group), width = 0.45, alpha = 0.55) +
      labs(title = "Error bars and crossbars")
    ggplot_webgl(p, height = 420)

## Applet: Boxplot summary

    p <- ggplot(mtcars, aes(factor(cyl), mpg, fill = factor(cyl))) +
      geom_boxplot_webgl() +
      labs(title = "Boxplot summary")
    ggplot_webgl(p, height = 420)

## Applet: Violin density summary

Violin rendering uses `ggplot2`’s built density output.

    p <- ggplot(mtcars, aes(factor(cyl), mpg, fill = factor(cyl))) +
      geom_violin_webgl(alpha = 0.7) +
      labs(title = "Violin density summary")
    ggplot_webgl(p, height = 420)

# Filled Regions

Ribbon, area, and simple polygon layers are filled-region APIs. They are useful for compact displays, but complex polygon topology such as holes or self-intersections should be treated as outside the current core contract.

## Applet: Ribbon band

    band <- data.frame(
      x = seq(0, 2 * pi, length.out = 80)
    )
    band$y <- sin(band$x)
    band$ymin <- band$y - 0.15
    band$ymax <- band$y + 0.15

    p <- ggplot(band, aes(x, ymin = ymin, ymax = ymax)) +
      geom_ribbon_webgl(fill = "#93c5fd", alpha = 0.6) +
      geom_line_webgl(aes(y = y), colour = "#1d4ed8") +
      labs(title = "Ribbon band")
    ggplot_webgl(p, height = 420)

## Code-only: Area band

    p <- ggplot(band, aes(x, y)) +
      geom_area_webgl(fill = "#a7f3d0", alpha = 0.7) +
      labs(title = "Area band")
    ggplot_webgl(p, height = 420)

## Applet: Simple polygon

    triangle <- data.frame(
      x = c(0, 1, 0.2),
      y = c(0, 0.2, 1),
      group = 1
    )

    p <- ggplot(triangle, aes(x, y, group = group)) +
      geom_polygon_webgl(fill = "#f97316", alpha = 0.7) +
      labs(title = "Simple polygon")
    ggplot_webgl(p, height = 420)

# Raster and Annotation Layers

Raster layers are intended for regular cell displays. Text and label layers are overlay metadata, not full WebGL glyph rendering.

## Applet: Raster grid

    small_raster <- expand.grid(
      x = seq_len(8),
      y = seq_len(6),
      KEEP.OUT.ATTRS = FALSE
    )
    small_raster$value <- with(small_raster, x * y)

    p <- ggplot(small_raster, aes(x, y, fill = value)) +
      geom_raster_webgl() +
      labs(title = "Raster grid")
    ggplot_webgl(p, height = 420)

## Applet: Text and rug overlays

    labels <- data.frame(
      x = c(2, 6),
      y = c(2, 5),
      label = c("low", "high")
    )

    p <- ggplot(small_raster, aes(x, y, fill = value)) +
      geom_tile_webgl(alpha = 0.55) +
      geom_text_webgl(data = labels, aes(x = x, y = y, label = label), inherit.aes = FALSE) +
      geom_rug_webgl(colour = "#334155") +
      labs(title = "Text and rug overlays")
    ggplot_webgl(p, height = 420)

## Code-only: Label overlay metadata

    p <- ggplot(labels, aes(x, y, label = label)) +
      geom_label_webgl(fill = "#ffffff", colour = "#0f172a") +
      labs(title = "Label overlay metadata")
    ggplot_webgl(p, height = 420)

# Facets, Coordinates, and Fallbacks

Fixed-scale facets are supported across the primitive families. Free-scale facets are serialized conservatively as metadata unless panel-local scaling is available for the layer combination being rendered.

## Code-only: Fixed-scale facets

    p <- ggplot(mtcars, aes(wt, mpg, colour = factor(cyl))) +
      geom_point_webgl() +
      facet_wrap(~am) +
      labs(title = "Fixed-scale facets")

    ggplot_webgl(p, height = 420)

Unsupported geoms remain visible to the extraction layer as unsupported metadata rather than being silently claimed as WebGL primitives. When a plot needs exact `ggplot2` parity for an unsupported layer, keep that layer in a static ggplot or replace it with one of the supported WebGL primitives above.