pub fn helix_sample_points(
axis_origin: Vec3,
axis_direction: Vec3,
reference: Option<Vec3>,
start_radius: f64,
end_radius: f64,
pitch: f64,
turns: f64,
start_angle: f64,
left_handed: bool,
) -> Result<(Vec<Vec3>, Vec<f64>), String>Expand description
Helical sweep (§5.7): sweep a CLOSED PLANAR profile loop along a helix of
helix_radius about the axis through axis_origin with direction
axis_direction, rising pitch per revolution for turns revolutions.
Sample a helix — turns revolutions about axis_direction from
axis_origin, starting at angle start_angle (radians, measured from the
axis frame’s u) and rising pitch per turn, the radius running linearly
from start_radius to end_radius — uniformly in angle: 64 stations per
turn (at least 9, at most 4097 in total, so beyond 64 turns the per-turn
density thins). Returns the points and their chord parameters s ∈ [0,1]
(uniform-in-angle IS chord-length for a constant-radius helix, which is
what the averaged-knot interpolation assumes). left_handed winds the
angle the other way. The axis frame is w = axis, u = the component of
reference perpendicular to the axis (so angle zero points AT the
reference — the helix feature’s local +X, or its start point), falling
back to w.perpendicular() when there is no usable reference, and
v = w × u. Shared by sweep_profile_helix and the HX feature, so the
coil a sweep builds and the edge a helix feature publishes agree exactly.
Errors on a degenerate axis, non-finite inputs, turns ≤ 0, more than 256
turns, a negative radius or pitch, or a helix that is a single point (both
radii AND the pitch zero).