pub struct LinkageFixed<const DOF: usize, const MARKS: usize, const N: usize> { /* private fields */ }Expand description
An allocation-free linkage with compile-time-fixed capacities.
LinkageFixed stores linkage steps and parameters in fixed-size arrays,
enabling const construction and evaluation without allocation. Use the
fluent DSL methods to define a linkage in firmware or other no_std code.
The three const capacities are independent: DOF is the number of runtime
parameters, MARKS is the number of named pose slots, and N is the step
storage capacity. N includes the implicit Step::Start step; the active
count is step_count. There is no built-in 256-step
limit: choose N for the asset, or let linkage_file! measure an external
.lb.rs asset and generate the fixed storage.
Use LinkageFixed directly for small source-defined linkages. Use
linkage_file! for a saved linkage asset, then obtain its
LinkageView for evaluation and rendering. The canonical example below
shows construction, parameter evaluation, marks, and visible geometry.
§Fluent operations
This compact example exercises the fixed and parameterized construction methods.
const LINKAGE: LinkageFixed<1, 1, 32> = LinkageFixed::start()
.define_param("value", 0.5)
.yaw(15.0)
.pitch(5.0)
.roll(2.0)
.forward(1.0)
.left(1.0)
.up(1.0)
.pen_up()
.pen_down()
.pen_color(Rgb888::new(0, 0, 255))
.pen_width(0.25)
.disk(0.25)
.sphere(0.5)
.yaw_param("value", -15.0, 15.0)
.pitch_param("value", -5.0, 5.0)
.roll_param("value", -2.0, 2.0)
.forward_param("value", 0.0, 1.0)
.left_param("value", 0.0, 1.0)
.up_param("value", 0.0, 1.0)
.disk_param("value", 0.1, 0.5)
.sphere_param("value", 0.1, 0.5)
.mark("saved")
.restore("saved");
assert!(LINKAGE.step_count() > 1);§Canonical construction and evaluation
const LINKAGE: LinkageFixed<1, 1, 8> = LinkageFixed::start()
.define_param("reach", 0.5)
.forward_param("reach", 1.0, 3.0)
.mark("tip")
.pen_color(Rgb888::new(0, 0, 255))
.disk(0.25);
const ACTIVE_STEPS: usize = LINKAGE.step_count();
const _: () = assert!(ACTIVE_STEPS < LinkageFixed::<1, 1, 8>::N);
const _: () = assert!(LinkageFixed::<1, 1, 8>::DOF == 1);
const _: () = assert!(LinkageFixed::<1, 1, 8>::MARKS == 1);
let view = LINKAGE.view();
let params = [0.5];
let mut items = view.draw_items_3d(¶ms)?;
while items.next().is_some() {}
let final_pose = items.final_pose();
assert!(final_pose.position().is_close_to(&Vec3::from([2.0, 0.0, 0.0]), 1e-5));
let marked_pose = items.pose_by_mark_name("tip")?;
assert!(marked_pose.position().is_close_to(&Vec3::from([2.0, 0.0, 0.0]), 1e-5));
assert_eq!(view.draw_item_3d_count(), 2);Parameter indexes are identities. Parameter names are labels/selectors and may
be duplicated. Use freeze_param_index and retain_param_indexes for precise
specialization. Name-based freezing requires exactly one matching parameter,
while name-based retaining keeps all slots matching each requested name. Freeze
raw values are operation values, not normalized slider values: rotations use
degrees, and distances/radii use linkage units.
Implementations§
Source§impl<const DOF: usize, const MARKS: usize, const N: usize> LinkageFixed<DOF, MARKS, N>
impl<const DOF: usize, const MARKS: usize, const N: usize> LinkageFixed<DOF, MARKS, N>
Sourcepub const N: usize = N
pub const N: usize = N
Step-slot capacity of this linkage (N), including the implicit start step.
See the capacity example.
Sourcepub const MARKS: usize = MARKS
pub const MARKS: usize = MARKS
Mark-slot capacity of this linkage (MARKS).
See the capacity example.
Sourcepub const fn view(&self) -> LinkageView<'_, DOF, MARKS>
pub const fn view(&self) -> LinkageView<'_, DOF, MARKS>
Create a borrowed view for evaluation and rendering.
The view erases step capacity N while preserving linkage-parameter
count DOF.
All evaluation methods (poses, draw_items_3d, etc.) operate on the view.
Sourcepub const fn step_count(&self) -> usize
pub const fn step_count(&self) -> usize
Return the number of steps actually used (including the implicit start step).
Use this to discover the correct N after building with an oversized capacity.
See the capacity example.
Sourcepub const fn param_count(&self) -> usize
pub const fn param_count(&self) -> usize
Return the number of parameters actually defined.
This is useful when discovering capacities from an intentionally oversized
declaration; linkage_file! performs the same measurement for assets.
Use this to discover the correct DOF after building with an oversized capacity.
See the capacity example.
Sourcepub const fn mark_count(&self) -> usize
pub const fn mark_count(&self) -> usize
Return the number of distinct mark names actually used.
Use this to discover the correct MARKS after building with an oversized capacity.
See the capacity example.
Sourcepub const fn define_param(self, name: &'static str, default: f32) -> Self
pub const fn define_param(self, name: &'static str, default: f32) -> Self
Define a named runtime parameter.
Duplicate names are allowed; later definitions shadow earlier ones when
a DSL method like yaw_param looks up the name.
Sourcepub const fn yaw(self, degrees: f32) -> Self
pub const fn yaw(self, degrees: f32) -> Self
Rotate about local +Z by a fixed number of degrees.
Sourcepub const fn pitch(self, degrees: f32) -> Self
pub const fn pitch(self, degrees: f32) -> Self
Rotate about local +Y by a fixed number of degrees. See the canonical construction example.
Sourcepub const fn roll(self, degrees: f32) -> Self
pub const fn roll(self, degrees: f32) -> Self
Rotate about local +X by a fixed number of degrees. See the canonical construction example.
Sourcepub const fn forward(self, distance: f32) -> Self
pub const fn forward(self, distance: f32) -> Self
Move along local +X by a fixed linkage distance.
Sourcepub const fn left(self, distance: f32) -> Self
pub const fn left(self, distance: f32) -> Self
Move along local +Y by a fixed linkage distance. See the canonical construction example.
Sourcepub const fn up(self, distance: f32) -> Self
pub const fn up(self, distance: f32) -> Self
Move along local +Z by a fixed linkage distance. See the canonical construction example.
Sourcepub const fn pen_up(self) -> Self
pub const fn pen_up(self) -> Self
Stop emitting strokes for subsequent movement. See the canonical construction example.
Sourcepub const fn pen_down(self) -> Self
pub const fn pen_down(self) -> Self
Emit strokes for subsequent movement. See the canonical construction example.
Sourcepub const fn pen_color(self, color: Rgb888) -> Self
pub const fn pen_color(self, color: Rgb888) -> Self
Set the color used by subsequent emitted geometry. See the canonical construction example.
Sourcepub const fn pen_width(self, width: f32) -> Self
pub const fn pen_width(self, width: f32) -> Self
Set the stroke width in linkage units. See the canonical construction example.
Sourcepub const fn disk(self, radius: f32) -> Self
pub const fn disk(self, radius: f32) -> Self
Emit a filled disk with a fixed radius at the current pose. See the canonical construction example.
Sourcepub const fn sphere(self, radius: f32) -> Self
pub const fn sphere(self, radius: f32) -> Self
Emit a sphere with a fixed radius at the current pose. See the canonical construction example.
Sourcepub const fn yaw_param(self, name: &str, low: f32, high: f32) -> Self
pub const fn yaw_param(self, name: &str, low: f32, high: f32) -> Self
Rotate about local +Z using a named parameter mapped to degrees.
Sourcepub const fn pitch_param(self, name: &str, low: f32, high: f32) -> Self
pub const fn pitch_param(self, name: &str, low: f32, high: f32) -> Self
Rotate about local +Y using a named parameter mapped to degrees. See the canonical construction example.
Sourcepub const fn roll_param(self, name: &str, low: f32, high: f32) -> Self
pub const fn roll_param(self, name: &str, low: f32, high: f32) -> Self
Rotate about local +X using a named parameter mapped to degrees. See the canonical construction example.
Sourcepub const fn forward_param(self, name: &str, low: f32, high: f32) -> Self
pub const fn forward_param(self, name: &str, low: f32, high: f32) -> Self
Move along local +X using a named parameter mapped to distances.
Sourcepub const fn left_param(self, name: &str, low: f32, high: f32) -> Self
pub const fn left_param(self, name: &str, low: f32, high: f32) -> Self
Move along local +Y using a named parameter mapped to distances. See the canonical construction example.
Sourcepub const fn up_param(self, name: &str, low: f32, high: f32) -> Self
pub const fn up_param(self, name: &str, low: f32, high: f32) -> Self
Move along local +Z using a named parameter mapped to distances. See the canonical construction example.
Sourcepub const fn disk_param(self, name: &str, low: f32, high: f32) -> Self
pub const fn disk_param(self, name: &str, low: f32, high: f32) -> Self
Emit a disk whose radius comes from a named parameter. See the canonical construction example.
Sourcepub const fn sphere_param(self, name: &str, low: f32, high: f32) -> Self
pub const fn sphere_param(self, name: &str, low: f32, high: f32) -> Self
Emit a sphere whose radius comes from a named parameter. See the canonical construction example.
Sourcepub const fn restore(self, name: &'static str) -> Self
pub const fn restore(self, name: &'static str) -> Self
Restore the pose and pen state saved by an earlier named mark. See the canonical construction example.
Sourcepub const fn mark(self, name: &'static str) -> Self
pub const fn mark(self, name: &'static str) -> Self
Save the current pose and pen state under a name for later recall.
Sourcepub const fn freeze_param_index<const OUT_DOF: usize>(
self,
param_index: usize,
raw_value: f32,
) -> LinkageFixed<OUT_DOF, MARKS, N>
pub const fn freeze_param_index<const OUT_DOF: usize>( self, param_index: usize, raw_value: f32, ) -> LinkageFixed<OUT_DOF, MARKS, N>
Freeze exactly one parameter slot by index at a raw operation value.
Parameter indexes are identities. Parameter names are labels and may be
duplicated. raw_value is the fixed operation value, not a normalized
slider value: rotations use degrees, while translations, radii, and widths
use linkage units. The raw value must be inside every referenced step range
for this slot; out-of-range values panic, including during const evaluation.
§Examples
const LINKAGE: LinkageFixed<2, 0, 6> = LinkageFixed::start()
.define_param("angle", 0.5)
.define_param("distance", 0.5)
.yaw_param("angle", -180.0, 180.0)
.forward_param("distance", 0.0, 10.0);
const FROZEN: LinkageFixed<1, 0, 6> = LINKAGE.freeze_param_index(0, 90.0);Sourcepub const fn freeze_param_name<const OUT_DOF: usize>(
self,
name: &'static str,
raw_value: f32,
) -> LinkageFixed<OUT_DOF, MARKS, N>
pub const fn freeze_param_name<const OUT_DOF: usize>( self, name: &'static str, raw_value: f32, ) -> LinkageFixed<OUT_DOF, MARKS, N>
Freeze the uniquely named parameter slot at a raw operation value.
This is a convenience selector over freeze_param_index.
It panics if no parameter has name, or if more than one parameter has
that name. Use index-based freezing when names are duplicated.
§Examples
const LINKAGE: LinkageFixed<2, 0, 6> = LinkageFixed::start()
.define_param("angle", 0.5)
.define_param("distance", 0.5)
.yaw_param("angle", -180.0, 180.0)
.forward_param("distance", 0.0, 10.0);
const FROZEN: LinkageFixed<1, 0, 6> = LINKAGE.freeze_param_name("angle", 90.0);Sourcepub const fn freeze_param_index_at_default<const OUT_DOF: usize>(
self,
param_index: usize,
) -> LinkageFixed<OUT_DOF, MARKS, N>
pub const fn freeze_param_index_at_default<const OUT_DOF: usize>( self, param_index: usize, ) -> LinkageFixed<OUT_DOF, MARKS, N>
Freeze exactly one parameter slot by index at its normalized default.
This is useful for specialization from declared defaults. Unlike
freeze_param_index, one default-normalized
parameter can legally feed steps with different raw ranges.
See the parameter specialization example.
Sourcepub const fn retain_param_indexes<const OUT_DOF: usize>(
self,
indexes: &[usize],
) -> LinkageFixed<OUT_DOF, MARKS, N>
pub const fn retain_param_indexes<const OUT_DOF: usize>( self, indexes: &[usize], ) -> LinkageFixed<OUT_DOF, MARKS, N>
Retain exactly the listed parameter slots and freeze all others at their defaults.
Retained slots are reindexed densely in original parameter-slot order, not caller-list order. Duplicate indexes and out-of-bounds indexes panic.
See the parameter specialization example.
§Examples
const LINKAGE: LinkageFixed<3, 0, 8> = LinkageFixed::start()
.define_param("angle", 0.5)
.define_param("pitch", 0.5)
.define_param("distance", 0.5)
.yaw_param("angle", -180.0, 180.0)
.pitch_param("pitch", -90.0, 90.0)
.forward_param("distance", 0.0, 10.0);
const RETAINED: LinkageFixed<1, 0, 8> = LINKAGE.retain_param_indexes(&[2]);Sourcepub const fn retain_param_names<const OUT_DOF: usize>(
self,
names: &[&'static str],
) -> LinkageFixed<OUT_DOF, MARKS, N>
pub const fn retain_param_names<const OUT_DOF: usize>( self, names: &[&'static str], ) -> LinkageFixed<OUT_DOF, MARKS, N>
Retain parameters selected by name and freeze all others at their defaults.
Each requested name must exist. If a requested name matches multiple parameter slots, all matching slots are retained. Duplicate names in the requested name list panic.
See the parameter specialization example.
Sourcepub const fn combine<const DOF2: usize, const MARKS2: usize, const DOF_OUT: usize, const MARKS_OUT: usize, const N_OUT: usize>(
self,
other: LinkageView<'_, DOF2, MARKS2>,
) -> LinkageFixed<DOF_OUT, MARKS_OUT, N_OUT>
pub const fn combine<const DOF2: usize, const MARKS2: usize, const DOF_OUT: usize, const MARKS_OUT: usize, const N_OUT: usize>( self, other: LinkageView<'_, DOF2, MARKS2>, ) -> LinkageFixed<DOF_OUT, MARKS_OUT, N_OUT>
Append another linkage’s steps after this one’s, merging their parameters.
The caller must supply the output sizes as const generics since Rust cannot
compute DOF + DOF2 as a const expression yet — follow the same pattern as
LedLayout::combine_h. A compile-time assertion verifies the sizes are correct.
The other linkage’s implicit Start step is skipped so evaluation continues
from wherever self ends rather than resetting to the origin.
For a complete construction and evaluation route, see the canonical example.
§Examples
const FIRST: LinkageFixed<0, 0, 4> = LinkageFixed::start().forward(1.0);
const SECOND: LinkageFixed<0, 0, 4> = LinkageFixed::start().left(2.0);
const COMBINED: LinkageFixed<0, 0, 8> = FIRST.combine(SECOND.view());
let pose = COMBINED.view().final_pose(&[])?;
assert!(pose.position().is_close_to(&Vec3::from([1.0, 2.0, 0.0]), 1e-5));Trait Implementations§
Source§impl<'a, const DOF: usize, const MARKS: usize, const N: usize> From<&'a LinkageFixed<DOF, MARKS, N>> for LinkageView<'a, DOF, MARKS>
impl<'a, const DOF: usize, const MARKS: usize, const N: usize> From<&'a LinkageFixed<DOF, MARKS, N>> for LinkageView<'a, DOF, MARKS>
Source§fn from(linkage: &'a LinkageFixed<DOF, MARKS, N>) -> Self
fn from(linkage: &'a LinkageFixed<DOF, MARKS, N>) -> Self
Source§impl<const DOF: usize, const MARKS: usize, const N: usize> From<&LinkageFixed<DOF, MARKS, N>> for LinkageBuf<DOF, MARKS>
Available on crate feature alloc only.
impl<const DOF: usize, const MARKS: usize, const N: usize> From<&LinkageFixed<DOF, MARKS, N>> for LinkageBuf<DOF, MARKS>
alloc only.