►V Reference
On this page:
58.17.1 First-Class Relation Visuals
relation-visual
relation-context-layout-box
relation-visual?
relation-visual-dependencies
relation-visual-cacheability
relation-dependency?
relation-context?
relation-context-anchor-ref
value-dependency
visual-dependency
anchor-dependency
selection-dependency
scene-validate-relations
scene-relation-report
scene-relation-sample-report
follow-anchor
58.17.1.1 Acyclic Live Layout
follow-above
follow-below
follow-left-of
follow-right-of
9.3

58.17 Relations and Live Layout🔗ℹ

A relation records dependencies and recomputes concrete geometry from a sampled scene state. Choose semantic resolution for model coordinates and layout resolution for renderer-measured anchors or boxes. Following helpers are relations too; they do not require a mutable frame updater.

See also Visual Protocols and Groups, Live Endpoints and Mathematical Annotations.

    58.17.1 First-Class Relation Visuals

      58.17.1.1 Acyclic Live Layout

58.17.1 First-Class Relation Visuals🔗ℹ

A relation is an immutable Visual whose concrete geometry is recomputed from explicit dependencies in each sampled scene state. No relation uses a mutable updater or needs the preceding frame.

procedure

(relation-visual template    
  [#:depends-on dependencies    
  #:phase phase    
  #:structure structure    
  #:space space    
  #:cache-key cache-key]    
  resolver) → relation-visual?
  template : visual?
  dependencies : (listof relation-dependency?) = '()
  phase : (or/c 'semantic 'layout) = 'semantic
  structure : (or/c 'root-only 'fixed) = 'root-only
  space : (or/c 'world 'local) = 'world
  cache-key : any/c = #f
  resolver : (-> relation-context? visual? visual?)
Creates a relation with the stable identity of template. The resolver receives a read-only relation-context? and a local template, and must return one concrete Visual with the same identity. Every value, Visual, renderer-anchor, or semantic selection read through the context must be named in dependencies; undeclared reads fail descriptively.

The ordinary movement, rotation, scale, opacity, fill, stroke, and stroke-width controls form an outer envelope. They are applied after the resolver has computed the current geometry, so a relation may be animated concurrently with its own changing dependencies. A requested style must be supported by both the template and the concrete result. A 'fixed relation preserves the template’s complete child-ID tree and may expose nested paths; a 'root-only relation deliberately exposes only its root ID.

A 'semantic relation is resolved from model data. A 'layout relation may use relation-context-anchor-ref, relation-context-layout-box, or selection boxes after the active renderer has measured its targets. Layout relations are currently top-level only, and their measurements are complete Pict boxes rather than tight visible outlines.

procedure

(relation-context-layout-box context    
  visual) → layout-box?
  context : relation-context?
  visual : visual?
Measures one resolver-local concrete Visual in the active renderer/camera configuration. This operation is available only to layout relations. It is intended for relations such as follow-anchor that must align one anchor of their own content to an anchor of another Visual.

procedure

(relation-visual? value) → boolean?

  value : any/c
Recognizes an immutable relation Visual.

procedure

(relation-visual-dependencies relation)

 → (listof relation-dependency?)
  relation : relation-visual?
Returns the relation’s explicitly declared dependencies in author order.

procedure

(relation-visual-cacheability relation)

 → (or/c 'serializable 'explicit-key 'disabled)
  relation : relation-visual?
Reports whether the resolver can participate in a persistent cache. Built-in transparent specifications are 'serializable; an author procedure with #:cache-key is 'explicit-key; an opaque procedure is 'disabled.

procedure

(relation-dependency? value) → boolean?

  value : any/c
Recognizes a declared value, Visual, anchor, or selection dependency.

procedure

(relation-context? value) → boolean?

  value : any/c
Recognizes the read-only context supplied to a relation resolver.

procedure

(relation-context-anchor-ref context    
  target    
  anchor) → vec2?
  context : relation-context?
  target : (or/c visual? symbol? visual-path?)
  anchor : symbol?
Returns a renderer-measured anchor for a layout relation after recording the corresponding declared anchor-dependency.

procedure

(value-dependency target) → relation-dependency?

  target : (or/c symbol? scene-parameter?)
Declares one sampled scalar/value input.

procedure

(visual-dependency target) → relation-dependency?

  target : (or/c visual? symbol? visual-path?)
Declares one semantic Visual input.

procedure

(anchor-dependency target anchor) → relation-dependency?

  target : (or/c visual? symbol? visual-path?)
  anchor : symbol?
Declares one renderer-measured anchor input.

procedure

(selection-dependency selection) → relation-dependency?

  selection : visual-selection?
Declares one semantic selection input.

procedure

(scene-validate-relations state) → immutable-hash?

  state : scene-state?
Checks declared relation dependencies and reports missing targets or deterministic dependency cycles before rendering.

procedure

(scene-relation-report state [target]) → any/c

  state : scene-state?
  target : (or/c #f visual? symbol? visual-path?) = #f
Returns deterministic relation-resolution report data without invoking author resolver procedures. It records full path, drawing order, phase, structure, declared dependencies, cacheability, and warnings. Library-owned serializable specifications are cacheable; generic resolver procedures remain opaque unless the author supplies #:cache-key.

procedure

(scene-relation-sample-report state [target]) → any/c

  state : scene-state?
  target : (or/c #f visual? symbol? visual-path?) = #f
Returns the same report shape, but additionally resolves each selected 'semantic relation once for this sampled state. The report’s 'used-dependencies and 'unused-dependencies fields then distinguish declared inputs that the resolver actually read from declared inputs it did not read at this instant. This is an opt-in diagnostic operation: it can run the author’s resolver procedure, but does not alter the immutable scene state or renderer cache.

For a 'layout relation those fields are #f. Determining its actual reads requires the active renderer’s measured layout boxes, which this headless report intentionally does not invent.

Built-in line-between, arrow-between, ray-from, parameter-display, and follow-anchor use serializable relation specifications. The live angle, brace, and curved-arrow constructors use generic relations because their builder procedure is author-specific; therefore they deliberately do not claim automatic persistent-cache reuse.

procedure

(follow-anchor content 
  target 
  [#:offset offset 
  #:target-anchor target-anchor 
  #:self-anchor self-anchor]) 
 → relation-visual?
  content : visual?
  target : (or/c visual? symbol? visual-path?)
  offset : vec2? = origin
  target-anchor : 
(or/c 'bottom-left 'bottom 'bottom-right
      'left 'center 'right
      'top-left 'top 'top-right)
   = 'center
  self-anchor : 
(or/c 'bottom-left 'bottom 'bottom-right
      'left 'center 'right
      'top-left 'top 'top-right)
   = 'center
Creates one world-space relation whose selected content anchor follows the selected sampled anchor of target, plus offset. target may be a top-level Visual, its symbol identity, or a nested path. The default centre-to-centre form is a semantic relation: it follows the target’s sampled reference point without invoking a renderer. Choosing a non-centre target or content anchor creates a layout relation, which measures the relevant Pict box in the active camera and renderer configuration. Both forms follow target motion without frame-mutating callbacks.

The content must be a concrete, non-frame-space Visual, and content and target must have distinct identities. Attachments may be animated through the normal relation envelope. One attachment may target another when the resulting relation graph is acyclic; they neither avoid other labels nor inherit target rotation. Layout attachments are top-level and renderer-dependent; a semantic centre attachment can be queried directly from a sampled scene state.

An attachment is a relation with an inspectable built-in specification.

Examples:
> (define attachment
    (follow-anchor (circle #:id 'follower) 'target #:offset (vec2 1 0)))
> (relation-visual? attachment)

#t

> (relation-visual-cacheability attachment)

'serializable

58.17.1.1 Acyclic Live Layout🔗ℹ

The live-layout procedures give renderer-aware attachments concise relationship names. Their relation graph is resolved from a concrete target outward at each render. A direct or indirect cycle raises an exception; no prior frame is consulted.

procedure

(follow-above content target [#:gap gap]) → relation-visual?

  content : visual?
  target : (or/c visual? symbol? visual-path?)
  gap : (and/c finite-real? (>=/c 0)) = 0
Places the content’s bottom anchor at the target’s top anchor plus gap.

procedure

(follow-below content target [#:gap gap]) → relation-visual?

  content : visual?
  target : (or/c visual? symbol? visual-path?)
  gap : (and/c finite-real? (>=/c 0)) = 0
Places the content’s top anchor at the target’s bottom anchor minus gap.

procedure

(follow-left-of content target [#:gap gap]) → relation-visual?

  content : visual?
  target : (or/c visual? symbol? visual-path?)
  gap : (and/c finite-real? (>=/c 0)) = 0
Places the content’s right anchor at the target’s left anchor minus gap.

procedure

(follow-right-of content target [#:gap gap]) → relation-visual?

  content : visual?
  target : (or/c visual? symbol? visual-path?)
  gap : (and/c finite-real? (>=/c 0)) = 0
Places the content’s left anchor at the target’s right anchor plus gap.