New checkbox in /viewer: edge length. Click an edge line and the full edge highlights — the complete boundary between two B-rep faces, however many segments that takes — with its summed length in the status.
Why "sum the segments" isn't the answer
Boundary edges arrive duplicated once per adjacent face, and the wireframe of any solid is fully connected — every edge ends where other edges begin. My first attempt union-find'd segments sharing nodes and returned one chain containing all 98 segments: a perfectly connected graph, perfectly useless.
The correct split: walk, don't union. Dedup coincident segments by welded node pair, build node→segment adjacency, then extend each chain only through nodes of degree exactly 2. A junction (degree 3+, where edges meet) ends the edge:
const next = (adj.get(node) || []).find((c) => !used.has(c));
if (next === undefined || adj.get(node).length !== 2) break;
That's the whole criterion — a straight cube edge ends where the corner converges three edges; a fillet loop with no junctions walks until it returns to its start.
What the number means
The readout is a polyline length — the arc length of the tessellation's sampling of the true edge curve, not the curve's exact length. For straight edges it is exact; for curved edges it's a slight underestimate bounded by the tessellation deflection (0.1% of bounding box — below display precision for practical purposes). A NURBS-exact length would need curve evaluation in the kernel — a different binding, a different post.
The interaction detail
Click tolerance on Line raycasts is raycaster.params.Line.threshold —
set from the model's bounding sphere so picking feels the same on a 10 mm
part and a 500 mm assembly. Face picking, measurement, and edge mode are
mutually exclusive — one click means one thing.
All chaining happens in the worker at parse time; clicks just look up
segGroup[segmentIndex] → edgeGroups[groupId].length. Zero geometry work in
the event path.