Client-side 3D charting for Libertas protocol data

This is the V1 chart contract for schema authors and compatible clients. Schema support and renderer availability are distinct: a client that cannot display a chart follows the chart failure policy. This reference does not certify feature parity for every distributed build.

Presentation uses the schema, exact dependency versions, and locale document associated with the returned value; unrelated installed versions do not redefine that value. See the schema reference.

The existing two-dimensional contract remains independently normative in Client-side charting for Libertas protocol data. This document adds a parallel, opt-in 3D namespace. Nothing here changes the meaning, validation, canonicalization, layout, or rendering of Chart, ChartChannel, ChartScale, or ChartGuide.

1. Purpose and compatibility boundary

A Libertas protocol response or subscription-data payload may carry a server-prepared three-dimensional chart. The App remains responsible for every domain calculation, including sampling functions, calculating contours, projecting data, grouping series, and selecting topology. The client resolves scales, constructs the declared primitives, lays out guides, presents an accessible camera, and preserves the ordinary typed-data view.

The language-neutral schema uses five attributes:

Attribute Placement Purpose
Chart3D A chart-data List, unit-carrier Table, or composition Table Select one 3D primitive mark or composition.
Chart3DChannel A direct scalar field of a 3D chart row Map the field to geometry, appearance, topology, or structural roles.
Chart3DScale A field with one scale-bearing Chart3DChannel role Override automatic scale behavior or share a scale.
Chart3DGuide A direct scalar field of a 3D chart row Configure, suppress, or source an axis, legend, or facet heading.
Chart3DView A unit or composition root, subject to physical-scene ownership Set projection, initial camera, and independently enabled camera interactions.

The boundary is strict:

  • a node cannot carry both a `Chart3D*` attribute and a `Chart*` attribute;
  • a visible result, carrier, composition, or Union wrapper cannot mix two-dimensional and three-dimensional chart children (see composition children and Union wrappers);
  • a `Chart3DScale.id` never resolves to a `ChartScale.id`, even when their spelling is identical;
  • clients never interpret `Chart3DChannel`, `Chart3DScale`, `Chart3DGuide`, or Chart3DView as aliases of their two-dimensional counterparts; and
  • a schema without `Chart3D*` attributes has exactly its pre-3D behavior and final schema representation.

An older client does not recognize Chart3D as Chart, so it never enters its two-dimensional renderer. An unsupported 3D presentation follows the shared chart failure policy; the protocol response itself remains accepted.

The Hub has no chart renderer and needs no 3D-specific message, persistence, cache, or runtime-value handling. It transports the validated attributes and existing typed values through the ordinary schema and protocol paths.

2. Source and generated syntax

TypeScript source uses:

TypeScript
/**
 * Samples in three dimensions.
 * @LibertasChart3D(point)
 * @LibertasChart3DView(projection=perspective, azimuth=45,
 *                      elevation=30, zoom=1, fov=45, orbit=true)
 */
export type Samples = Sample[];

export interface Sample {
  /** @LibertasChart3DChannel(x, tooltip) */
  x: number;
  /** @LibertasChart3DChannel(y, tooltip) */
  y: number;
  /** @LibertasChart3DChannel(z, tooltip) */
  z: number;
}

Rust source uses:

Rust
#[derive(LibertasExport, LibertasAvroDecode)]
pub struct Sample {
    #[libertas_chart3d_channel(x, tooltip)]
    pub x: f64,
    #[libertas_chart3d_channel(y, tooltip)]
    pub y: f64,
    #[libertas_chart3d_channel(z, tooltip)]
    pub z: f64,
}

#[libertas_chart3d(point)]
#[libertas_chart3d_view(
    projection = perspective,
    azimuth = 45,
    elevation = 30,
    zoom = 1,
    fov = 45,
    orbit = true
)]
pub type Samples = Vec<Sample>;

The generated attributes are ordinary schema attributes:

JSON
{
  "Attributes": [
    { "Name": "Chart3D", "Value": "point" },
    {
      "Name": "Chart3DView",
      "Value": "projection=perspective,azimuth=45,elevation=30,zoom=1,fov=45,orbit=true"
    }
  ]
}

Every attribute value is closed and canonical. Source-language whitespace and quoting are removed, duplicate roles are deduplicated where specified, and properties are written in the fixed orders below. Each schema node may contain at most one attribute of each of the five names. Attribute inheritance uses the ordinary nearest-declaration rule: the nearest value replaces the complete same-named value rather than merging individual roles or properties.

Chart3DScale uses source property kind; the parser result uses type, which Studio compiles into the package's Display Template as a scale hint and omits from the final schema. A source declaration using type is invalid. Numeric properties use the same finite shortest-round-tripping binary64 canonical spelling as ChartScale.

3. Placement and authoritative data

3.1 Unit charts

A unit chart is a complete snapshot with this effective shape:

Text
List<Table Row> carrying Chart3D=<mark>

The List carries Chart3D. Direct scalar fields of Row carry Chart3DChannel and optional Chart3DScale and Chart3DGuide. An App duplicates a logical value into separate fields when it needs independently scaled roles.

A row field may carry Hidden=true. It is chart data, not presentation: the client keeps it in the retained row value, so a custom chart request can CopyFrom it. Chart presentation data is never Hidden: a row field carrying Hidden=true cannot carry Chart3DChannel, Chart3DScale, or Chart3DGuide; Studio rejects that chart metadata.

A mark may instead be applied to a carrier table:

Text
Table UnitCarrier carrying Chart3D=<mark> {
    data: List<Table Row>
    transactionContext: any value carrying Hidden=true
    ...
}

data is the exactly one non-hidden direct field and is the real chart data. It does not repeat Chart3D; the enclosing table owns the mark. Every other direct field carries Hidden=true. Hidden values may use any otherwise valid Libertas type. They do not become marks, channels, guide content, topology, tooltips, interaction identity, accessibility content, or chart resource usage. The client retains the complete carrier so a later typed request or CopyFrom operation can reuse transaction context.

3.2 Compositions

A composition has this effective shape:

Text
Table Composition carrying Chart3D=<composition> {
    childA: List<Table RowA> carrying Chart3D=<mark>
    childB: List<Table RowB> carrying Chart3D=<mark>
    transactionContext: any value carrying Hidden=true
    ...
}

Every non-hidden direct child must independently carry Chart3D. At least one such child is required. Other direct fields must carry Hidden=true. Children are traversed in schema order.

3.3 Protocol Union wrappers

A Response or SubscriptionData Union variant may carry Chart3D itself, or it may be an unannotated carrier table containing exactly one non-hidden direct field whose effective type carries Chart3D. Every sibling must carry Hidden=true.

Clients never recursively search for an arbitrary annotated descendant and never choose among several chart fields. The effective selected variant or its one permitted direct chart field is the only presentation root. More than one visible chart field, one visible non-chart field beside a chart, or a mixture of Chart and Chart3D invalidates chart presentation.

The complete selected variant remains the authoritative source tree even when the renderer projects its one chart field. Hidden context is never cloned away.

The selected Response or SubscriptionData variant's localized name and description supply the overall chart title and description, even when the chart payload is a child field. Child charts within a composition retain their own localized names and descriptions.

3.4 Complete snapshots

Every response, and every complete subscription snapshot, replaces the prior chart snapshot. A subscription report may instead extend or update the working value through the shared mechanisms described in the 2D snapshot rule. Clients do not otherwise join, patch, or merge rows, grids, series, or topology. An empty list is a valid empty chart when its schema is valid. A data-changing interaction sends an ordinary typed protocol request and receives another complete snapshot. Snapshot replacement does not imply presentation-camera reset; Section 8.2 defines camera continuity.

4. Chart3D

Chart3D contains exactly one lowercase token:

Text
mark        = "point" | "line" | "bar" |
              "surface" | "wireframe" | "stem"
composition = "layer" | "hconcat" | "vconcat"
chart3d     = mark | composition

4.1 Primitive marks

Every primitive requires one x, one y, and one z binding.

Mark Additional geometry Meaning
point Forbids x2,y2,z2,u,v A three-dimensionally positioned symbol. size produces Bubble 3D.
line Forbids x2,y2,z2,u,v One or more ordered 3D polylines.
bar Banded/value, sparse-column, or complete explicit-cuboid form An axis-aligned 3D bar or column with independently controlled base extents.
surface Continuous x,y,z; optional paired u,v; no secondary endpoints Filled rectangular-grid or parameter-grid surface.
wireframe Same topology as surface Surface grid edges without filled faces.
stem Optional z2; forbids x2,y2,u,v A segment from (x,y,z2) to (x,y,z), using the resolved z-scale base plane when z2 is absent.

tooltip, detail, key, row, and column are available to every mark. order is meaningful for line and for deterministic independent-mark paint and hit-test ties. Surface and wireframe topology is owned by x,y or u,v, not by list order; an order binding does not change mesh connectivity.

Point and line

point and line use the mapped location (x,y,z). A null or non-finite required coordinate suppresses a point and breaks a line path. Line rows are partitioned first by facet and then by the composite raw detail identity. List order is the default vertex order; an order binding sorts ascending within each path with source order retained for ties. An Unordered source list carrying line must declare order.

Each of x, y, and z may independently be continuous, categorical, or an explicitly discrete numeric/temporal position. A categorical point axis uses a point scale unless explicitly banded; the renderer never coerces its localized label back into geometry.

Point and stem-tip symbols may be camera-facing or volumetric. The complete portable identity catalog and automatic categorical assignment order is:

Text
circle,square,triangle,diamond,sphere,cube,pyramid,cylinder

The first four are camera-facing symbols; the final four are plot-space 3D primitives. circle is the default. An automatic shape scale assigns categories in canonical raw-domain order, cycles through this list, and repeats from circle only after exhausting it. An identity shape must be one of these tokens; it is never a platform class, path, model, image, or URL. One client cannot substitute a native-only shape or change this assignment order.

size is a finite non-negative relative magnitude. Zero suppresses a point or stem-tip marker without removing its row from tooltips or accessibility. An automatic size scale preserves authored zero and chooses a responsive positive output range for positive values from the plot dimensions, available display area, and accessibility settings. The schema imposes no fixed projected-radius range. Numeric identity size is likewise finite and non-negative. For a camera-facing symbol it controls projected size; for a volumetric symbol it controls plot-space diameter and therefore participates in perspective. The resolved shape determines that interpretation consistently on every client. This permits both screen-stable Bubble 3D symbols and volume-calibrated solid symbols without making either model mandatory.

Bar

A bar has one of three deterministic forms. Classification is unambiguous: all six positions select the explicit cuboid; otherwise a continuous z selects the normal x/y-base sparse column; every remaining valid shorthand must satisfy the legacy two-band/one-value rule. A z-oriented legacy-shaped row therefore has the same geometry as a normal sparse column and follows the normal form.

The legacy banded/value form has:

  • two primary axes with effective band scales; and
  • one continuous value axis, optionally with its matching secondary endpoint.

The value axis may be x, y, or z. When its secondary is present, both endpoints are explicit and either order is valid. Otherwise the client uses the resolved scale base plane: zero when zero is representable and included in the resolved domain, or the lower resolved domain boundary otherwise. The sole continuous axis identifies the value axis, so this form may point along x, y, or z without another orientation property.

The normal sparse-column form uses x and y as base positions and z as the value axis:

Text
x[,x2],y[,y2],z[,z2]

Each base axis may be continuous or discrete. A band base starts with its full domain-slot bandwidth. An explicit point-scale base, or a continuous base without a secondary, derives a centered interval from adjacent distinct mapped positions in the same facet/detail group. Its available width is the smallest positive mapped gap to either neighbor, or the sole gap at an endpoint. An isolated position uses one tenth of the mapped axis length. Scale padding is then applied to that band, point, or inferred continuous interval. A continuous base with a matching secondary instead uses the authored interval, and padding has no effect on it. z2 is the authored baseline. Without z2, the baseline is the same resolved scale base plane described above. Positive log domains, all-positive or all-negative linear domains, and temporal domains remain valid without z2; they use their lower resolved boundary.

The explicit-cuboid form requires all six positions:

Text
x,x2,y,y2,z,z2

Every axis is continuous; each secondary has the same effective scalar class, unit, and scale as its primary. Endpoint order is not semantic. No baseline or width is invented.

The sparse-column form may contain any subset of the three secondaries. They are independent: x2 and y2 author continuous base extents, while z2 authors the baseline. In the banded/value form, only the sole continuous value axis may have a secondary; band bases cannot. The explicit-cuboid form requires all three. See secondary-channel compatibility and the bar forms.

size on a bar is a finite non-negative per-row multiplier applied to both base extents after explicit/inferred extent and padding resolution; zero produces a degenerate bar without removing its source row, and the multiplier never changes the value endpoint or baseline. Automatic shape scales use the portable bar-shape order box,cylinder,pyramid,sphere, cycling only after all four. Identity bar shapes use the same four-token catalog; the primitive is aligned between the baseline and value endpoint and scaled to the two resolved base extents. The default is box.

Stem

stem uses (x,y,z) as its tip and (x,y,z2) as its base. x2 and y2 are never accepted. The z binding is continuous. With no z2, the base is the resolved z-scale base plane: zero when representable and included, otherwise the lower resolved domain boundary. With z2, both z fields are compatible continuous values. The x and y positions retain the general continuous or discrete position compatibility from Section 5.2. size, shape, and fill roles add a marker at the tip; omitting them produces the path alone.

4.2 Appearance applicability

Appearance is closed rather than renderer-dependent:

Mark Accepted appearance roles
point color,fill,stroke,opacity,fillOpacity,strokeOpacity,size,shape,strokeWidth,strokeDash
line color,stroke,opacity,strokeOpacity,strokeWidth,strokeDash
bar color,fill,stroke,opacity,fillOpacity,strokeOpacity,size,shape,strokeWidth,strokeDash
surface color,fill,stroke,opacity,fillOpacity,strokeOpacity,strokeWidth,strokeDash
wireframe color,stroke,opacity,strokeOpacity,strokeWidth,strokeDash
stem color,fill,stroke,opacity,fillOpacity,strokeOpacity,size,shape,strokeWidth,strokeDash

An appearance role outside its row is invalid rather than ignored. Existing V1 paint palettes, identity-token validation, opacity ranges, stroke-width ranges, dash tokens, theme contrast rules, the Display Template palette, and the requirement that paint not be the sole carrier of meaning apply unchanged, but through the independent Chart3DChannel and Chart3DScale attributes.

color supplies the mark-default paint: point fill and boundary, line, wireframe, and stem stroke, or bar and surface fill. Explicit fill or stroke overrides that component. Stroke metadata alone never creates a boundary when neither stroke nor an applicable color resolves one.

For stem, size and shape describe a marker at the tip, while fill and fillOpacity describe that marker's interior. The stem segment remains the stroke component. A renderer with no native impulse-marker primitive constructs the same result from a segment and point marker; that lowering is not visible in schema or interaction semantics.

4.3 Compositions

Token Meaning
layer Draw every child in one depth-tested 3D scene.
hconcat Place independent 3D scenes left to right.
vconcat Place independent 3D scenes top to bottom.

A layer child is a unit chart or another layer. A direct concat child is invalid because it does not share one physical scene. Nested layers flatten depth-first in schema order. Concat children may be units, layers, or further concats, allowing explicit grids.

Depth normally determines visibility. When two fragments have equal mapped depth, the later flattened child wins, then the later canonical row. A renderer may use a bounded render-only depth bias to implement that tie; it must not change data coordinates, scales, domains, tooltip values, hit identities, or requests. This rule makes server-emitted contour lines layered after a surface stable rather than subject to platform-specific z-fighting.

row and column create facets. Every facet is an independent camera scene using the unit or enclosing layer's view. A layer may lower compatible children into one facet grid only when their ordered raw facet domains are identical; otherwise it uses independent grids or follows the chart failure policy in §12.6.

5. Chart3DChannel

The value is a comma-separated set of roles. Studio deduplicates and emits them in this order:

Text
x,x2,y,y2,z,z2,u,v,
color,fill,stroke,opacity,fillOpacity,strokeOpacity,
size,shape,strokeWidth,strokeDash,
tooltip,detail,order,key,row,column

The vocabulary is:

Group Roles Meaning
Position x,x2,y,y2,z,z2 Three primary coordinates and paired endpoints.
Surface topology u,v Parameter-grid adjacency; not visual scales.
Paint color,fill,stroke Default paint or explicit component paint.
Paint strength opacity,fillOpacity,strokeOpacity Overall or component alpha.
Symbol/stroke size,shape,strokeWidth,strokeDash Point/bar geometry or path appearance.
Inspection tooltip Values included in the typed inspector.
Structure detail,order,key Series grouping, path/paint order, and stable row identity.
Facet row,column Small-multiple partitioning.

5.1 Multiplicity

All roles except tooltip and detail are singletons within a unit. tooltip and detail may occur on multiple fields; multiple details form a composite raw series key in schema field order.

A field may drive multiple scale-bearing roles when every one uses its implicit scale; for example, z,color,tooltip can position and color by the same raw value. A field-level Chart3DScale still requires exactly one scale-bearing role because that attribute has no target property with which to disambiguate the scale. A source=scale or source=none guide does have a target, so it may select one matching role on a multi-role field. A field may also combine scaled roles with non-scale roles such as tooltip, detail, order, key, or one topology role. Thus x,u,tooltip is valid, and a field-level Chart3DScale unambiguously configures x because u is not scale-bearing. A field may not carry both u and v.

x2, y2, and z2 use the corresponding primary scale. A secondary cannot carry Chart3DScale or exist without its primary. u and v never own a scale or guide; a field carrying either topology role cannot declare Chart3DScale for that topology role. A scale on the same field may configure one other scale-bearing role such as x, y, or z.

5.2 Scalar compatibility

V1 imports the typed scalar identities, formatting, categorical ordering, and provenance rules from the 2D contract. Compatibility is closed:

Role Permitted effective scalar values
x,y,z Continuous or explicitly discrete Number, DateOnly Number, DateTime, TimeOnly, or a categorical V1 chart scalar
x2,y2,z2 A continuous ordinary Number, DateOnly Number, DateTime, or TimeOnly compatible with its primary
u,v Finite Number without DateOnly or a topology-owned visual scale
row,column Categorical, or an allowed explicitly banded discrete numeric/temporal scalar
color,fill,stroke Continuous Number, categorical value, or validated identity String
opacity,fillOpacity,strokeOpacity,size,strokeWidth Ordinary Number
shape,strokeDash Categorical or validated identity String; an allowed discrete integral Number may opt into ordinal behavior
tooltip,detail,order,key Any V1 chart scalar

surface and wireframe additionally require continuous x,y,z; their geometry cannot use categorical, ordinal, band, or point position scales. An omitted bar or stem endpoint uses the resolved value-scale base plane and therefore remains valid for numeric, logarithmic, or temporal continuous axes.

Physical units and Format remain presentation metadata on the same typed raw value. V1 performs no unit conversion. Paired endpoints and shared scales have identical effective PhysicalUnit and compatible Format requirements.

5.3 Identity, order, and missing values

Grouping, uniqueness, category domains, series identity, and key identity use canonical raw typed values, never localized labels. Floating negative zero is canonicalized to positive zero for identity. Non-finite values cannot become keys or topology indices.

A non-null key is unique within its unit, facet, and detail tuple. Duplicate keys invalidate 3D presentation. Without a key, a source row index is identity only for the current complete snapshot.

Null or non-finite required point/bar/stem coordinates suppress that row. They break line paths. For surface and wireframe they remove the vertex and every incident face or edge. Null optional appearance uses the theme-native default. Null tooltips are omitted.

6. Chart3DScale

Chart3DScale starts with the ChartScale property and type vocabulary, adds portable logarithm-base control, automatic-domain growth, and 3D bar-base padding, and participates only in a Chart3D tree:

Text
property-order = id,type,logBase,min,max,mid,zero,reverse,
                 growMin,growMax,padding

type = linear | log | symlog | sqrt | time | utc |
       ordinal | band | point | identity

The generated grammar is a nonempty comma-delimited list of unique key=value properties in property order. id is a canonical schema identifier. zero and reverse are Boolean. Numeric or temporal bounds use the existing type-specific canonical representation. logBase is a finite number greater than 1, is valid only with type=log, and defaults to 10. padding is a finite number in 0 <= padding <= 1. It is valid only on a band, point, or continuous position scale used as a bar base. It removes that fraction from the resolved domain-slot or neighbor-derived interval, centered equally on both sides; padding=1 intentionally produces a degenerate zero-width base rather than invalidating the schema. The default bar-base padding is 0.3. An explicit matching secondary endpoint is authoritative, so padding has no effect on that authored extent.

growMin and growMax are independent finite non-negative fractions for an automatic continuous primary x, y, or z domain. They default to zero and have no artificial upper bound. After resolving the ordinary non-degenerate domain, the client maps it into the scale's continuous coordinate, subtracts growMin * span from an automatic lower side, adds growMax * span to an automatic upper side, and maps back. This gives logarithmic axes multiplicative growth while preserving positivity. An explicit min or max remains authoritative on that side; the corresponding growth property is accepted but has no effect. Growth is not bar width and is independent of padding.

Absent scale types infer as follows:

  • ordinary Number and TimeOnly positions use `linear`;
  • DateOnly and DateTime positions use `time`;
  • categorical point/line/point-cloud positions use `point`;
  • discrete bar bases use `band`, continuous sparse-column bases keep their continuous position scale;
  • categorical paint and shape use `ordinal`; and
  • numeric paint, opacity, size, and stroke width use `linear`.

identity is not valid for x,y,z, facets, or topology. It is valid only for the same bounded literal appearance values admitted by the 2D V1 contract and has no implicit guide.

Automatic domains use every finite, type-valid contributing value before faceting and viewport culling. Secondary values contribute through their primary scale. Explicit min/max/mid, zero inclusion, transform restrictions, DateOnly and DateTime bounds, TimeOnly range, log positivity, sqrt non-negativity, and categorical ordering are identical to ChartScale.

6.1 Shared scales

Outside a physical layer, an unnamed scale is local to one unit. Within one flattened layer, compatible unnamed x, y, or z position scales automatically share by role and union their domains. This is the ordinary multiple-series case and requires no artificial scale identifier. A categorical point scale and band scale are compatible in such a group: the common scale is banded when any contributing bar requires a band, and point/line coordinates use band centers. The same point-to-band promotion applies to an explicitly named positional shared-scale group.

A nonempty id explicitly shares a scale inside the containing Chart3D composition. An explicit different id opts out of automatic layer sharing. Contributors must have the same position/appearance family, effective scalar and presentation class, compatible inferred or explicit type, PhysicalUnit, Format, and output-range class. Explicit domain and logarithm-base properties cannot conflict. Domain contributions union independently of composition traversal order. Shared automatic growMin and growMax resolve independently to the greatest requested fraction, so adding a series never removes requested margin. padding remains local to each bar binding and may differ between series sharing the same position scale.

A same-spelled ChartScale.id is unrelated. A scale never crosses a concat pane. Compatible scales in one flattened layer may share one guide.

7. Chart3DGuide

The grammar is named, closed, and has no position property:

Text
canonical-order = target,source,title,domain,ticks,labels,grid,tickCount,tickStep

target = x | y | z |
         color | fill | stroke |
         opacity | fillOpacity | strokeOpacity |
         size | shape | strokeWidth | strokeDash |
         detail | row | column

source = scale | value | span | none
component = auto | none

target and source are required. Optional title, domain, ticks, labels, and grid values are auto or none. tickCount is a positive safe integer maximum for generated major ticks. tickStep is a positive finite major-tick interval in the target scale's native interval convention: raw mapped numeric units for continuous axes, exponent stride for log, seconds for DateTime and TimeOnly, and days for DateOnly. On a band or point scale it is a positive safe-integer stride through the ordered category domain. tickCount and tickStep are mutually exclusive and are valid only for x/y/z with source=scale. Keys cannot repeat.

7.1 Placement

source=scale and ordinary source=none are declared on the field owning the matching primary scale-bearing role. The target must equal one scale-bearing role on that field and disambiguates a field with multiple implicit roles. The detail exception is described below. A secondary endpoint and u/v cannot own a guide.

source=value and source=span are declared on a direct scalar guide-label field. That field has no scale-bearing Chart3DChannel and no Chart3DScale, though it may additionally carry tooltip, detail, or key.

  • `value` for `x,y,z` creates candidates at the target coordinate of eligible rows.
  • `span` is valid only for `x,y,z` and requires the corresponding x2,y2,z2 binding in the same unit. It describes the explicit continuous interval; a band extent or invented zero is not an authored span.
  • `value` with `target=detail` is declared on one field carrying `detail`. Its candidates are the complete composite detail tuples, not just that field. The client joins the localized component labels in schema order using its localized list grammar. At most one detail guide exists in a unit.
  • `none` with `target=detail` suppresses an otherwise requested detail guide.
  • appearance and facet targets accept only `scale` or `none`.

7.2 Components and inference

Guide Targets Components
3D axis x,y,z title,domain,ticks,labels,grid
Value/span axis labels x,y,z title,domain,ticks,labels,grid
Appearance legend Appearance targets title,ticks,labels
Series legend detail title,ticks,labels
Facet heading row,column title,labels
Suppressed Every target None

Unsupported properties are errors rather than inert. source=none permits no optional component property. A value/span guide defaults title=none and its other supported components to auto. Other guide components default to auto; unsupported components default to none.

Without an explicit declaration, every non-identity primary binding has source=scale with defaults. Identity appearance has source=none. One or more detail bindings infer one composite source=value series legend with default components. An explicit detail guide configures that legend or suppresses it with source=none; it never creates separate legends for individual fields of the composite detail tuple.

3D position axes are placed on camera-visible plot-box edges by a deterministic client layout; the schema does not expose unstable edge or screen-side choices. domain is the axis line, ticks and labels are typed scale candidates, and grid extends them over the applicable plot-box faces. Appearance legends use the responsive full-screen orientation policy in Section 12.5; previews retain the inherited bottom-shell form. Facet headings remain attached to their pane grid in every orientation.

7.3 Position-guide cadence and thinning

An automatic continuous x, y, or z source=scale guide—that is, one without tickStep—adopts the complete deterministic cadence contract in Section 6.4.5 of the general chart specification. Quantitative guides use its closed {1,2,5} * 10^k ladder, temporal guides use its closed typed ladder, and every probe retains its 4096-candidate bound. The resolved domain endpoints bound an ordinary aligned tier but do not enter it unless that lattice generates their exact identity. If no ordinary tier wins, the priorities-plus-resolved-endpoints terminal tier follows. A nondegenerate automatic tier with only one candidate cannot win over that terminal endpoint pair; only a degenerate domain has one automatic raw candidate.

Cadence selection occurs only after the camera, plot box, and viewport have settled. A quantitative guide projects every candidate onto the final camera-visible axis edge and selects the first ladder tier whose adjacent projected anchors meet the general fixed pitch: 64 logical points for a screen-horizontal edge, the greater of 40 logical points and 1.4 times the effective caption-font line height for a screen-vertical edge, or 40 logical points when labels are suppressed. For a quantitative transform, an edge-length-derived candidate count alone is not sufficient.

A temporal guide instead derives its fixed-pitch capacity from that settled projected edge and uses the general ICU-free nominal-width probe. It constructs the exact UTC or local calendar run only once, after selecting the cadence. Calendar or daylight-saving variation may make that run denser than its nominal probe geometry; the selected-run thinning rule below handles the difference without selecting another cadence or replacing it with terminal endpoints. Neither probe performs localization, text formatting, shaping, wrapping, or measurement, and the temporal probe does not construct a calendar, resolve a time zone, or invoke ICU.

tickStep is an authored semantic cadence and therefore bypasses the automatic ladder. It generates only values aligned to that interval in the native convention defined above; it does not synthesize a non-aligned domain endpoint. tickCount cannot accompany tickStep. Without tickStep, tickCount only lowers the automatic tier's viewport-derived candidate capacity; it never asks for exactly that many values, invents evenly spaced samples, or replaces the required nondegenerate terminal endpoint pair. Thus tickCount=1 does not turn a nondegenerate automatic guide into a one-label summary: if its essential terminal candidates cannot fit, ordinary guide fallback applies.

One settled camera-and-viewport state owns one immutable cadence plan. Camera gesture frames transform that plan with the marks and do not iterate the ladder; a changed projected-geometry key selects a replacement only when the camera or viewport settles. Locale and final label width never select a cadence. After selection, the client constructs exactly one bounded visible candidate run and formats the complete run deterministically through the typed rules in the general contract, including its cadence-derived whole-run numeric precision guard. It never formats candidates one at a time or formats a rejected tier.

Final localized text can still require visual thinning. The client tests the complete anchored power-of-two tiers with strides 1,2,4,8,..., anchored at candidate index zero and always retaining the last semantic candidate. It selects the first tier whose final projected label boxes fit with at least four logical points of separation. A removed candidate's enabled label, tick, and grid paint are removed atomically; retained accessibility text remains unabridged and exposes that exact selected semantic run rather than rebuilding a default-capacity run independently of the settled camera. This paint-only thinning never changes or reprobes the selected automatic cadence, never changes an authored tickStep, and never substitutes a different candidate ladder merely because fewer labels remain visible.

7.4 Other numeric guide runs

A continuous numeric appearance source=scale guide adopts the general continuous-legend cadence on its exact 160-logical-point rail. Candidate selection uses the applicable closed automatic ladder and its bounds before any localization or formatting. The client then formats the complete selected candidate run, including every retained essential endpoint, as one set. An appearance legend cannot derive its semantic cadence from an incidental plot axis or format each rail label independently.

Numeric source=value and source=span guides retain their authored row candidate identities and therefore do not invoke an automatic scale ladder. They still format each complete bounded candidate run as one set. For every 3D numeric guide run, a nonempty authored Format is authoritative. Otherwise the client uses the general cadence-derived whole-run precision rule: authored tickStep, selected automatic quantitative cadence, associated scale cadence, or the normalized smallest positive adjacent gap, in that order as applicable. It never starts from a generic 15-significant-digit default and never chooses precision independently per label. The declared value remains in its authored PhysicalUnit; after the one numeric formatting pass, the client attaches that provided unit with the general CLDR rule and performs neither automatic unit conversion nor a second rounding pass. A client must not use a per-value platform-default number conversion for visible or accessibility guide text.

7.5 Layer ownership

Explicitly shared compatible scale IDs and automatically shared unnamed layer position scales merge their implicit guides. Identical explicit guide declarations in a shared group merge and replace the group default; conflicting declarations are invalid. Different-ID scales remain independent.

After shared-guide resolution, one physical 3D layer permits at most one non-suppressed x guide, one y guide, and one z guide. Because the grammar has no axis-position property, multiple visible axes in one family are ambiguous. Independent layered position scales are permitted only when every extra guide is explicitly suppressed. Appearance legends remain independently resolvable under the existing guide resource and layout policy.

Guide text comes from existing typed/localized sources. No Chart3DGuide property contains user-visible text.

8. Chart3DView

Chart3DView is optional and contains unique named properties in this canonical order:

Text
projection,azimuth,elevation,zoom,fov,orbit,
aspectX,aspectY,aspectZ,targetX,targetY,targetZ,pan,zoomEnabled

The closed value contract is:

Property Values Default
projection perspective or orthographic perspective
aspectX,aspectY,aspectZ Positive finite plot-box ratios 1,1,1
targetX,targetY,targetZ Finite normalized plot-space coordinates 0.5,0.5,0.5
azimuth Any finite degrees; canonicalized modulo 360 45
elevation Any finite degrees; effective client value clamped to [-90,90] 30
zoom Any positive finite scalar 1
fov Finite vertical degrees with 0 < fov < 180 45 for perspective
orbit true or false true
pan true or false true
zoomEnabled true or false true

Azimuth canonicalization produces the equivalent value in -180 <= azimuth < 180; for example, 180 becomes -180. Elevation remains an arbitrary finite schema value for wire compatibility, but the client clamps the effective authored/default elevation and every transient update to the closed [-90,90] degree interval before camera evaluation. Values below -90 therefore behave as -90, and values above 90 behave as 90; the authored schema value itself is not rewritten. An orthographic view accepts fov for portable shared declarations but ignores it. Omitted properties use the defaults without being inserted into final schema JSON.

8.1 Placement

A standalone unit may carry one Chart3DView. In a layer, the outer physical layer root is the sole view owner; child units and nested layers cannot declare competing views. An hconcat or vconcat root may carry a default view inherited by each descendant physical scene that has no nearer view. A child unit or outer child layer may replace that complete default, and a nested concat may establish a nearer default for its descendants. This is view inheritance, not camera-state sharing: every concat child remains an independently interactive scene.

A Chart3DView anywhere else, including a row field, hidden field, function, or a child of a physical layer, is invalid.

8.2 Camera semantics

The data coordinate system is right-handed with positive z as up. After scale mapping, x, y, and z span a fitted plot box whose world dimensions have the normalized aspectX:aspectY:aspectZ ratio. The default remains a cube. Target coordinates use this normalized post-scale space: each axis cube runs from 0 to 1, the default 0.5,0.5,0.5 is its center, and finite targets outside the box are permitted.

azimuth rotates around the positive-z axis and elevation moves above or below the x/y plane. Before evaluating the camera, implementations clamp the effective elevation to the closed [-90,90] degree interval. The exact poles are valid camera states; clients do not substitute an epsilon such as 89 or 89.9. At +90 or -90, the client retains authored or transient azimuth and selects the same deterministic projected-positive-y, then positive-x, camera-up fallback on every platform. Continuing an outward vertical orbit at a pole leaves elevation at that pole. Reversing direction moves away immediately without hysteresis, pole reflection, a 180-degree azimuth change, or camera roll.

At zoom=1, the complete resolved plot box fits in the available scene after title, guide, and safe-area layout. Perspective uses fov as its vertical field of view. Orthographic projection ignores perspective foreshortening and derives its fitted extent from the same box. Near and far clipping planes are bounded renderer-derived values and are not schema inputs.

When orbit=true, a view.orbit action updates only transient camera azimuth and elevation, clamping the resulting elevation to [-90,90]. When zoomEnabled=true, a view.zoom action updates transient positive zoom without a fixed schema-level cap. When pan=true, a view.pan action updates the transient target in normalized plot space. orbit=false fixes rotation; pan=false fixes the target; zoomEnabled=false disables every user zoom action while retaining the authored initial zoom. These three properties are independent capability gates, not a selected interaction mode. They do not change projection or initial camera meaning. view.reset returns the complete camera to the effective authored/default view, including its clamped effective elevation. Section 12 defines the one universal mapping from touch, visible controls, keyboard input, and accessibility actions to this vocabulary.

A complete data snapshot does not by itself reset presentation state. The client preserves transient camera orientation, zoom, and target while the presentation-root identity and effective Chart3DView remain compatible. It resets only on an explicit user reset, an authored view change, an incompatible presentation root, or a non-finite retained target. Presentation-root identity is the selected response field path plus its effective chart/composition schema, not the current row contents.

Camera motion never alters scale domains, topology, source identity, tooltip values, accessibility order, or request data.

8.3 Universal client action vocabulary

Every Android and iOS renderer exposes the following semantic actions. The names are normative for cross-platform fixtures and localization mapping, but they are client-internal: they are not schema attributes, protocol messages, or serialized camera data. Every datum or camera action also receives its explicit physical-scene identity; it never resolves an implicit last-touched scene.

Action Meaning
inspect.at Inspect the nearest eligible visible datum at a screen point.
inspect.clear Clear transient datum inspection.
datum.next, datum.previous Traverse eligible source rows independently of occlusion.
view.orbit Apply a continuous screen-space drag to azimuth and clamped elevation without camera roll.
view.orbit.step(left/right/up/down) Rotate the visible scene by one discrete screen-relative step.
view.pan Apply a continuous screen-plane translation to the camera target.
view.pan.step(left/right/up/down) Move the visible scene by one discrete screen-relative step.
view.zoom Apply a continuous positive zoom factor about the current target.
view.zoom.step(in/out) Apply one discrete zoom factor.
view.reset Restore projection, orientation, target, and zoom to the effective authored/default view.
fullscreen.open, fullscreen.close Push or pop the existing full-screen Chart Explorer destination.

A discrete orbit step is 15 degrees and clamps its resulting elevation to [-90,90]. A discrete pan step inverse-projects a screen displacement equal to 10 percent of the physical scene viewport width or height at the current camera-target plane, using the deterministic camera-right/up basis from Section 8.2, then moves the visible scene in the requested screen direction. A discrete zoom-in step multiplies zoom by 1.25; zoom-out divides by 1.25. A client stops before producing a non-positive or non-finite zoom or any other non-finite camera value. Continuous gesture sensitivity and damping may remain platform-native, but direction and action meaning cannot differ.

Client UI uses localized, nontechnical wording: Rotate view, Move view, Zoom in, Zoom out, Reset view, Explore 3D chart, Back, Next data point, and Previous data point. orbit and pan remain schema and internal terms and are not exposed as untranslated user-facing labels.

There is no camera-operation mode, interaction mode, selected rotate-versus-move state, or corresponding schema/wire variable. Pointer count selects the continuous action, and each tap-only or accessibility control names its action explicitly. The existing preview-versus-full-screen navigation state alone determines whether direct chart manipulation is active.

9. Surface and wireframe topology

Surface topology is explicit and resource-safe. The client never triangulates an arbitrary point cloud, runs Delaunay construction, infers nearest neighbors, or executes a formula.

Rows are partitioned first by facet and then by the composite raw detail identity. Each group independently defines one grid.

9.1 Rectangular height grid

When u and v are absent:

  • x and y are the two topology coordinates as well as visual positions;
  • their distinct finite raw values are sorted by canonical typed ordering;
  • every present ordered x/y pair has at most one source row;
  • a missing pair is an explicit hole, while a duplicate pair invalidates the complete 3D chart; and
  • x and y spacing may be non-uniform.

This form represents an ordinary height map z=f(x,y) without copying x/y into separate index fields. A row with a null or non-finite z retains its unique grid slot but contributes no finite vertex, so its incident cells form a hole under Section 9.3.

9.2 Parameter grid

When u and v are present:

  • both are required finite ordinary Numbers (see [scalar compatibility](#52-scalar-compatibility) and surface requirements);
  • each distinct raw domain is sorted by canonical numeric ordering and may be negative, fractional, non-uniform, or sparse;
  • `(u,v)` is unique within the facet/detail group;
  • x, y, and z remain arbitrary continuous positions and need not form a height function; and
  • a missing `(u,v)` pair creates a hole rather than causing neighbor inference.

This form represents non-separable, curvilinear, folded, or parameterized surfaces. The App computes the sample coordinates; u,v describe only adjacency.

9.3 Cells

Let u[i],u[i+1] and v[j],v[j+1] be consecutive entries in the two canonically sorted distinct topology domains. The corresponding cell is:

Text
a = (u[i],   v[j])
b = (u[i+1], v[j])
c = (u[i+1], v[j+1])
d = (u[i],   v[j+1])

A cell exists only when all four vertices are present and have finite mapped x/y/z. surface triangulates it as (a,b,c) and (a,c,d), fixing the diagonal across platforms. Faces are visible from either side; winding does not remove data. wireframe draws only the four grid edges and never exposes the internal triangulation diagonal.

Implementations find cells through checked row/index lookup. They do not allocate an unchecked u-count * v-count matrix. Repeated edges are painted once per grid group. Missing or invalid vertices remove incident cells and break wire paths.

List order does not affect cells. It remains the stable source order for tooltips, accessibility, and equal hit-test ties.

10. Supported families

The supported family names are recipes over the closed primitive set, not additional tokens:

Family V1 representation
3D scatter point with x,y,z
3D line line with x,y,z; detail partitions paths and order orders vertices
3D bars/columns bar using x/y sparse or discrete bases plus z value, the any-orientation two-band shorthand, or a complete explicit cuboid
Bubble 3D point plus numeric size
Surface/height map surface using the rectangular x/y grid
Wireframe wireframe using either grid form
Contours on surface A layer with surface followed by server-emitted line children; contour identity/level uses typed detail and tooltip fields
Non-uniform surface grid Non-uniform x/y coordinates, or arbitrary finite ordered u,v domains for a curvilinear grid
Waterfall/spectrum 3D line with one detail identity per trace and an order field along each spectrum
Impulse/stem 3D stem, optionally layered with point tips
Arbitrary mathematical surface App code evaluates and samples the function, then emits surface; parametric functions use u,v
3D point cloud point, optionally with size,color,detail,key,tooltip
Multiple 3D series detail groups for homogeneous marks or layer for independently typed units and mark kinds

There are intentionally no bubble, contour, pointCloud, waterfall, or formula-expression tokens. Contours are not calculated by the client. An App that changes a formula or sampling density returns another complete typed snapshot.

11. Localization and visible text

3D semantics have no schema-document dependency:

Text
schema + ScriptValue snapshot -> semantic Chart3DSpec
semantic Chart3DSpec + resolved document? + client resources -> presentation

Geometry, topology, grouping, scales, keys, and interaction identities use only schema and raw values. The existing localized package document supplies optional presentation:

Existing source 3D use
Type DisplayName and Description Scene title, help, accessibility context
Field/member localized Name and Description Axis/legend/tooltip captions and help
Enumeration member document Localized category label and help
Libertas object resolver Dynamic names for Device, VirtualDevice, User, Endpoint, or LanDevice identities
Package StringResources Render FormattedText Bytes through LMF1
Client localization catalog Section 8.3 control terms, errors, fallback, camera actions, and accessibility announcement grammar

No Chart3D* property contains user-visible wording.

Every visibly rendered row value preserves its semantic source type:

  • a closed App vocabulary is an Enumeration;
  • App-authored dynamic or parameterized text is FormattedText Bytes;
  • a Libertas system identity remains its typed object reference;
  • only genuine literal domain/user text, such as a proper name or free-form annotation, is a plain String; and
  • a key-only or guide-less identity appearance String is not rendered text.

Localized labels never replace raw identity, change topology, merge categories, or affect ordering. A missing optional label is omitted. A missing essential category/object/formatted-text label invokes the chart failure policy in §12.6 for the complete 3D presentation rather than exposing an internal token.

12. Interaction, accessibility, and fallback

12.1 Inspection and protocol boundary

Hit testing uses final visible, depth-tested geometry. The nearest visible fragment wins; equal-depth ties use flattened layer and row order. A line or wire edge resolves to one of its original endpoint rows. A surface cell resolves to its nearest contributing source vertex. The renderer never synthesizes a request row.

In Chart Explorer, a tap on eligible visible geometry invokes inspect.at; a tap on empty scene space invokes inspect.clear. Movement beyond the native touch-slop threshold cancels the pending tap. Inspection and tooltips retain the original ScriptValue. The projected chart also retains its complete response, carrier, or selected Union variant so hidden transaction fields remain available to typed NextRequest and CopyFrom handling. Inspection is transient presentation state for the current snapshot; the tap itself never sends a protocol request.

Camera movement is presentation-only. It does not send a protocol request, change the selected row, modify source values, or create a persistent App state. A data-changing control uses the normal typed protocol interaction and replaces the snapshot.

12.2 Preview and full-screen ownership

The application-shell rules in Runtime endpoint presentation apply to both 2D and 3D charts. A 3D preview is a live but gesture-neutral summary. Its plot registers no inspection, orbit, pan, pinch, zoom, double-tap, or long-press recognizer. A tap on the preview or its localized Explore 3D chart action invokes fullscreen.open and always pushes full-screen Chart Explorer. Ordinary touches that begin over the preview therefore remain available to the containing workspace scroll.

Only full-screen Chart Explorer owns direct 3D manipulation, inspection, tooltips, and camera controls. The application shell's normal Back affordance invokes fullscreen.close, pops exactly that chart destination, and reveals the retained previous chart or workspace. It is not a second chart control or a separate Close button. There is no engaged inline presentation, interaction mode, or mode variable.

Within Chart Explorer, a pointer sequence belongs to the physical scene in whose final plot bounds it begins. Concat children and facets remain independent scenes; the gesture changes only that scene's transient camera. A layer has one physical scene and therefore one camera. Touches outside a scene remain available to the Chart Explorer shell and its outer scroller.

12.3 Required direct-touch bindings

With screen-reader touch exploration inactive, clients use exactly this V1 mapping inside a full-screen physical scene:

Touch input Semantic action
Tap visible eligible geometry inspect.at for the nearest depth-tested datum.
Tap empty scene space inspect.clear.
One-finger drag view.orbit; the visible scene follows the drag until elevation reaches its closed pole.
Two-finger centroid translation view.pan; the visible scene follows the centroid.
Pinch or spread view.zoom; pinch reduces and spread increases zoom about the current target.
Simultaneous two-finger translation and span change Apply enabled view.pan and view.zoom components together.

One-finger orbit never changes the target or zoom. Two-finger translation never changes azimuth/elevation. Pinch/spread never changes the target, so an off-center pinch cannot bypass pan=false. The two-finger twist component is ignored because V1 has no camera roll.

Double tap, touch-and-hold, edge-origin gestures, and gestures with three or more fingers have no Chart3D V1 action. In particular, double tap never resets the camera, and a client dispatches a recognized single tap without delaying it to await a possible second tap. Touch-and-hold may acquire a future ordinary context-menu meaning, but it cannot be required for inspection or camera control. Operating-system navigation and assistive-technology gestures take priority and clients do not install system-gesture exclusion regions for a chart. A renderer-library default that assigns any of these inputs differently must be overridden.

12.4 Gesture arbitration and continuity

Clients use native touch slop and gesture recognizers and do not capture a sequence merely because its first pointer went down. Control hit targets, assistive technology, and system-edge navigation resolve before chart gestures. For a sequence that reaches the chart:

  • exceeding touch slop cancels a pending tap before camera movement begins;
  • the arrival of a second pointer atomically ends one-finger orbit, cancels a pending tap, and establishes a new centroid and span without a camera jump;
  • any pointer-count change rebases the remaining two-finger transform; after a two-finger transform falls back to one pointer, orbit does not resume until every pointer has lifted and a new sequence begins;
  • the arrival of a third pointer cancels chart recognition without changing the last finite camera state, and recognition cannot restart until every pointer has lifted;
  • `orbit=false` ignores and does not consume one-finger drag rather than remapping it to pan; pan=false ignores the translation component without consuming or remapping it; and zoomEnabled=false ignores the span-change component without consuming or remapping it;
  • a sequence with both pan and zoom disabled remains available to an eligible ancestor recognizer; and
  • cancellation or interruption commits the last finite camera state, produces no inertia after cancellation, and never resets the view or emits a request.

Native damping or post-release inertia is allowed for an otherwise completed orbit or pan, remains presentation-only, stops on the next input, and is disabled when the platform's reduced-motion preference is active. Reset uses an immediate or short non-spatial transition under reduced motion. Auto-rotation remains excluded.

12.5 Visible and accessible controls

Preview exposes only its Configure action when otherwise applicable and the action that opens Chart Explorer. Each independently interactive physical scene owns one scene-local control set in full-screen Chart Explorer; a root, concat, or facet control never silently targets the last-touched scene. Under the rules in Section 4.3, an unfaceted unit or layer has one scene, while every resolved facet is a separate scene. For a root with one physical scene, its scene-local chrome is also the root chrome.

Full-screen scene chrome responds to the current usable viewport after safe areas, system bars, and persistent application chrome. Let its finite positive width and height be W,H. H > W is portrait; H <= W is landscape or square. Clients use this measured viewport classification rather than device orientation notifications, the assigned plot-box aspect ratio, or a stale pre-rotation size. Rotation or window resizing re-evaluates only placement; it does not recreate the physical scene, reset its camera or inspection, replace its settled guide semantics, or reset either outer scroll position.

In portrait, one full-width scene-local control strip immediately precedes the physical scene. The client first attempts one complete row. If it does not fit, the same fixed-order controls remain in one conventional horizontal control strip; it scrolls only on its control axis and does not wrap into multiple tall rows. A directional group remains intact and no control is hidden behind a mode, selector, disclosure, or modal surface. The physical scene follows that strip at its assigned size. Its appearance and detail guides follow the scene in the inherited full-width bottom form.

In landscape or square, the client first attempts one trailing scene-local utility rail beside the physical scene. The rail contains the complete control set first. Below the controls, complete appearance and detail guide blocks use their ordinary horizontal form and greedily pack in semantic order from the physical leading edge to the trailing edge, then wrap downward. The controls retain their fixed reading order and wrap only between complete groups. Position guides remain on their deterministic camera-visible plot-box edges, and facet row/column headings remain attached to their pane grid; neither enters the utility rail.

The client measures the localized controls-width rail with the active accessibility font and platform touch targets. The controls may use that rail when the remaining physical scene retains a finite positive viewport and satisfies the existing M = min(200,C) final post-guide plot-width rule, where C is the plot frame remaining after the utility rail and its gap have been removed. A positive C < 200 is valid when the final plot retains all of C. Guides use the same right rail whenever it can contain at least one complete localized guide block without clipping, shrinking or eliding it. Only when it cannot fit one complete guide do the guides alone fall back to their full-width horizontal flow below the physical-scene/control row; admitted controls remain in the trailing rail. In either placement, guide height never reduces the physical scene's normally assigned full-screen height. Overflow increases the one outer vertical Chart Explorer scroll extent; it never creates a private guide scroller or overlays the scene. Concat children and facets apply this decision independently to their own final pane width and scene-local ownership.

Each scene's safe control area contains, in fixed reading order when applicable: the Rotate view directional group, the Move view directional group, Zoom out, Reset view, then Zoom in. Each directional group contains explicit left, right, up, and down buttons mapped to its corresponding .step action. A disabled capability removes its complete directional or zoom group and leaves no empty slot. Reset view is always present and remains operable as an idempotent action while the transient camera already equals the effective authored/default view. The application shell's Back affordance remains outside every scene-local control set.

Every visible control has a minimum touch target of 44 x 44 points on iOS and 48 x 48 density-independent pixels on Android and remains inside platform safe and system-gesture insets. Controls and guides never overlay the physical scene. They do not reduce its assigned height; only an admitted landscape utility rail may consume its cross-axis width after the required post-guide plot width has been proven.

The directional groups are directly visible tap-only controls. A client never replaces them with a Rotate/Move selector, disclosure, modal surface, or hidden last-used action, so they add no control mode or presentation state. Direction labels describe movement of the visible scene on screen, not internal camera motion.

The same localized actions are exposed through the platform accessibility API:

  • Rotate view left, right, up, and down when `orbit=true`;
  • Move view left, right, up, and down when `pan=true`;
  • Zoom in and Zoom out when `zoomEnabled=true`;
  • Reset view for the explicitly identified physical scene, including while it is already at its effective authored/default view;
  • Next data point and Previous data point for virtualized source traversal; and
  • Explore 3D chart in preview and the normal Back action in Chart Explorer.

Screen readers own their normal touch gestures; direct-touch passthrough is not the only way to operate a chart. Visible buttons and accessibility actions call the same semantic action implementation, and switch control, voice control, keyboard, and pointer activation remain equivalent. Keyboard operation uses the focused named controls and introduces no hidden shortcut or mode. Wheel or trackpad magnification over a physical scene invokes view.zoom when enabled.

After a discrete camera action, or after a continuous gesture and any permitted inertia have reached their final settled state, the client announces exactly one bounded localized summary rather than announcing every animation frame. The summary identifies the physical scene and contains projection, azimuth, elevation, and zoom. When pan changed the target, the same completion announcement includes its normalized x/y/z target as locale-formatted percentages. Angle values are rounded to the nearest degree and zoom is shown with at most two locale-formatted fractional digits.

Accessibility additionally provides:

  • localized scene, series, facet, axis, and tooltip descriptions;
  • a virtualized traversal of eligible source rows independent of occlusion;
  • raw typed values formatted through the same locale, Format, PhysicalUnit, object resolver, and LMF1 pipeline as visible output;
  • a nonvisual indication for every meaning otherwise encoded through paint, size, shape, or depth.

Depth, perspective, lighting, or color can never be the only carrier of domain meaning.

12.6 Fallback

The shared chart failure policy applies to all 3D presentation failures, including unknown future marks, channels, scale/view properties, guide tokens, and unsupported valid features.

13. Security and resources

All metadata and data are untrusted, but Chart3D adds no fixed schema-validity cap for composition depth, unit count, facets, guides, tooltip fields, source rows, point-cloud points, surface vertices, cells, or line vertices. Neither an ECharts-GL nor a SciChart-compatible shape becomes invalid merely because it crosses a Libertas-only count. The enclosing ScriptValue transport owns payload admission, and each client applies its ordinary configurable memory, work, text, and native-renderer budgets. Exceeding a runtime budget causes cancellation and invokes the chart failure policy in §12.6; it never retroactively makes the schema or protocol response invalid.

A superseded source, schema, locale, size, or camera query cancels pending work. Visible level of detail does not change source domains, tooltips, requests, accessibility, or the ordinary data view. Non-finite geometry is suppressed; recoverable allocation or rendering failures follow the chart failure policy in §12.6. Diagnostics remain bounded and do not dump complete payloads.

The contract admits no executable expressions, arbitrary field paths, HTML, URLs, remote images, shader text, material programs, platform objects, model assets, client-side joins, client topology inference, or arbitrary JSON option blobs.

14. Validation

Studio checks the full schema contract after language extraction and dependency resolution. Clients check the effective schema and returned values when presenting a chart. Invalid or unsupported presentation follows the chart failure policy; it does not alter the response payload.

15. Cross-platform rendering and Hub behavior

Android and iOS may use different native graphics libraries, but they share:

  • schema parsing and validation;
  • mark geometry and bar/stem lowering;
  • scale inference, domains, grouping, ordering, and topology;
  • fixed grid triangulation and wire edges;
  • flattened layer order and equal-depth ties;
  • guide inference, suppression, and single-visible-position-axis rules;
  • view defaults, numeric normalization, aspect, target, projection, reset, orbit, pan, zoom, discrete steps, and snapshot-continuity semantics;
  • gesture-neutral preview, full-screen-only manipulation, gesture-to-action assignment, pointer-count arbitration, control vocabulary, and the absence of any rotate/pan mode;
  • raw row ownership for hit testing and typed requests;
  • localization and accessibility meaning;
  • resource accounting and cancellation; and
  • the shared chart failure policy in §12.6, with its implementation choice.

Theme-native fonts, antialiasing, lighting that carries no data meaning, continuous gesture sensitivity, damping, and permitted inertia may differ. Gesture-to-action assignment, visible-scene direction, discrete step sizes, capability gating, control meaning, geometry, scale meaning, topology, identity, literal colors, camera defaults, and supported/unsupported classification may not differ.

16. Deliberate exclusions

V1 excludes:

  • client-evaluated mathematical expressions or arbitrary functions;
  • client-calculated contours, regression, aggregation, bins, stacks, or interpolation;
  • Delaunay/nearest-neighbor or arbitrary triangle-mesh inference;
  • volume, voxel, isosurface, geographic-globe, and 3D model rendering;
  • camera roll, authored motion paths, or auto-rotation;
  • inline chart manipulation, App-authored gesture mappings or sensitivities, double-tap camera reset, and any interaction/rotate/pan mode variable;
  • executable shader/material programs and unverified external texture or image URLs;
  • screen-space annotations or 3D text marks;
  • persistent selection and linked cross-filter expressions;
  • chart-specific incremental mesh/data patch formats; and
  • mixing Chart and Chart3D inside one presented result.

If an App can compute a feature and return explicit typed rows and existing 3D primitives, it does so. A future schema extension is warranted only for a portable presentation or interaction capability that cannot be expressed safely that way.

17. Design references

The vocabulary, supported geometry, and constraints were compared against platform interaction/accessibility guidance and the official ECharts-GL and SciChart contracts. In particular:

Those systems establish the portability floor: Libertas does not impose a semantic restriction that both renderers avoid. Libertas still retains its own typed payload, server-computed safe data, closed metadata, localization, fallback, and cross-platform semantics.

Search Libertas