# The Three Geometry Modes conformallab++ implements discrete conformal geometry in three model spaces. All three share the same algorithmic structure — only the angle formula, the trilateration geometry, and the Hessian sign differ. --- ## Comparison ``` Euclidean Spherical Hyper-ideal ───────────────────────────────────────────────────── Space ℝ² S² H² (Poincaré disk) Curvature K = 0 K = +1 K = −1 Typical genus any (cone metrics) 0 ≥ 1 Angle sum Σαᵥ = Θᵥ Σαᵥ = Θᵥ Σβᵥ = Θᵥ Gradient sign G_v = actual − Θᵥ G_v = Θᵥ − actual G_v = actual − Θᵥ Hessian PSD (cotangent-Lap.) NSD (sign-flip) PSD (FD, strict conv.) Newton solve SimplicialLDLT(H) SimplicialLDLT(−H) SimplicialLDLT(H) Holonomy translations ωᵢ rotations (2-D) Möbius maps Tᵢ ∈ SU(1,1) Period τ = ω₂/ω₁ ∈ ℍ — axis of Tᵢ Normalise PCA centring Rodrigues to N pole weighted Möbius centring Layout Layout2D (ℝ²) Layout3D (unit sphere) Layout2D (Poincaré disk) ``` --- ## Euclidean (ℝ²) **Energy:** the cotangent-weighted angle defect energy (Pinkall & Polthier 1993). **Effective log-length:** ``` Λ̃ᵢⱼ = λ°ᵢⱼ + uᵢ + uⱼ ``` **Gradient:** `G_v = Σ_{faces adj. v} α_v(face) − Θᵥ` — the actual angle sum minus the target. **Hessian:** cotangent Laplacian, assembled in `euclidean_hessian.hpp`. PSD with one zero eigenvalue (constant function) for closed meshes — handled by pinning one vertex or SparseQR. **Normalisation:** centroid → origin, major axis → x-axis via PCA (`normalise_euclidean`). **Holonomy:** lattice translations ω₁, ω₂ ∈ ℂ for closed surfaces. Period ratio τ = ω₂/ω₁ ∈ ℍ is the conformal modulus of the torus. --- ## Spherical (S²) **Typical use:** genus-0 (sphere-like) surfaces. **Gradient:** `G_v = Θᵥ − Σ α_v(face)` — note the **sign reversal** vs. Euclidean. **Hessian:** NSD (the spherical energy is concave). Newton solves `(−H)·Δx = G`, i.e. `SimplicialLDLT` is called on `−H`. This is handled transparently in `newton_spherical()`. **Gauge fix:** for a closed spherical surface, one additional DOF must be pinned to remove the rotational gauge mode. `SphericalMaps` has a dedicated `gauge_vertex` field. **Normalisation:** `normalise_spherical()` rotates the layout so the area centroid maps to the north pole (Rodrigues rotation formula). --- ## Hyper-ideal (H²) **Typical use:** genus-g surfaces (g ≥ 1), hyperbolic cone metrics. **DOFs:** both vertex variables `bᵢ` (hyper-ideal radius) and edge variables `aₑ` (intersection angle). `assign_all_dof_indices(mesh, maps)` assigns both automatically. No vertex needs to be pinned — the functional is strictly convex. **Geometry functions** (in `hyper_ideal_geometry.hpp`): ``` ζ₁₃(b, a) ζ₁₄(b, a) ζ₁₅(b, a) — the three fundamental Springborn functions lᵢⱼ(ζ) — edge length from ζ value αᵢⱼ(l₁, l₂, l₃) — interior angle βᵢ(l₁, l₂, l₃) — vertex angle sum contribution ``` **Hessian:** currently a symmetric finite-difference approximation (see `hyper_ideal_hessian.hpp`). The analytic Hessian through the `(bᵢ, aₑ) → lᵢⱼ → ζ → αᵢⱼ/βᵢ` chain is Phase 9b. **Holonomy:** Möbius isometries Tᵢ ∈ SU(1,1) (orientation-preserving isometries of the Poincaré disk). `MobiusMap` in `layout.hpp`: T(z) = (az+b)/(cz+d). **Normalisation:** `normalise_hyperbolic()` performs iterative face-area-weighted Möbius centring (Fréchet mean, 30 iterations) to map the weighted centroid to the disk origin. --- ## Gauss–Bonnet constraint Before calling any Newton solver, the target angles must satisfy the Gauss–Bonnet equation: ``` Σᵥ (2π − Θᵥ) = 2π · χ(M) (Euclidean / flat) Σᵥ (2π − Θᵥ) > 0 (spherical, χ > 0) Σᵥ (2π − Θᵥ) < 0 (hyperbolic, χ < 0) ``` If this is violated, no conformal factor can realise the target angles and Newton will fail to converge without a visible error. ```cpp check_gauss_bonnet(mesh, maps); // throws if violated enforce_gauss_bonnet(mesh, maps); // redistributes residual uniformly across all vertices ``` **This is the most common source of silent non-convergence.** Always call one of these before solving.