Skip to main content
Back to Journal
user@argobox:~/journal/2026-02-26-knowledge-graph-physics
$ cat entry.md

Knowledge Graph Physics: Bounding Boxes and Settle Detection

○ NOT REVIEWED

Knowledge Graph Physics: Bounding Boxes and Settle Detection

The Problem

The blog knowledge graph at /blog/ is a nice visual. It shows relationships between articles—which posts mention the same projects, which ones build on similar ideas. The layout was a wide rectangle, about 50vh tall.

But in practice, people want to use it. Click nodes, explore connections. The physics simulation would run for a few seconds, then still be settling when they started interacting. Nodes would drift around when they tried to read labels. Zooming and panning would jitter because physics was still running underneath.

You'd see: position → click → position shifts because physics nudged something → position shifts again. Jarring.

The Solution

Two features added to the upstream Tendril library:

Bounds Clamping

The graph now respects viewport boundaries. Nodes that drift toward the edge get a soft bounce back:

// After position integration
if (node.x < boundingBox.x1) {
  node.x = boundingBox.x1;
  node.vx *= -0.3;  // soft bounce, 30% reverse velocity
}

It's not a hard wall. It's more like bumping into a cushion. The node comes back into the viewport smoothly, doesn't snap, doesn't create energy.

Tested different bounce coefficients: 0.1 felt too sticky, 0.5 was too bouncy. 0.3 feels natural.

Settle Detection

More important: the graph now detects when physics has calmed down and auto-disables.

Tracks total velocity across all nodes. After 30 frames of "calm" (velocity below threshold), automatically:

  1. Calls cy.fit() to auto-zoom/pan the graph into view
  2. Disables physics engine
  3. From then on, zooming and panning are pure camera operations—physics doesn't run

Zooming and panning become responsive instantly. No jitter. No nodes drifting mid-interaction.

There's an onSettle callback so consumers can react when the graph stabilizes. And enablePhysics(true) resets the counter so you can re-run the physics if you want.

The Integration

Converted the blog knowledge graph to use a perfect square:

aspect-ratio: 1/1;
width: min(90vw, 800px);
margin: 0 auto;

Tighter layout works better with the physics tuning. Nodes are more constrained, forces feel more balanced.

Tuned the physics parameters:

  • centerForce: 0.12 (was 0.05) — Stronger pull toward center
  • repelForce: 2000 (was 3500) — Nodes push each other less (they were too spread out before)
  • linkForce: 0.2 (was 0.3) — Edges pull less aggressively
  • linkDistance: 160 (was 200) — Edges want to be shorter in the tighter square
  • damping: 0.82 (was 0.85) — Slightly more friction to settle faster
  • boundingBox: true — Enable bounds clamping
  • settleThreshold: 0.5 — New parameter for settle detection sensitivity

Committed to Tendril. Then committed the integration changes to ArgoBox. Both repos pushed.

Why This Matters

The knowledge graph was a cool visual that wasn't actually functional for interaction. Now it's stable. You can hover over nodes, read labels without them moving, click links. The physics runs until the system is calm, then stops.

This is one of those quality-of-life improvements that's invisible until you use it. Before: jittery, distracting, makes you wait. After: clicks feel responsive, reading feels natural, interaction is smooth.

The Deeper Pattern

This kind of work—adding polish features to open-source libraries, then integrating them into product—requires living upstream. Can't just use Tendril as a black box. Had to understand the physics engine, see where it was weak, add features, test them locally, push upstream, then bring the improvements back to the product.

Takes more time than just hacking the consumer product directly. But it means the improvements compound. Someone else building with Tendril gets the same bounds clamping and settle detection. The library gets stronger. The product gets stronger.

Still Saturday Evening

Started this at 8 PM. Finished at 11:30. Three and a half hours of physics tweaking, testing, integrating, documenting.

It's the kind of work you do on a weekend because it's not urgent but it's been bothering you. The graph has been flickering for weeks. Saturday evening finally had space for it.

Now it's done. The knowledge graph is stable. Tendril is better. Everything on top of Tendril gets the benefit.


Status: Bounds clamping and settle detection live in Tendril v0.3.0. Blog knowledge graph switched to square layout with tuned physics. No more jitter. Graph usable for real interaction.