A tour in the wonderland of math with python

Möbius Transformations in Hyperbolic 3-Space

This project is exported and adapted from Roice Nelson's code at shadertoy, thank him for this nice aniamtion! You may refer to Roice's homepage for more explanations on the math behind the scenes.


  1. pyglet for the UI and OpenGL environment.
  2. ffmpeg for rendering the animation to video files.


Simply run and use keyboard to switch between different scenes.


  1. Loxodromic transformation of a Dupin cyclide:

  2. Loxodromic transformation of a cone:

  3. Parabolic translation of a holosphere:

Möbius transformations and isometries of the hyperbolic 3-space

Möbius transformations are also called fractal linear transformations of the extended complex plane \(\hat{\mathbb{C}}\):

\[M(z) = \frac{az+b}{cz+d},\quad a,b,c,d\in\mathbb{C}, z\in \hat{\mathbb{C}}.\]

\(M\) can be decomposed into "building blocks" of 4 types:

  1. \(M\) is called parabolic if it's conjugate to a pure translation \(z\to z+a\) where \(a\in\mathbb{C}\).
  2. \(M\) is called elliptic if it's conjugate to a pure rotation \(z\to e^{i\theta}z\) where \(\theta\in\mathbb{R}\).
  3. \(M\) is called hyperbolic if it's conjugate to a pure scaling \(z\to\lambda z\) where \(\lambda\in\mathbb{R}\) and \(\lambda > 0\).
  4. \(M\) is called loxodromic if it's conjugate to a composition of a hyperbolic transformation and an elliptic transformation, i.e. it's conjugate to some \(z\to cz\) where \(c\in\mathbb{C}\) and \(c\ne0\).

Any Möbius transformation can be uniquely extended to an isometry of the upper hyperbolic halfspace \[H_3 = \{(x,y,z)\in\mathbb{R}^3\ |\ z>0\}.\] This can be easily defined by using quaternions: let \[M: z\to\dfrac{az+b}{cz+d}\] be a Möbius transformation and \(p=(x,y,z)\in\mathbb{H}^3\), let \(q\) be the quaternion \(q=xi+yj+zk\), then define \[M(p) = \frac{aq+b}{cq+d}.\]

  1. If \(M\) is of parabolic type then this extended isometry has one fixed point at \(\infty\).
  2. If \(M\) is of elliptic type then this extended isometry has two fixed points and it's a rotation around the axis connecting these two points.
  3. If \(M\) is of hyperbolic type then this extended isometry also has two fixed points but it's a scaling that looks like "emitting" from one source and "sinking" into the other one.
  4. If \(M\) is of loxodromic type then this extended isometry has two fixed points but it "emits" spiral curves from the source and "shrinks" into the sink.

One can also use a Möbius transformation to "invert" the cone into a Dupin cyclide, in this case the two fixed points \(0\) and \(\infty\) become the two "horns" of the cyclide.

About the scene

The scene is rendered by raymarching and GLSL: in each raymarching step we compute the distance between current point and the scene. For example to compute the distance between a point \(p\) and the Dupin cyclide \(C\), one just transform \(C\) back to the cone by applying \(M^{-1}\), and transform \(p\) to \(q=M^{-1}(p)\), then compute the distance between the cone and \(q\). If in some step we found that \(q\) has "hit" the cone then we think \(p\) also has hit the cyclide, and we color the "hitting point" by the coordinates of \(q\).