Möbius Transforms, Poincaré Disks, Escher's Fish, and More

I was halfway through *Gödel, Escher, Bach* (I lied, I've finished a solid 50 pages max over the last 6 years), sending my friends voice notes about how every second brain app is basically a fancy text editor with a graph view bolted on. Obsidian, Roam, and Logseq all promise to externalize your thinking, and then they give you a flat plane to dump notes on. You scroll. You zoom. You search. Your brain does all the spatial work the tool was supposed to do for you.

Then I hit the Escher chapters. Hofstadter walks through the *Circle Limit* woodcuts, the tessellations of fish and angels and devils that tile an entire disk, getting infinitely smaller toward the edge but never running out of space. I'd seen them before but never really understood them. They're not decorative. They're mathematically rigorous tilings of the Poincaré disk, a model of hyperbolic geometry where the entire infinite plane fits inside a finite circle.

That's when the idea hit: what if a second brain lived in hyperbolic space instead of Euclidean space? What if the geometry itself could manage information density, so you never need to scroll, paginate, or lose context?

## The second brain problem

The dream of externalizing your thinking is old. Niklas Luhmann built his Zettelkasten in the 1960s: 90,000 index cards in wooden drawers, connected by hand-written cross-references. Vannevar Bush imagined the Memex in 1945, a desk with microfilm that could follow trails of association. The modern wave started around 2020 with Roam Research, then Obsidian, Logseq, and Notion's databases.

The core promise is always the same: get ideas out of your head, connect them, and let the structure that emerges be smarter than any single thought.

The core failure is also the same. Every one of these tools lays your notes on a flat Euclidean plane. Obsidian's graph view is a force-directed layout on $\mathbb{R}^2$. Notion is pages inside pages. Roam is an outliner, a tree projected onto a vertical scroll. When you have 40 nodes, it's fine. When you have 400, it's a mess. You zoom to see more, you scroll to find things, you paginate to manage the overflow.

In Euclidean space, the circumference of a circle grows linearly with radius ($2\pi r$). A knowledge tree that's 4 levels deep with a branching factor of 3 has about 40 leaf nodes. On a flat plane, those 40 leaves need to share the circumference at radius 4, and they start overlapping fast.

What if the space itself had more room?

## A brief history of non-Euclidean geometry

For over 2,000 years, mathematicians tried to prove Euclid's 5th postulate (the one that says given a line and a point not on it, exactly one parallel line passes through the point) from the other four axioms. They couldn't.

In the 1830s, Nikolai Lobachevsky and János Bolyai independently realized you could *deny* the 5th postulate and get a consistent geometry. What if there are infinitely many parallel lines through a point? You get hyperbolic geometry, a system where space curves away from itself, where triangles have angle sums less than 180°, and where parallel lines diverge.

In 1882, Henri Poincaré gave this abstract geometry a concrete model: the Poincaré disk. Map the entire infinite hyperbolic plane onto a finite unit circle. "Straight lines" become circular arcs that meet the boundary at right angles. Distances get compressed toward the edge. A step near the center covers more "ground" than a step near the boundary.

There's a *Gödel, Escher, Bach* thread here. Just as Gödel proved that no consistent axiomatic system can prove all truths within itself, the independence of the parallel postulate shows that Euclidean geometry isn't "correct." It's a choice. Hyperbolic geometry is equally valid, equally consistent. We just don't build user interfaces in it.

And then Escher enters. The geometer H.S.M. Coxeter sent Escher a paper on hyperbolic tessellations. Escher, who had no formal math training, turned it into the *Circle Limit* series (1958–1960). The fish in Circle Limit III and the angels and devils in Circle Limit IV aren't artistic interpretations of a mathematical idea. They *are* the math. Each figure is a tile in a regular tessellation of the Poincaré disk. I built a hover preview into the experiment's info modal that shows Escher's work when you mouse over the reference. It felt wrong to talk about this geometry without showing the art that made it famous.

## Exponential room: why hyperbolic space fits knowledge

In hyperbolic space, circumference grows *exponentially* with radius:

$$
C(r) = 2\pi\sinh(r) \approx \pi e^r \text{ for large } r
$$

Each concentric ring has exponentially more room than the last. For a knowledge graph, this means the root topic sits at the center, first-level subtopics live at radius 0.4 (3–4 nodes, comfortable), second-level at 0.7 (6–12 nodes, still no crowding), third-level at 0.88 (12–24 nodes), and fourth-level at 0.95 (24–48 nodes).

In Euclidean space, 48 leaf nodes at the same radius would be a disaster. In hyperbolic space, each one gets its own visual territory because the boundary ring has exponentially more circumference.

This connects back to Luhmann's Zettelkasten. His system worked because of physical proximity: related slips lived near each other in the drawer. Hyperbolic space offers the same property: subtopics are geometrically close to their parent, and the exponential growth means you never run out of "nearby" slots.

The left side is a flat Euclidean layout. The right is the same tree on a Poincaré disk. Crank up the branching factor and depth. The Euclidean side collapses into overlapping dots while the hyperbolic side stays readable.

## The Möbius transform: one function to navigate infinity

The entire navigation system is one function:

```typescript
function mobiusTransform(z: Complex, a: Complex): Complex {
const num = z.sub(a);
const den = Complex.ONE.sub(a.conj().mul(z));
return num.div(den);
}
```

$$
z \mapsto \frac{z - a}{1 - \bar{a}z}
$$

This maps point $a$ to the origin. Everything else flows conformally: angles are preserved, the boundary circle maps to itself, and the entire disk reshuffles around the new center. It's not a pan. It's not a zoom. It's a restructuring of the space around your focus.

In Euclidean space, panning is addition: $x + \Delta x$. In hyperbolic space, panning is a Möbius transform. The math is more involved, but the payoff is different in kind. You don't just shift the view, you pull distant information toward you while pushing peripheral information toward the horizon.

Composing transforms matters. Dragging twice doesn't add. It composes. `mobiusTransform(mobiusTransform(z, a), b)` is itself a Möbius transform. The group structure means navigation is always consistent. There's no way to "break" the view or end up in an invalid state.

There's a *Bach* connection here from GEB. A Möbius transform is to hyperbolic space what transposition is to music. When Bach transposes a fugue subject to a different key, every interval is preserved. The structure is identical; the perspective changes. Composing Möbius transforms is like layering fugue voices: each voice presents the same harmonic structure from a different tonal center. In the experiment, each drag gives you a new "voicing" of the same knowledge graph.

Drag inside the disk. The grid warps conformally: every dot moves, but the angles between gridlines stay the same. Toggle "Show angle preservation" to see the small squares at each grid point: they stay square even as the grid distorts. Toggle "Highlight fixed boundary" to confirm the disk edge never moves.

## Geodesics: straight lines that curve

In the Poincaré disk, the shortest path between two points isn't a straight line but a circular arc orthogonal to the boundary circle. These are the geodesics of hyperbolic space.

The algorithm to compute them is one of the more satisfying pieces of geometry in the codebase. Given two points $z_1$ and $z_2$:

1. Check if they're collinear with the origin (cross product test). If so, the geodesic is a diameter, a straight line through the center.
2. Otherwise, compute the inversion point $1/\bar{z}_1$, the reflection of $z_1$ across the boundary circle.
3. Find the unique circle passing through $z_1$, $z_2$, and the inversion point. This circle is guaranteed to be orthogonal to the boundary.
4. Extract the SVG arc parameters and sweep flag.

The orthogonality invariant $|C|^2 = R^2 + 1$ (where $C$ is the circle center and $R$ is its radius) is what makes this work. It's verified in the test suite and holds to floating-point precision.

Why arcs instead of lines? The hyperbolic metric $ds = \frac{2|dz|}{1-|z|^2}$ stretches distances near the boundary. The arc "cuts through" the shorter hyperbolic path even though it looks longer in Euclidean terms.

Click two points inside the disk. The blue curve is the geodesic, the true shortest path in hyperbolic space. The dashed gray line is the Euclidean straight line between the same points. Toggle the construction view to see the orthogonal circle (purple, dashed) and the inversion point $1/\bar{z}_1$ (amber dot).

## Conformal scaling and the dual render pipeline

Every tile in the experiment scales according to the conformal factor:

```typescript
const scale = Math.max(0, 1 - w.abs() ** 2);
```

Where $w$ is the Möbius-transformed position. This isn't a design choice. It falls directly out of the hyperbolic metric. Tiles at the center are full-size. Tiles near the boundary shrink toward zero. The formula $1 - |w|^2$ is the conformal factor of the Poincaré disk metric.

Nodes with `scale < 0.05` are culled from the DOM entirely. This keeps the render tree manageable even with 40+ nodes. Z-index is derived from scale: `Math.floor(scale * 100)`, so closer (larger) tiles naturally render on top without an explicit z-buffer.

The rendering uses a dual-layer architecture. An SVG layer (z-index 10) handles geodesic edges; SVG's native arc commands (`A R R 0 0 sweep x2 y2`) handle the curves perfectly. A DOM div layer (z-index 20) handles tiles: CSS text rendering, Tailwind styling, `translate3d` for GPU compositing. The SVG viewport is fixed at 300 units; the DOM layer scales with the container via a `useViewportRadius` hook.

Drag the slider to move the point along the radius. The purple tile shrinks as it approaches the boundary. The curve on the right plots $1 - |w|^2$, the quadratic dropoff that makes the horizon feel infinite.

## Growing trees in curved space

The knowledge graph is generated procedurally using a BFS tree layout adapted for the Poincaré disk. Nodes are assigned to concentric layers at specific radii: `[0, 0.4, 0.7, 0.88, 0.95]`. These were chosen for visual separation in hyperbolic coordinates. In Euclidean terms, the outer rings are crammed together, but in hyperbolic terms, each ring has exponentially more room.

Branching decreases with depth: the root gets 3–4 children, level 1 gets 2–3, level 2 gets 1–2. Angular jitter (±20% of sector width) gives the layout an organic, mind-map feel. Node types follow a hierarchy (root, area, project, note/media) with random Lucide icons assigned per type.

The graph is generated client-side in a `useEffect` to avoid hydration mismatch from random number generation. The labels use real PKM categories: "Dev," "Writing," "Health," "Art," "Finance," "Travel."

Adjust the depth, branching factor, and jitter to see different tree structures. Hit "Regenerate" for a new random layout. Notice how even dense trees (depth 4, branching 4) remain readable because each ring has exponentially more room.

## Strange loops and the future of knowledge space

Hofstadter's central concept in GEB is the *strange loop*, a self-referential structure where moving through a hierarchy eventually brings you back to where you started, but shifted. He argues that these tangled hierarchies are fundamental to consciousness, to Gödel's incompleteness theorem, to Bach's canons, and to Escher's impossible staircases.

The hyperbolic workspace is a strange loop. There is no privileged origin. Any node can be dragged to center. The "root" of the knowledge graph has no special geometric status. It's just wherever you happened to start. Compose enough Möbius transforms and you return to a transformed version of where you began. The hierarchy is real (nodes have parents and children) but the geometry treats every perspective as equally valid.

Contrast this with existing PKM tools. Obsidian has a "vault root." Notion has a "workspace." Roam has "daily notes" as the default entry point. These are all privileged origins, home pages that shape how you navigate everything downstream. A hyperbolic PKM has no home page. Focus *is* the interface.

The "horizon" metaphor is what makes this feel different from anything in Euclidean space. In the Poincaré disk, the boundary represents infinity. Information at the horizon is always visible but infinitely small. This is richer than "out of view" (scroll-based navigation) or "in another page" (folder navigation). Everything is always present. The question isn't "where is it?" but "what am I focused on?"

The obvious next steps: variable information density tied to scroll speed, topology-shifting zoom instead of pixel scaling, semantic clustering via hyperbolic embeddings. Poincaré embeddings are already used in machine learning for hierarchical data. Facebook Research published a paper on it in 2017. The same geometry that makes this experiment work is being used to embed entire taxonomies into low-dimensional hyperbolic space with better fidelity than Euclidean embeddings.

GEB argues that formal systems, visual art, and music share deep structural patterns, that the same isomorphisms appear across domains. The structure-preserving property of the Möbius transform is the same property that makes Bach's fugue transpositions work: change the center, keep the relationships. Hyperbolic space is mathematically better for trees, and knowledge graphs are trees (or at least approximately tree-like). Every force-directed graph layout is fighting against the geometry it's embedded in.

## Full thing

## What I'd do differently

Dead ends I hit along the way: I tried canvas rendering instead of SVG for the geodesic edges. Pixel-level arc rendering was noticeably worse than SVG's native arc commands: jaggy, slow, and harder to debug. I also tried animating the Möbius transform for smooth transitions between focal points. It's technically possible (interpolate the parameter `a` along a geodesic path), but hard to make feel right without inducing motion sickness from the nonlinear warping.

Open questions worth exploring: semantic clustering (auto-grouping related nodes based on content similarity), multi-user hyperbolic spaces (overlaying two people's knowledge graphs on the same disk), animated focal transitions that feel natural, and import from Obsidian vaults. Poincaré embeddings for hierarchical ML data could also be visualized directly in this UI.

The whole thing is 1,209 lines of code. Pure SVG and DOM: no canvas, no WebGL, no build dependencies beyond React. The math library is 146 lines. The geometry works. The real product would need search, editing, and persistence.