Bland.Figure (Elixir Technical Drawing v0.4.0)

Copy Markdown View Source

The plot document.

A %Figure{} holds the canvas dimensions, axis configuration, series list, and ornaments (legend, title block, annotations). Builder functions return updated figures so the whole pipeline stays immutable:

Bland.figure(size: :a5_landscape)
|> Bland.line([1, 2, 3], [1, 4, 9])
|> Bland.axes(xlabel: "n", ylabel: "n²")
|> Bland.render()

Paper sizes

size: accepts {width_px, height_px} tuples or one of the named paper presets (dimensions in pixels at 96 DPI):

  • :a4, :a4_landscape
  • :a5, :a5_landscape
  • :letter, :letter_landscape
  • :legal, :legal_landscape
  • :square — 600×600

The default is :letter_landscape.

Struct fields

  • :width, :height — canvas dimensions (px)
  • :margins{top, right, bottom, left} inside the border
  • :title, :subtitle — figure text
  • :xlim, :ylim — data-space limits, or :auto (default)
  • :xscale, :yscale:linear (default), :log, or :date
  • :xtick_format, :ytick_format — optional Calendar.strftime/2 format string for :date axes; nil (default) picks one based on the visible span
  • :xlabel, :ylabel
  • :grid:none | :major | :both

  • :series — list of %Bland.Series{} in draw order
  • :legend%{position: atom, title: string} | nil

  • :title_block%Bland.TitleBlock{} or nil
  • :annotations — list of %{type: atom, ...} overlays
  • :theme — map returned by Bland.Theme.get/1

Summary

Functions

Appends a series to the figure. Accepts a %Bland.Series.Line{} or similar struct, or any map tagged with :type.

Builds a new figure. opts accepts any of the struct fields, plus :size (alias for setting :width and :height from a preset) and :theme (atom or map, resolved via Bland.Theme.get/1).

List of built-in paper size presets.

Returns the inner plotting rectangle {x, y, w, h} in pixel coordinates, accounting for the figure's margins.

Resolves :size to {width, height}. Raises on unknown presets.

Updates the figure with a keyword list of overrides.

Types

size()

@type size() :: atom() | {pos_integer(), pos_integer()}

t()

@type t() :: %Bland.Figure{
  annotations: [map()],
  axes: term(),
  clip: :rect | :circle,
  colorbar: map() | nil,
  grid: :none | :major | :both,
  height: pos_integer(),
  legend: map() | nil,
  margins: {number(), number(), number(), number()},
  projection: atom(),
  series: [map()],
  subtitle: String.t() | nil,
  theme: map(),
  title: String.t() | nil,
  title_block: map() | nil,
  width: pos_integer(),
  xlabel: String.t() | nil,
  xlim: {number(), number()} | :auto,
  xscale: :linear | :log | :date,
  xtick_format: term(),
  ylabel: String.t() | nil,
  ylim: {number(), number()} | :auto,
  yscale: :linear | :log | :date,
  ytick_format: term()
}

Functions

add_series(fig, s)

@spec add_series(t(), map()) :: t()

Appends a series to the figure. Accepts a %Bland.Series.Line{} or similar struct, or any map tagged with :type.

new(opts \\ [])

@spec new(keyword()) :: t()

Builds a new figure. opts accepts any of the struct fields, plus :size (alias for setting :width and :height from a preset) and :theme (atom or map, resolved via Bland.Theme.get/1).

paper_sizes()

@spec paper_sizes() :: %{required(atom()) => {pos_integer(), pos_integer()}}

List of built-in paper size presets.

plot_rect(figure)

@spec plot_rect(t()) :: {number(), number(), number(), number()}

Returns the inner plotting rectangle {x, y, w, h} in pixel coordinates, accounting for the figure's margins.

resolve_size(name)

@spec resolve_size(size()) :: {pos_integer(), pos_integer()}

Resolves :size to {width, height}. Raises on unknown presets.

update(fig, opts)

@spec update(
  t(),
  keyword()
) :: t()

Updates the figure with a keyword list of overrides.