Skip to main content

miter_extension

Function miter_extension 

Source
pub fn miter_extension(
    width: f32,
    prev: [f32; 2],
    vertex: [f32; 2],
    next: [f32; 2],
) -> f32
Expand description

The extension a joined end needs to reach its corner’s point: the miter length at vertex, where the chain arrives from prev and leaves for next, clamped to MITER_LIMIT half-widths (ADR-0158).

§The expression, and why it carries no trigonometry

For an interior angle theta the miter is width / sin(theta / 2). Writing d1, d2 for the two unit directions, the turn between them is theta_turn = pi - theta, so

sin(theta / 2) = cos(theta_turn / 2) = sqrt((1 + d1 · d2) / 2)

— a dot product and a square root, with no acos to lose precision near the straight case and no branch on the turn’s sign. A straight joint has d1 · d2 = 1 and yields exactly width, which is the flat half-width, so a collinear chain is byte-identical to one that extends by width.

§Homogeneous of degree 1 in width

Both width / sin(theta / 2) and the clamp MITER_LIMIT * width scale linearly, so miter(c * w) == c * miter(w) and the clamp cannot be engaged at one width and not another. That is what lets the cached producers compute this against PLACEHOLDER_WIDTH at configure and have LineInstance::styled carry it to this frame’s width by the ratio. Both are crate-private, so this names them rather than linking them. theta survives that too: every transform between a producer and the shader — uniform scale, rotation, reflection, the mirror replication, normalize_fit — is a similarity, and a similarity preserves angles.

§Degenerate input

A zero-length arm has no direction, and a chain that doubles back exactly (d1 · d2 = -1) has no reachable point. Both fall back to width, the flat half-width — which is the same value a corner past MITER_LIMIT takes, so the degenerate case is the limit case rather than a separate rule.