►V Reference
On this page:
58.7.1 Matrices and Tables
matrix
matrix-row-id
matrix-column-id
matrix-row-path
matrix-entry-path
matrix-bracket-path
table
table-row-id
table-column-id
table-row-path
table-cell-path
58.7.2 Linear-Algebra Diagrams
number-plane
number-plane-grid-path
number-plane-axes-path
number-plane-labels-path
vector-arrow
vector-coordinates
vector-label
basis-vectors
linear-transformation-diagram
9.3

58.7 Matrices, Tables, and Vector Diagrams🔗ℹ

Use matrix or table for rows of Visual entries. Their path helpers name cells without requiring a constructed matrix or table. Number planes and vector diagrams are also ordinary group trees; their stable child paths identify the components to animate.

See also Visual Protocols and Groups, Arrows and Coordinate Axes.

    58.7.1 Matrices and Tables

    58.7.2 Linear-Algebra Diagrams

58.7.1 Matrices and Tables🔗ℹ

matrix and table return ordinary immutable group-visual? values. Their rows and cells are regular nested groups, not a separate rendering or animation object. Existing path-addressed operations therefore work directly: (indicate (matrix-entry-path 'A 1 2)), move-to, follow-anchor, and transform-from-copy need no matrix/table variants.

Both constructors take a nonempty rectangular list of nonempty rows. Each entry must be an affine Visual. The constructor re-bases every entry at its cell centre, preserving identity, rotation, scale, opacity, style, and children but intentionally replacing its supplied reference position. Width and height can be one shared measure, one explicit per-axis list, or an 'auto construction-time measurement. The result is still an ordinary immutable group with no renderer dependency after construction.

procedure

(matrix rows    
  #:id id    
  [#:center center    
  #:rotation rotation    
  #:scale scale    
  #:opacity opacity    
  #:entry-width entry-width    
  #:entry-height entry-height    
  #:entry-padding entry-padding    
  #:column-gap column-gap    
  #:row-gap row-gap    
  #:brackets? brackets?    
  #:bracket-width bracket-width    
  #:bracket-gap bracket-gap    
  #:stroke stroke    
  #:stroke-width stroke-width    
  #:typography typography]) → group-visual?
  rows : (listof (listof (and/c visual? affine-visual?)))
  id : symbol?
  center : vec2? = origin
  rotation : finite-real? = 0
  scale : scale-factor? = 1
  opacity : opacity? = 1
  entry-width : 
(or/c 'auto (and/c finite-real? positive?)
      (listof (and/c finite-real? positive?)))
   = 1
  entry-height : 
(or/c 'auto (and/c finite-real? positive?)
      (listof (and/c finite-real? positive?)))
   = 1
  entry-padding : (and/c finite-real? (>=/c 0)) = 1/5
  column-gap : (and/c finite-real? (>=/c 0)) = 1/4
  row-gap : (and/c finite-real? (>=/c 0)) = 1/4
  brackets? : boolean? = #t
  bracket-width : (and/c finite-real? positive?) = 1/5
  bracket-gap : (and/c finite-real? (>=/c 0)) = 1/10
  stroke : any/c = "black"
  stroke-width : (and/c finite-real? (>=/c 0)) = 2
  typography : (or/c false/c typography-theme?) = #f
Creates an immutable matrix grid. Rows are named 'row-1, 'row-2, and so on; a row’s cells are named 'col-1, 'col-2, and so on. Thus a matrix named 'A exposes its second entry in the first row at '(A row-1 col-2). Equal 'col-1 names in different rows are permitted because their complete paths differ.

When brackets? is true, the matrix has ordinary open path children named 'left-bracket and 'right-bracket. They use square brackets, stroke, and stroke-width.

For either entry dimension, a positive scalar supplies one shared cell extent; a list supplies one extent per column or row; and 'auto measures each entry with the active default Pict renderer and selects the largest visible-box extent in that column or row. entry-padding is added on both sides of each auto-sized extent. This is a snapshot: later text/formula changes do not reflow a constructed matrix.

When entries include semantic text, pass #:typography to choose the snapshot used for 'auto measurement. Changing a project’s typography later changes that text’s rendering, but does not resize an already constructed matrix.

procedure

(matrix-row-id row) → symbol?

  row : exact-positive-integer?
Returns the local row identity, such as 'row-2.

procedure

(matrix-column-id column) → symbol?

  column : exact-positive-integer?
Returns the local column identity, such as 'col-2.

procedure

(matrix-row-path matrix-id row) → visual-path?

  matrix-id : symbol?
  row : exact-positive-integer?
Returns the row’s stable nested path, such as '(A row-2).

procedure

(matrix-entry-path matrix-id row column) → visual-path?

  matrix-id : symbol?
  row : exact-positive-integer?
  column : exact-positive-integer?
Returns the cell group’s stable nested path, such as '(A row-2 col-1). It does not require a matrix value at construction time, which makes it useful in independently declared animation requests.

Paths can be prepared without constructing or measuring a matrix.

Examples:
> (matrix-row-path 'A 2)

'(A row-2)

> (matrix-entry-path 'A 2 1)

'(A row-2 col-1)

procedure

(matrix-bracket-path matrix-id side) → visual-path?

  matrix-id : symbol?
  side : (or/c 'left 'right)
Returns the path for the selected square-bracket child.

procedure

(table rows    
  #:id id    
  [#:center center    
  #:rotation rotation    
  #:scale scale    
  #:opacity opacity    
  #:cell-width cell-width    
  #:cell-height cell-height    
  #:cell-padding cell-padding    
  #:column-gap column-gap    
  #:row-gap row-gap    
  #:stroke stroke    
  #:stroke-width stroke-width    
  #:typography typography]) → group-visual?
  rows : (listof (listof (and/c visual? affine-visual?)))
  id : symbol?
  center : vec2? = origin
  rotation : finite-real? = 0
  scale : scale-factor? = 1
  opacity : opacity? = 1
  cell-width : 
(or/c 'auto (and/c finite-real? positive?)
      (listof (and/c finite-real? positive?)))
   = 1
  cell-height : 
(or/c 'auto (and/c finite-real? positive?)
      (listof (and/c finite-real? positive?)))
   = 3/4
  cell-padding : (and/c finite-real? (>=/c 0)) = 1/5
  column-gap : (and/c finite-real? (>=/c 0)) = 0
  row-gap : (and/c finite-real? (>=/c 0)) = 0
  stroke : any/c = "black"
  stroke-width : (and/c finite-real? (>=/c 0)) = 2
  typography : (or/c false/c typography-theme?) = #f
Creates an immutable grid table. Its row/cell names use the same 'row-N/'col-N convention as matrix. Shared grid boundaries are ordinary child paths named 'grid-column-0, 'grid-column-1, and so on, followed by 'grid-row-0, 'grid-row-1, and so on. Each boundary is drawn once, avoiding doubled cell-border strokes.

The cell-size arguments follow the same scalar/list/'auto policy as matrix. Auto measurement adds cell-padding on all sides and does not remeasure after construction. Pass #:typography when automatic cell sizing measures semantic text.

procedure

(table-row-id row) → symbol?

  row : exact-positive-integer?
Returns the table’s local 'row-N identity.

procedure

(table-column-id column) → symbol?

  column : exact-positive-integer?
Returns the table’s local 'col-N identity.

procedure

(table-row-path table-id row) → visual-path?

  table-id : symbol?
  row : exact-positive-integer?
Returns the row’s stable table path.

procedure

(table-cell-path table-id row column) → visual-path?

  table-id : symbol?
  row : exact-positive-integer?
  column : exact-positive-integer?
Returns the cell group’s stable table path, such as '(results row-2 col-3).

58.7.2 Linear-Algebra Diagrams🔗ℹ

Linear-algebra diagram constructors create small, conventional diagrams without a mutable diagram class. Each constructor below returns an ordinary immutable Visual or group-visual?. Its children retain their normal nested paths, so existing scene operations work directly. In particular, apply-matrix can map one complete top-level diagram coherently.

procedure

(number-plane #:id id 
  [#:x-range x-range 
  #:y-range y-range 
  #:x-length x-length 
  #:y-length y-length 
  #:center center 
  #:rotation rotation 
  #:scale scale 
  #:grid? grid? 
  #:labels? labels? 
  #:grid-stroke grid-stroke 
  #:grid-stroke-width grid-stroke-width 
  #:axes-stroke axes-stroke 
  #:axes-stroke-width axes-stroke-width 
  #:label-font-size label-font-size 
  #:label-color label-color]) 
 → group-visual?
  id : symbol?
  x-range : axis-range? = (axis-range -4 4 1)
  y-range : axis-range? = (axis-range -3 3 1)
  x-length : (and/c finite-real? positive?) = 8
  y-length : (and/c finite-real? positive?) = 6
  center : vec2? = origin
  rotation : finite-real? = 0
  scale : scale-factor? = 1
  grid? : boolean? = #t
  labels? : boolean? = #f
  grid-stroke : any/c = "lightsteelblue"
  grid-stroke-width : (and/c finite-real? (>=/c 0)) = 1
  axes-stroke : any/c = "navy"
  axes-stroke-width : (and/c finite-real? (>=/c 0)) = 2
  label-font-size : (and/c finite-real? positive?) = 1/4
  label-color : any/c = "navy"
Creates a conventional Cartesian number plane. The returned group has an 'axes child and, when requested, 'grid and 'labels children. The grid uses the plane’s ranges and display lengths; its geometry is therefore in the same coordinate system as the axes. Numeric labels are absent by default, because dense labels are often inappropriate in an animation.

The stable direct-child paths are produced by number-plane-grid-path, number-plane-axes-path, and number-plane-labels-path. When #:grid? or #:labels? is false, its corresponding path intentionally does not resolve.

procedure

(number-plane-grid-path plane-id) → visual-path?

  plane-id : symbol?
Returns (list plane-id 'grid).

procedure

(number-plane-axes-path plane-id) → visual-path?

  plane-id : symbol?
Returns (list plane-id 'axes).

procedure

(number-plane-labels-path plane-id) → visual-path?

  plane-id : symbol?
Returns (list plane-id 'labels).

procedure

(vector-arrow endpoint    
  [#:start start]    
  #:id id    
  [#:stroke stroke    
  #:stroke-width stroke-width    
  #:tip-length tip-length    
  #:tip-width tip-width]) → arrow-visual?
  endpoint : vec2?
  start : vec2? = origin
  id : symbol?
  stroke : any/c = "darkorchid"
  stroke-width : (and/c finite-real? (>=/c 0)) = 3
  tip-length : (and/c finite-real? positive?) = 3/10
  tip-width : (and/c finite-real? positive?) = 1/4
Creates an ordinary arrow from start to endpoint. The name is deliberately vector-arrow, not vector, so requiring animate does not shadow Racket’s built-in vector constructor.

procedure

(vector-coordinates arrow) → vec2?

  arrow : arrow-visual?
Returns the arrow’s endpoint minus its start point, in the arrow’s containing coordinate system.

procedure

(vector-label arrow    
  #:id id    
  [#:text text    
  #:offset offset    
  #:font-size font-size    
  #:color color]) → text-visual?
  arrow : arrow-visual?
  id : symbol?
  text : (or/c false/c string?) = #f
  offset : vec2? = (vec2 1/5 1/5)
  font-size : (and/c finite-real? positive?) = 1/4
  color : any/c = "darkorchid"
Creates a static text label beside arrow’s endpoint. Without #:text, its content is the vector’s coordinate pair. This is a construction-time snapshot: if the arrow itself is separately animated, rebuild the label through derived-visual when it needs to follow the arrow.

procedure

(basis-vectors #:id id    
  [#:origin origin    
  #:e1 e1    
  #:e2 e2    
  #:e1-color e1-color    
  #:e2-color e2-color    
  #:stroke-width stroke-width]) → group-visual?
  id : symbol?
  origin : vec2? = origin
  e1 : vec2? = (vec2 1 0)
  e2 : vec2? = (vec2 0 1)
  e1-color : any/c = "crimson"
  e2-color : any/c = "forestgreen"
  stroke-width : (and/c finite-real? (>=/c 0)) = 3
Creates a group with conventional 'e1 and 'e2 arrow children. The e1 and e2 arguments are endpoints, not displacement vectors: their common start is origin.

procedure

(linear-transformation-diagram #:id id 
  [#:x-range x-range 
  #:y-range y-range 
  #:vector-end vector-end 
  #:unit-square? unit-square? 
  #:grid? grid?]) 
 → group-visual?
  id : symbol?
  x-range : axis-range? = (axis-range -4 4 1)
  y-range : axis-range? = (axis-range -3 3 1)
  vector-end : vec2? = (vec2 3 2)
  unit-square? : boolean? = #t
  grid? : boolean? = #t
Creates the standard matrix-action diagram. Its stable children are 'plane, 'basis, 'vector, and, unless disabled, 'unit-square. The first two have their own paths such as '(diagram plane grid) and '(diagram basis e1).

For example, this keeps all geometric parts together while a title remains fixed outside the mapped group:

(define diagram
  (linear-transformation-diagram #:id 'diagram
                                 #:vector-end (vec2 3 2)))
 
(scene-play
 (scene-add (make-scene) diagram)
 (apply-matrix 'diagram
               (linear2 1 1
                        0 1))
 #:duration 3)