Skip to main content

LinkageFixed

Struct LinkageFixed 

Source
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(&params)?;
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>

Source

pub const DOF: usize = DOF

Number of runtime parameters this linkage expects (DOF).

See the canonical construction and evaluation example.

Source

pub const N: usize = N

Step-slot capacity of this linkage (N), including the implicit start step.

See the capacity example.

Source

pub const MARKS: usize = MARKS

Mark-slot capacity of this linkage (MARKS).

See the capacity example.

Source

pub const fn start() -> Self

Start a fixed-size linkage with an implicit origin row.

See the canonical construction and evaluation example.

Source

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.

See the canonical construction and evaluation example.

Source

pub const fn dof(&self) -> usize

Return the number of runtime parameters this linkage expects.

See the canonical construction and evaluation example.

Source

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.

Source

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.

Source

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.

Source

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.

See the canonical construction and evaluation example.

Source

pub const fn yaw(self, degrees: f32) -> Self

Rotate about local +Z by a fixed number of degrees.

See the canonical construction and evaluation example.

Source

pub const fn pitch(self, degrees: f32) -> Self

Rotate about local +Y by a fixed number of degrees. See the canonical construction example.

Source

pub const fn roll(self, degrees: f32) -> Self

Rotate about local +X by a fixed number of degrees. See the canonical construction example.

Source

pub const fn forward(self, distance: f32) -> Self

Move along local +X by a fixed linkage distance.

See the canonical construction and evaluation example.

Source

pub const fn left(self, distance: f32) -> Self

Move along local +Y by a fixed linkage distance. See the canonical construction example.

Source

pub const fn up(self, distance: f32) -> Self

Move along local +Z by a fixed linkage distance. See the canonical construction example.

Source

pub const fn pen_up(self) -> Self

Stop emitting strokes for subsequent movement. See the canonical construction example.

Source

pub const fn pen_down(self) -> Self

Emit strokes for subsequent movement. See the canonical construction example.

Source

pub const fn pen_color(self, color: Rgb888) -> Self

Set the color used by subsequent emitted geometry. See the canonical construction example.

Source

pub const fn pen_width(self, width: f32) -> Self

Set the stroke width in linkage units. See the canonical construction example.

Source

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.

Source

pub const fn sphere(self, radius: f32) -> Self

Emit a sphere with a fixed radius at the current pose. See the canonical construction example.

Source

pub const fn yaw_param(self, name: &str, low: f32, high: f32) -> Self

Rotate about local +Z using a named parameter mapped to degrees.

See the canonical construction and evaluation example.

Source

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.

Source

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.

Source

pub const fn forward_param(self, name: &str, low: f32, high: f32) -> Self

Move along local +X using a named parameter mapped to distances.

See the canonical construction and evaluation example.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

pub const fn mark(self, name: &'static str) -> Self

Save the current pose and pen state under a name for later recall.

See the canonical construction and evaluation example.

Source

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);
Source

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);
Source

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.

Source

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]);
Source

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.

Source

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>

Source§

fn from(linkage: &'a LinkageFixed<DOF, MARKS, N>) -> Self

Converts to this type from the input type.
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.
Source§

fn from(linkage: &LinkageFixed<DOF, MARKS, N>) -> Self

Converts to this type from the input type.

Auto Trait Implementations§

§

impl<const DOF: usize, const MARKS: usize, const N: usize> Freeze for LinkageFixed<DOF, MARKS, N>
where [Step; N]: Freeze, [Param; DOF]: Freeze, [&'static str; MARKS]: Freeze,

§

impl<const DOF: usize, const MARKS: usize, const N: usize> RefUnwindSafe for LinkageFixed<DOF, MARKS, N>

§

impl<const DOF: usize, const MARKS: usize, const N: usize> Send for LinkageFixed<DOF, MARKS, N>
where [Step; N]: Send, [Param; DOF]: Send, [&'static str; MARKS]: Send,

§

impl<const DOF: usize, const MARKS: usize, const N: usize> Sync for LinkageFixed<DOF, MARKS, N>
where [Step; N]: Sync, [Param; DOF]: Sync, [&'static str; MARKS]: Sync,

§

impl<const DOF: usize, const MARKS: usize, const N: usize> Unpin for LinkageFixed<DOF, MARKS, N>
where [Step; N]: Unpin, [Param; DOF]: Unpin, [&'static str; MARKS]: Unpin,

§

impl<const DOF: usize, const MARKS: usize, const N: usize> UnsafeUnpin for LinkageFixed<DOF, MARKS, N>
where [Step; N]: UnsafeUnpin, [Param; DOF]: UnsafeUnpin, [&'static str; MARKS]: UnsafeUnpin,

§

impl<const DOF: usize, const MARKS: usize, const N: usize> UnwindSafe for LinkageFixed<DOF, MARKS, N>
where [Step; N]: UnwindSafe, [Param; DOF]: UnwindSafe, [&'static str; MARKS]: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Az for T

Source§

fn az<Dst>(self) -> Dst
where T: Cast<Dst>,

Casts the value.
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<Src, Dst> CastFrom<Src> for Dst
where Src: Cast<Dst>,

Source§

fn cast_from(src: Src) -> Dst

Casts the value.
Source§

impl<T> CheckedAs for T

Source§

fn checked_as<Dst>(self) -> Option<Dst>
where T: CheckedCast<Dst>,

Casts the value.
Source§

impl<Src, Dst> CheckedCastFrom<Src> for Dst
where Src: CheckedCast<Dst>,

Source§

fn checked_cast_from(src: Src) -> Option<Dst>

Casts the value.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> OverflowingAs for T

Source§

fn overflowing_as<Dst>(self) -> (Dst, bool)
where T: OverflowingCast<Dst>,

Casts the value.
Source§

impl<Src, Dst> OverflowingCastFrom<Src> for Dst
where Src: OverflowingCast<Dst>,

Source§

fn overflowing_cast_from(src: Src) -> (Dst, bool)

Casts the value.
Source§

impl<T> SaturatingAs for T

Source§

fn saturating_as<Dst>(self) -> Dst
where T: SaturatingCast<Dst>,

Casts the value.
Source§

impl<Src, Dst> SaturatingCastFrom<Src> for Dst
where Src: SaturatingCast<Dst>,

Source§

fn saturating_cast_from(src: Src) -> Dst

Casts the value.
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> UnwrappedAs for T

Source§

fn unwrapped_as<Dst>(self) -> Dst
where T: UnwrappedCast<Dst>,

Casts the value.
Source§

impl<Src, Dst> UnwrappedCastFrom<Src> for Dst
where Src: UnwrappedCast<Dst>,

Source§

fn unwrapped_cast_from(src: Src) -> Dst

Casts the value.
Source§

impl<T> WrappingAs for T

Source§

fn wrapping_as<Dst>(self) -> Dst
where T: WrappingCast<Dst>,

Casts the value.
Source§

impl<Src, Dst> WrappingCastFrom<Src> for Dst
where Src: WrappingCast<Dst>,

Source§

fn wrapping_cast_from(src: Src) -> Dst

Casts the value.