Inversion

Interactive applets

By Juan Carlos Ponce Campuzano, 16/Dec/2025


Historical background

Inversive geometry is a branch of geometry that studies transformations known as inversions, defined with respect to a circle (in the plane) or a sphere (in space). Essentially, these transformations preserve angles and map circles and lines to other circles or lines, providing a powerful framework for analyzing geometric structures beyond Euclidean transformations.

According to Yates (1947, p. 127) and Kline (1972, pp. 932-933), several mathematicians contributed to the development of inversive geometry throughout the 19th century. For example, Jacob Steiner (1796-1863) was one of the first to recognize the properties of geometric inversion in the plane Patterson (1933, p. 155). In addition, Adolphe Quetelet (1796-1874) and Germinal Pierre Dandelin (1794-1847) explored applications of this transformation to geometric problems Patterson (1933, pp. 156-164). Likewise, August Ferdinand Möbius (1790-1868) studied inversive geometry extensively Möbius (1855) and introduced the concept of Möbius transformations. Finally, William Thomson (Lord Kelvin) (1824-1907) and Joseph Liouville (1809-1882) emphasized the importance of inversion in mathematical physics, particularly in problems of potentials and electrostatics Thomson (1847). Taken together, these contributions laid the foundation for inversive geometry as a central area of modern geometry, with later applications in complex analysis and non-Euclidean geometry.

During the 20th century, inversive geometry continued to develop in close connection with complex analysis and the theory of conformal mappings. Felix Klein and Henri Poincaré used inversion ideas to formulate models of hyperbolic geometry and to advance the theory of transformation groups. In the same period, a major contribution was made by H. S. M. Coxeter (1907-2003), who systematically linked inversive geometry with projective geometry and the models of hyperbolic geometry. His works, such as The Inversive Plane and Hyperbolic Space (1966) Coxeter (1966) and Inversive Geometry (1971) Coxeter (1971), as well as his books Non-Euclidean Geometry (1942) Coxeter (1998) and Introduction to Geometry (1961) Coxeter (1969), consolidated the role of inversion within a unified vision of geometries.


Interactive applets

Inversion of curves in space: Knots

Trefoil knot
GeoGebra code


Figure-8 knot
GeoGebra code


Inversion of Sphere and Torus


Inversion of Spheroid and Hyperboloid (one sheet)


Inversion of Knot Surfaces



Python Code

1. Trefoil knot Inverted

Trefoil knot surface inverted
Trefoil knot surface inverted.
# Author: Juan Carlos Ponce Campuzano
# Date: 16/Dec/2025
# Trefoil knot Inverted

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

# Inversion sphere
center = np.array([3, 0.0, 0.0])  # center of inversion sphere
R = 1                             # radius of inversion sphere

# === Parameter grid ===
u = np.linspace(0, 4 * np.pi, 400)
v = np.linspace(0, 2 * np.pi, 100)
u, v = np.meshgrid(u, v)

# === Helper factor ===
factor = 1

# === Parametric equations ===
x = ( -np.cos(u) * np.cos(v) - 3 * np.cos(u) * (1.5 + 0.5 * np.sin(3 * u / 2)) ) * factor
y = ( np.sin(u) * np.cos(v) + 3 * np.sin(u) * (1.5 + 0.5 * np.sin(3 * u / 2)) ) * factor
z = ( np.sin(v) + 2 * np.cos(3*u/2) ) * factor

# === Inversion ===
X = x - center[0]
Y = y - center[1]
Z = z - center[2]

r2 = X**2 + Y**2 + Z**2
# avoid division by zero
r2[r2 == 0] = np.nan

x_inv = center[0] + (R**2 * X) / r2
y_inv = center[1] + (R**2 * Y) / r2
z_inv = center[2] + (R**2 * Z) / r2

# === Plot ===
fig = plt.figure(figsize=(9, 7))
ax = fig.add_subplot(111, projection='3d')
ax.set_proj_type('ortho')

# Inverted surface (blue tone)
ax.plot_surface(
    x_inv, y_inv, z_inv,
    rstride=1, cstride=1,
    color='#4f83cc',
    linewidth=0.1,
    edgecolor='k',
    alpha=0.3
)

# === Labels, title, aspect ===
ax.set_xlabel('X', fontsize=12)
ax.set_ylabel('Y', fontsize=12)
ax.set_zlabel('Z', fontsize=12)
ax.set_title(r"Inversion of Trefoil Knot Surface", fontsize=14)

ax.axis('on')
ax.set_box_aspect([1, 1, 1])
ax.view_init(elev=20, azim=190)

plt.tight_layout()
plt.show()

2. Figure-eight Knot Tube Surface

Figure-8 tubular surface
Figure-8 tubular surface.
# Author: Juan Carlos Ponce Campuzano
# Date: 16/Dec/2025
# Tube Surface with improved Frenet Frame

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

# --- Parameters ---
eps    = 0.16     # modulation parameter
h      = 1        # vertical scaling
lamb   = 0.25     # interpolation factor
sigma  = 1        # global scaling
r_tube = 1/4      # tube radius

# --- Auxiliary functions ---
def A(x):
    return eps * np.sin(4 * x)

def v1(x):
    return lamb * np.sin(x) - (1 - lamb) * np.sin(3 * x)

def v2(x):
    return lamb * np.cos(x) + (1 - lamb) * np.cos(3 * x)

def v3(x):
    return h * np.sin(2 * x)

# --- Figure-eight knot curve ---
def knot_curve(x):
    scale = sigma * (1 + A(x)) / (1 - A(x))
    return np.array([
        scale * v1(x),
        scale * v2(x),
        scale * v3(x)
    ])

# --- Improved Frenet Frame (robust) ---
def frenet_frame(u):
    du = 1e-4
    r1 = knot_curve(u - du)
    r2 = knot_curve(u)
    r3 = knot_curve(u + du)

    # First derivative (velocity)
    rp = (r3 - r1) / (2 * du)
    T = rp / np.linalg.norm(rp)

    # Second derivative (acceleration)
    rpp = (r3 - 2 * r2 + r1) / (du ** 2)

    # Normal vector
    N = rpp - np.dot(rpp, T) * T
    N = N / (np.linalg.norm(N) + 1e-12)

    # Binormal vector
    B = np.cross(T, N)
    B = B / np.linalg.norm(B)

    return r2, T, N, B

# --- Tube surface parametrization ---
def tube_surface(u, v):
    r, T, N, B = frenet_frame(u)
    return r + r_tube * (np.cos(v) * N + np.sin(v) * B)

# --- Mesh grid ---
u_vals = np.linspace(0, 2 * np.pi, 250)
v_vals = np.linspace(0, 2 * np.pi, 60)
U, V = np.meshgrid(u_vals, v_vals)
X = np.zeros_like(U)
Y = np.zeros_like(U)
Z = np.zeros_like(U)

# --- Evaluate surface points ---
for i in range(U.shape[0]):
    for j in range(U.shape[1]):
        p = tube_surface(U[i, j], V[i, j])
        X[i, j], Y[i, j], Z[i, j] = p

# --- Plot ---
fig = plt.figure(figsize=(8, 8))
ax = fig.add_subplot(111, projection='3d')
ax.set_proj_type('ortho')  # Orthographic projection

ax.plot_surface(
    X, Y, Z,
    rstride=1, cstride=1,
    color='#f2f2f2',
    linewidth=0.1,
    edgecolor='k',
    alpha=1.0
)

# Labels, aspect, and viewpoint
ax.set_xlabel("X", labelpad=10)
ax.set_ylabel("Y", labelpad=10)
ax.set_zlabel("Z", labelpad=10)
ax.set_box_aspect([1, 1, 1])
ax.view_init(elev=10, azim=45)
ax.axis('on')

plt.tight_layout()
plt.show()

3. Figure-eight Knot Tube + Inversion

Figure-8 knot surface inverted
Figure-8 knot surface inverted.
# Author: Juan Carlos Ponce Campuzano
# Date: 16/Dec/2025
# Tube Surface with improved Frenet frame and Inversion

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

# --- Parameters ---
eps    = 0.16     # modulation parameter
h      = 1        # vertical scaling
lamb   = 0.25     # interpolation factor
sigma  = 1        # global scaling
r_tube = 1/4      # tube radius
center = np.array([1, 0, 0])  # translation of original surface

# --- Auxiliary functions ---
def A(x):
    return eps * np.sin(4 * x)

def v1(x):
    return lamb * np.sin(x) - (1 - lamb) * np.sin(3 * x)

def v2(x):
    return lamb * np.cos(x) + (1 - lamb) * np.cos(3 * x)

def v3(x):
    return h * np.sin(2 * x)

# --- Figure-eight knot curve ---
def knot_curve(x):
    scale = sigma * (1 + A(x)) / (1 - A(x))
    return np.array([
        scale * v1(x),
        scale * v2(x),
        scale * v3(x)
    ])

# --- Robust Frenet Frame ---
def frenet_frame(u):
    du = 1e-4
    r1 = knot_curve(u - du)
    r2 = knot_curve(u)
    r3 = knot_curve(u + du)

    # First derivative (velocity)
    rp = (r3 - r1) / (2 * du)
    T = rp / np.linalg.norm(rp)

    # Second derivative (acceleration)
    rpp = (r3 - 2 * r2 + r1) / (du ** 2)

    # Normal vector
    N = rpp - np.dot(rpp, T) * T
    N = N / (np.linalg.norm(N) + 1e-12)

    # Binormal vector
    B = np.cross(T, N)
    B = B / np.linalg.norm(B)

    return r2, T, N, B

# --- Tube surface parametrization ---
def tube_surface(u, v):
    r, T, N, B = frenet_frame(u)
    return r + r_tube * (np.cos(v) * N + np.sin(v) * B) + center

# --- Create mesh grid ---
u_vals = np.linspace(0, 2 * np.pi, 800)
v_vals = np.linspace(0, 2 * np.pi, 40)
U, V = np.meshgrid(u_vals, v_vals)
X = np.zeros_like(U)
Y = np.zeros_like(U)
Z = np.zeros_like(U)

# --- Compute tube coordinates ---
for i in range(U.shape[0]):
    for j in range(U.shape[1]):
        p = tube_surface(U[i, j], V[i, j])
        X[i, j], Y[i, j], Z[i, j] = p

# --- Inversion transformation ---
R2 = X**2 + Y**2 + Z**2
X_inv = X / R2
Y_inv = Y / R2
Z_inv = Z / R2

# --- Plot both surfaces ---
fig = plt.figure(figsize=(10, 10))
ax = fig.add_subplot(111, projection='3d')
ax.set_proj_type('ortho')  # Orthographic projection 

# Original tube (semi-transparent)
ax.plot_surface(
    X, Y, Z,
    rstride=1, cstride=1,
    color='royalblue',
    linewidth=0.3,
    edgecolor='gray',
    alpha=0.5
)

# Inverted surface
ax.plot_surface(
    X_inv, Y_inv, Z_inv,
    rstride=1, cstride=1,
    color='#f2f2f2',
    linewidth=0.1,
    edgecolor='k',
    alpha=0.1
)

# Labels and view
ax.set_xlabel("X", labelpad=10)
ax.set_ylabel("Y", labelpad=10)
ax.set_zlabel("Z", labelpad=10)
ax.set_box_aspect([1, 1, 1])
ax.view_init(elev=-40, azim=40)
ax.axis('off')

#plt.tight_layout()
plt.show()

References

  1. Coxeter, H. S. M. (1998). Non-Euclidean Geometry (6th ed.). The Mathematical Association of America, Inc., USA.
  2. Coxeter, H. S. M. (1966). The inversive plane and hyperbolic space. Abhandlungen aus dem Mathematischen Seminar der Universität Hamburg, 29, 217–242. https://doi.org/10.1007/BF03016050
  3. Coxeter, H. S. M. (1971). The inversive plane and hyperbolic space. Educational Studies in Mathematics, 3, 310–321. https://www.jstor.org/stable/3482030
  4. Coxeter, H. S. M. (1969). Introduction to Geometry (2nd ed.). John Wiley & Sons, Inc.
  5. Coxeter, H. S. M., & Greitzer, S. L. (1967). Geometry Revisited. The Mathematical Association of America, Inc.
  6. Segerman, H. (2016). Visualizing Mathematics with 3D Printing. Johns Hopkins University Press.
  7. Kline, M. (1972). Mathematical Thought from Ancient to Modern Times. New York: Oxford University Press. https://archive.org/details/mathematicalthou0000unse
  8. Möbius, K. (1855). Die Theorie der Kreisverwandtschaft in rein geometrischer Darstellung. Abhandlungen der Königl. Sächs. Gesellschaft der Wissenschaften, 2, 529–595. (Werke 2, 243–345).
  9. Patterson, B. C. (1933). The Origins of the Geometric Principle of Inversion. Isis, 19(1), 154–180.
  10. Rolfsen, D. (2003). Knots and Links. AMS Chelsea Publishing, USA. (Original work published 1976).
  11. Thomson, W. (1847). Extraits deux lettres adressées à M. Liouville. Journal de Mathématiques Pures et Appliquées, Ser. 1, Vol. 12, 265–290.
  12. Thurston, W. P. (1979). The Geometry and Topology of Three-Manifolds. [Lecture Notes] Princeton University. https://archive.org/details/ThurstonTheGeometryAndTopologyOfThreeManifolds
  13. Yates, R. C. (1947). Handbook on Curves and Their Properties. Edwards Brothers, Inc.

Finally, if you find this content useful, please consider supporting my work using the links below.

I sincerely appreciate it. Thank you! 😃

Knot unfolding
Knot unfolding. Wikimedia Commons.