Task 4 of 6

From Seeds to Distances

The finished field already is a distance field — you just have to ask it. Every cell knows where its nearest seed is, so the distance to that seed is one subtraction and one square root away, in a single extra pass with no memory of its own.

This is where carrying the position rather than the distance pays off twice over. Had the cells accumulated distances, every pass would have compounded whatever rounding the last one introduced. Carrying coordinates means the distance is computed once, at the end, from two exact integers — so the field is as accurate as the seed assignment is, and no more approximate than that.

Goal: write distance — unpack each cell's seed and return the Euclidean distance from the cell to it.

Requirements

Hint 1 — the same unpack as the flood pass

Nothing new: it is the two lines you already wrote inside the loop, applied once.

const sy = Math.floor(id / this.constants.n);
const sx = id - sy * this.constants.n;
Hint 2 — the whole body
return Math.sqrt((sx - x) * (sx - x) + (sy - y) * (sy - y));

A seed cell measures 0 from itself, which is exactly right — those are the black pinpricks in the rendered field.

Same idea elsewhere

Distance fields are the workhorse texture of real-time graphics: glyph rendering (Valve's signed-distance text), outlines and glows, soft particle collision, path planning and morphological dilation are all "threshold a distance field". Every one of them wants the field regenerated per frame from changing input, which is why this algorithm — not the asymptotically better sweep — is the one that ships.

All tasks in Jump Flooding: Voronoi in log n Passes

  1. What a Cell Has to Carry
  2. One Pass, One Stride
  3. The Halving Ladder
  4. From Seeds to Distances
  5. A Signed Distance Field From a Bitmap
  6. Payoff: Measure the Lie

This page is an interactive exercise — the editor, the GPU runner and your saved progress need JavaScript. The text above is the full brief.