Files
vectorcraft/crates/brush/src
Muhammad Saad 18e916ddf5 Pattern Brush: decide straightness from the track, not from samples (#3926 review)
Messhias is right that a sampled check cannot promise a run is straight, and my
own write-up overstated what the grid did: I said the fit was "used only where
it reproduces the real map", which five sample positions cannot establish. A
bend narrower than the sample spacing passes between the samples, and the grid
then approves an affine that is simply wrong.

It is not a theoretical gap. A zigzag of amplitude 4 pt and half-period 20 pt,
turning 11.3 degrees (under CORNER_DEG, so the vertices are not corners and
their tangents blend flat), lands its y = 0 vertices exactly on the five sample
positions. All 25 grid points then agree with the affine to the last digit while
the art between them is thrown 4.000 pt off, against the 0.0613 pt tolerance the
grid believed it was enforcing: 65 times over, measured, not estimated.

`Track::is_straight(s0, s1)` reads the answer off the track instead. A bend in
the span is two segment directions that differ, so no bend can hide in it
whatever its size. It also checks the vertex tangents, because `frame` blends
them across a segment unless the vertex is a corner, so a neighbour outside the
span can bend the tangent inside it: directions alone would call `d, d, e`
straight over the first two segments and be wrong. It fails closed on a closed
track's seam, a non-finite bound and a track with no segments.

`AlongMap::is_linear` covers the other half: Between Guides bends the arc-length
map itself, which no amount of looking at the track would reveal.

The grid stays, demoted to a second opinion that can reject and never admit, and
`affine_fit`'s doc comment now says that rather than claiming to be the gate.

Tests. `a_bend_shorter_than_the_sample_grid_is_still_a_bend` builds the zigzag
above, asserts the sampled check accepts it, measures how far out the approved
affine is, and then asserts the track-based gate refuses it; end to end through
`bend` it asserts the aliased bend is subdivided while a genuinely straight run
of the same span keeps the tile's four anchors. Restoring the sampled gate reds
it with `the aliased bend is subdivided, not affine-mapped: 4 anchors`, so the
old code really did lay a flat tile along a waving track.

`straightness_is_read_off_the_track_not_sampled` covers the predicate directly:
collinear segments and their extrapolation, a 0.2 pt detour, a span around it
and a span before it, the blended-tangent case above, the closed seam and a NaN
bound. Writing it caught a bug in my own guard: `f64::min` discards a NaN rather
than propagating it, so `is_straight(NAN, 10.0)` was reporting straight until
the finiteness check moved ahead of the min/max.
2026-10-29 13:00:45 +07:00
..