Structured the development roadmap into four blocks with an explicit boundary marker separating direct Java ports (Phase 1–7) from infrastructure (Phase 8), remaining porting (Phase 9), and new research territory (Phase 10+). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
565 lines
22 KiB
Markdown
565 lines
22 KiB
Markdown
# conformallab++ — Architecture & Pipeline
|
||
|
||
## Origin
|
||
|
||
conformallab++ is a C++ reimplementation of
|
||
[ConformalLab](https://github.com/varylab/conformallab),
|
||
the Java research library for discrete conformal geometry by
|
||
**Stefan Sechelmann** (TU Berlin, Institut für Mathematik,
|
||
SFB/Transregio 109 *Discretization in Geometry and Dynamics*).
|
||
|
||
The algorithmic foundation is his doctoral dissertation:
|
||
|
||
> Stefan Sechelmann —
|
||
> **Variational Methods for Discrete Surface Parameterization: Applications and Implementation**
|
||
> Doctoral thesis, Technische Universität Berlin, 2016.
|
||
> DOI: [10.14279/depositonce-5415](https://depositonce.tu-berlin.de/items/8e2988b2-d991-45b5-aad5-9fb7988f3b2f) · CC BY-SA 4.0
|
||
|
||
The dissertation develops the variational framework for discrete conformal equivalence:
|
||
discrete uniformization of Riemann surfaces, cone metrics, period matrices, and
|
||
holonomy — all of which are directly implemented in this library.
|
||
|
||
Further links:
|
||
**Java original:** [github.com/varylab/conformallab](https://github.com/varylab/conformallab) ·
|
||
**Website:** [sechel.de](https://sechel.de/) ·
|
||
**LinkedIn:** [linkedin.com/in/sechel](https://www.linkedin.com/in/sechel/)
|
||
|
||
---
|
||
|
||
## Positioning
|
||
|
||
conformallab++ is a **specialised research library for discrete conformal geometry** on
|
||
triangulated surfaces. It is not a general geometry-processing framework.
|
||
|
||
The library revives the algorithms of the original ConformalLab by Stefan Sechelmann
|
||
in a modern C++ setting. Its core concern is one precise mathematical question:
|
||
|
||
> Given a triangulated surface, find a conformally equivalent metric that satisfies
|
||
> prescribed curvature (angle-sum) constraints at each vertex.
|
||
|
||
Everything in the library serves this goal:
|
||
|
||
| What it is | What it is not |
|
||
|------------|----------------|
|
||
| Discrete conformal maps (Euclidean, spherical, hyperbolic) | General mesh processing |
|
||
| Newton solver for angle-sum energy functionals | Remeshing / boolean / smoothing |
|
||
| Priority-BFS layout into ℝ², S², Poincaré disk | Point-cloud or implicit-field processing |
|
||
| Holonomy, period matrices, fundamental domains | NURBS / parametric modelling |
|
||
| Research platform — experiment-first, CLI-ready | Production rendering engine |
|
||
|
||
**Relation to existing libraries.**
|
||
conformallab++ sits *on top of* CGAL, not beside it.
|
||
`CGAL::Surface_mesh` is the internal mesh representation; there is no additional
|
||
abstraction layer. Eigen handles all linear algebra. libigl provides the optional
|
||
interactive viewer. The library adds the conformal-geometry layer that none of these
|
||
provide.
|
||
|
||
---
|
||
|
||
## The conformal geometry pipeline
|
||
|
||
The full pipeline runs in three stages. All stages operate on the same
|
||
`ConformalMesh` (= `CGAL::Surface_mesh<Point3>` with attached property maps).
|
||
|
||
```mermaid
|
||
graph TD
|
||
IN["Input\n(OFF / OBJ / PLY / builder)"]
|
||
ADAPTER["Input Adapter\nload_mesh() · make_triangle() · make_quad_strip() …"]
|
||
|
||
subgraph PRE["① PREPROCESSING"]
|
||
MAPS["Maps Setup\nsetup_*_maps() + compute_lambda0_from_mesh()"]
|
||
DOF["DOF Assignment\nv_idx[v] · e_idx[e] · pin / free"]
|
||
THETA["Target Angles\ntheta_v[v] — cone metric or natural equilibrium"]
|
||
GB["Gauss–Bonnet Check\ncheck_gauss_bonnet() / enforce_gauss_bonnet()"]
|
||
MAPS --> DOF --> THETA --> GB
|
||
end
|
||
|
||
subgraph CORE["② PROCESSING CORE"]
|
||
NEWTON["Newton Solver\nnewton_euclidean/spherical/hyper_ideal()\n→ NewtonResult x* ∈ ℝⁿ"]
|
||
CG["Cut Graph [closed surfaces]\ncompute_cut_graph()\n→ CutGraph (2g seam edges)"]
|
||
LAYOUT["Layout / Embedding\neuclidean/spherical/hyper_ideal_layout()\n→ Layout2D / Layout3D\n · uv[v] · halfedge_uv[h]\n · HolonomyData"]
|
||
NORM["Normalisation\nnormalise_euclidean / _hyperbolic / _spherical()"]
|
||
PERIOD["Period Matrix [genus 1]\ncompute_period_matrix()\n→ PeriodData τ ∈ ℍ"]
|
||
FD["Fundamental Domain\ncompute_fundamental_domain()\n→ FundamentalDomain + tiling"]
|
||
NEWTON --> CG --> LAYOUT --> NORM --> PERIOD --> FD
|
||
end
|
||
|
||
subgraph POST["③ POSTPROCESSING"]
|
||
SERIAL["Serialisation\nsave_result_json/xml()\nsave_layout_off()"]
|
||
VIZ["Visualisation\nexample_viewer (libigl / GLFW)"]
|
||
CLI["CLI App\nconformallab_core -i -g -o -j -x -s"]
|
||
end
|
||
|
||
IN --> ADAPTER --> PRE
|
||
PRE --> CORE
|
||
CORE --> POST
|
||
|
||
style PRE fill:#dbeafe,stroke:#3b82f6,stroke-width:2px,color:#000
|
||
style CORE fill:#dcfce7,stroke:#16a34a,stroke-width:2px,color:#000
|
||
style POST fill:#fef9c3,stroke:#ca8a04,stroke-width:2px,color:#000
|
||
```
|
||
|
||
---
|
||
|
||
## Stage ① — Preprocessing
|
||
|
||
### Input adapter
|
||
|
||
All mesh input flows through a single entry point:
|
||
|
||
```cpp
|
||
ConformalMesh mesh = load_mesh("input.off"); // OFF · OBJ · PLY
|
||
ConformalMesh mesh = make_quad_strip(); // built-in test meshes
|
||
```
|
||
|
||
**Precondition guarantee:** the adapter ensures the mesh is a valid, orientable,
|
||
triangulated surface with consistent halfedge structure (CGAL validity).
|
||
Downstream stages never check for degeneracies — they trust the adapter.
|
||
|
||
### Maps setup
|
||
|
||
Each geometry mode has its own maps struct that attaches property maps to the mesh:
|
||
|
||
| Geometry | Setup function | Key property maps |
|
||
|----------|---------------|-------------------|
|
||
| Euclidean (ℝ²) | `setup_euclidean_maps()` | `lambda0[e]`, `theta_v[v]`, `v_idx[v]` |
|
||
| Spherical (S²) | `setup_spherical_maps()` | `lambda0[e]`, `theta_v[v]`, `v_idx[v]` |
|
||
| Hyper-ideal (H²) | `setup_hyper_ideal_maps()` | `beta_v[v]`, `alpha_e[e]`, `v_idx[v]`, `e_idx[e]` |
|
||
|
||
`compute_*_lambda0_from_mesh()` initialises log-edge-lengths from the 3-D vertex
|
||
positions. After this step the solver works entirely in scale-factor space; the
|
||
original vertex positions are no longer needed.
|
||
|
||
### DOF assignment & target angles
|
||
|
||
```cpp
|
||
// Pin first vertex (gauge fix for open meshes)
|
||
maps.v_idx[*mesh.vertices().begin()] = -1;
|
||
int idx = 0;
|
||
for (auto v : rest_of_vertices) maps.v_idx[v] = idx++;
|
||
|
||
// Set target curvature (cone metric or natural equilibrium)
|
||
maps.theta_v[v] = 2 * M_PI; // flat interior vertex
|
||
maps.theta_v[v] = M_PI / 3; // 60° cone singularity
|
||
```
|
||
|
||
**Natural equilibrium shortcut:** evaluate the gradient at `x = 0`, subtract it from
|
||
`theta_v` — the solver then converges to `x* = 0` identically (useful for tests).
|
||
|
||
### Gauss–Bonnet check
|
||
|
||
Before solving, the prescribed angles must satisfy:
|
||
|
||
$$\sum_{v} (2\pi - \Theta_v) = 2\pi \cdot \chi(M)$$
|
||
|
||
```cpp
|
||
check_gauss_bonnet(mesh, maps); // throws if violated
|
||
enforce_gauss_bonnet(mesh, maps); // distributes residual uniformly
|
||
```
|
||
|
||
**This is the most common source of silent Newton non-convergence.**
|
||
Prescribing angles that violate Gauss–Bonnet means no conformal factor exists —
|
||
the solver will iterate without converging.
|
||
|
||
---
|
||
|
||
## Stage ② — Processing core
|
||
|
||
### The three geometry modes
|
||
|
||
conformallab++ implements discrete conformal geometry in three model spaces:
|
||
|
||
| Mode | Space | Curvature | Typical surfaces |
|
||
|------|-------|-----------|-----------------|
|
||
| **Euclidean** | ℝ² | K = 0 | Flat tori, developable surfaces, open patches |
|
||
| **Spherical** | S² | K = +1 | Genus-0 (sphere-like) surfaces |
|
||
| **Hyper-ideal** | H² (Poincaré disk) | K = −1 | Genus-g surfaces (g ≥ 1), hyperbolic structures |
|
||
|
||
All three share the same algorithmic structure — only the angle formula, the
|
||
trilateration geometry, and the Hessian sign differ.
|
||
|
||
### Newton solver
|
||
|
||
```
|
||
NewtonResult newton_euclidean (mesh, x0, maps [, tol, max_iter])
|
||
NewtonResult newton_spherical (mesh, x0, maps [, tol, max_iter])
|
||
NewtonResult newton_hyper_ideal(mesh, x0, maps [, tol, max_iter, hess_eps])
|
||
```
|
||
|
||
Each iteration:
|
||
1. Evaluate gradient **G** (angle-sum defect per vertex)
|
||
2. Evaluate Hessian **H** (analytical for Euclidean/Spherical; symmetric FD for HyperIdeal)
|
||
3. Solve **H·Δx = −G** — try `SimplicialLDLT`, fall back to `SparseQR` on rank deficiency
|
||
4. Backtracking line search (up to 20 halvings)
|
||
|
||
**Preconditions:** mesh triangulated + manifold · Gauss–Bonnet satisfied · DOFs assigned
|
||
**Provides:** `NewtonResult.x` — converged scale factors; `converged`, `iterations`, `grad_inf_norm`
|
||
|
||
**SparseQR fallback** handles gauge modes on closed meshes without a pinned vertex.
|
||
The fallback is public API: `solve_linear_system(H, rhs, &used_fallback)`.
|
||
|
||
### Cut graph (closed surfaces)
|
||
|
||
For a closed genus-g surface, cutting along 2g independent homology cycles
|
||
turns it into a topological disk — a prerequisite for globally consistent BFS layout.
|
||
|
||
```cpp
|
||
CutGraph cg = compute_cut_graph(mesh);
|
||
// cg.cut_edge_flags[e.idx()] — true for seam edges
|
||
// cg.cut_edge_indices — ordered list of 2g seam edges
|
||
// cg.genus — g
|
||
```
|
||
|
||
**Algorithm:** tree-cotree decomposition (Erickson–Whittlesey 2005).
|
||
**Preconditions:** closed, orientable, triangulated mesh
|
||
**Provides:** exactly `2g` seam edges whose removal makes the surface simply connected
|
||
|
||
### Layout / Embedding
|
||
|
||
BFS-trilateration unfolds the mesh into the target geometry.
|
||
The root face (largest 3-D area, 1.5× interior bonus) is placed first;
|
||
all other faces are placed in **priority order by BFS depth** (min-heap),
|
||
minimising trilateration error accumulation.
|
||
|
||
```cpp
|
||
HolonomyData hol;
|
||
Layout2D layout = euclidean_layout(mesh, result.x, maps, &cg, &hol, /*normalise=*/true);
|
||
Layout3D slayout = spherical_layout(mesh, result.x, smaps);
|
||
Layout2D hlayout = hyper_ideal_layout(mesh, result.x, hmaps, &cg, &hol);
|
||
```
|
||
|
||
**Key outputs:**
|
||
|
||
| Field | Content |
|
||
|-------|---------|
|
||
| `layout.uv[v.idx()]` | Primary UV — first / shallowest-BFS visit |
|
||
| `layout.halfedge_uv[h.idx()]` | UV of `source(h)` as seen from `face(h)` — seam-aware |
|
||
| `layout.has_seam` | True when a vertex was reached via two different paths |
|
||
| `hol.translations[i]` | Translation ω_i across cut edge i (Euclidean / spherical) |
|
||
| `hol.mobius_maps[i]` | Möbius isometry T_i ∈ SU(1,1) across cut edge i (hyperbolic) |
|
||
|
||
**`halfedge_uv` — texture atlas semantics:**
|
||
At a seam edge the two opposite halfedges carry *different* UV values.
|
||
This gives each face its own UV copy of a seam vertex, enabling
|
||
a proper GPU texture atlas without vertex duplication.
|
||
|
||
**Trilateration — geometry by mode:**
|
||
|
||
| Mode | Method | Accuracy |
|
||
|------|--------|---------|
|
||
| Euclidean | Analytic formula in ℝ² | Exact |
|
||
| Spherical | Spherical law of cosines on S² | Exact |
|
||
| Hyper-ideal | Möbius + hyperbolic law of cosines in Poincaré disk | Exact |
|
||
|
||
**Preconditions:** `NewtonResult.converged` · mesh · maps · optional `CutGraph`
|
||
**Provides:** `Layout2D/3D` with `uv`, `halfedge_uv` · `HolonomyData` with translations / Möbius maps
|
||
|
||
### Möbius maps
|
||
|
||
`MobiusMap` (T(z) = (az+b)/(cz+d)) is the central algebraic object for hyperbolic geometry:
|
||
|
||
```cpp
|
||
MobiusMap T = MobiusMap::from_three(z1,w1, z2,w2, z3,w3); // fit to 3 correspondences
|
||
MobiusMap S = T.inverse().compose(U); // group operations
|
||
Eigen::Vector2d p2 = T.apply(p); // apply to 2-D point
|
||
```
|
||
|
||
Used for: hyperbolic trilateration · holonomy tracking · normalisation centering.
|
||
|
||
### Normalisation
|
||
|
||
After layout, a canonical post-processing step brings the result into a standard position:
|
||
|
||
| Mode | Method | Effect |
|
||
|------|--------|--------|
|
||
| Euclidean | PCA — centroid → origin, major axis → x-axis | Translation + rotation |
|
||
| Hyperbolic | Weighted Möbius centering (Fréchet mean, 30 iterations) | Maps centroid to disk origin |
|
||
| Spherical | Rodrigues rotation | Maps centroid to north pole |
|
||
|
||
Both `uv` and `halfedge_uv` are transformed identically.
|
||
|
||
### Period matrix (genus 1)
|
||
|
||
From the two holonomy translations ω₁, ω₂ ∈ ℂ read off from the cut graph,
|
||
the conformal type of a flat torus is the SL(2,ℤ)-orbit of:
|
||
|
||
$$\tau = \omega_2 / \omega_1 \in \mathbb{H}$$
|
||
|
||
```cpp
|
||
PeriodData pd = compute_period_matrix(hol);
|
||
// pd.tau — complex period ratio
|
||
// pd.omega[i] — lattice generators as complex numbers
|
||
// pd.in_fundamental_domain — after SL(2,ℤ) reduction
|
||
// pd.genus() — g = omega.size() / 2
|
||
```
|
||
|
||
SL(2,ℤ) reduction alternates T: τ↦τ+1 and S: τ↦−1/τ steps until
|
||
τ ∈ F = {|τ| ≥ 1, −½ ≤ Re(τ) < ½}.
|
||
|
||
**Note:** The Siegel period matrix Ω ∈ H_g for genus g ≥ 2 requires integrating
|
||
holomorphic differentials — deferred to Phase 8.
|
||
|
||
### Fundamental domain
|
||
|
||
```cpp
|
||
FundamentalDomain fd = compute_fundamental_domain(hol);
|
||
// genus 1: CCW parallelogram {0, ω₁, ω₁+ω₂, ω₂}
|
||
// genus g > 1: empty — 4g-polygon boundary walk deferred to Phase 8
|
||
|
||
auto tiles = tiling_neighbourhood(layout, hol, /*m_max=*/2, /*n_max=*/2);
|
||
// returns (2·m_max+1)·(2·n_max+1) translated copies of the layout
|
||
// for visualising the universal cover
|
||
```
|
||
|
||
---
|
||
|
||
## Stage ③ — Postprocessing
|
||
|
||
### Serialisation
|
||
|
||
```cpp
|
||
// Layout as mesh file
|
||
save_layout_off("layout.off", mesh, layout);
|
||
|
||
// Full result: DOF vector + metadata + layout UVs
|
||
save_result_json("result.json", result, "euclidean", V, F, &layout);
|
||
save_result_xml ("result.xml", result, "euclidean", V, F, &layout);
|
||
|
||
// Round-trip load
|
||
NewtonResult res2; std::string geom; Layout2D uv2;
|
||
load_result_json("result.json", &res2, &geom, &uv2);
|
||
```
|
||
|
||
### CLI app
|
||
|
||
```bash
|
||
conformallab_core \
|
||
-i input.off # input mesh
|
||
-g euclidean # geometry: euclidean | spherical | hyper_ideal
|
||
-o layout.off # layout output
|
||
-j result.json # JSON serialisation
|
||
-x result.xml # XML serialisation
|
||
-s # show input in viewer
|
||
-v # verbose solver output
|
||
```
|
||
|
||
### Interactive viewer
|
||
|
||
`example_viewer` (libigl / GLFW) shows the 3-D mesh and the 2-D layout
|
||
side-by-side. Built automatically with `-DWITH_CGAL=ON`.
|
||
|
||
---
|
||
|
||
## Processing unit contracts
|
||
|
||
Each stage has explicit preconditions and guarantees.
|
||
A pipeline is valid if every unit's preconditions are satisfied
|
||
by the outputs of all preceding units.
|
||
|
||
| Unit | Preconditions | Provides |
|
||
|------|--------------|---------|
|
||
| `load_mesh` | Valid file path, supported format | Manifold, oriented, triangulated `ConformalMesh` |
|
||
| `setup_*_maps` | Triangulated mesh | Initialised property maps; `lambda0` from 3-D positions |
|
||
| `check_gauss_bonnet` | `theta_v` set | Throws if Σ(2π−Θ_v) ≠ 2π·χ |
|
||
| `enforce_gauss_bonnet` | `theta_v` set | Σ(2π−Θ_v) = 2π·χ guaranteed |
|
||
| `newton_*` | GB satisfied · DOFs assigned | `NewtonResult.converged` · `x*` · gradient norm |
|
||
| `compute_cut_graph` | Closed, orientable mesh | `2g` seam edges · `CutGraph.genus` |
|
||
| `euclidean_layout` | `newton_euclidean` converged | `uv[v]` · `halfedge_uv[h]` · `HolonomyData` |
|
||
| `normalise_euclidean` | `layout.success == true` | Centroid at origin · major axis = x-axis |
|
||
| `compute_period_matrix` | `hol.translations.size() >= 2` | `τ ∈ ℍ` · optionally reduced to F |
|
||
| `compute_fundamental_domain` | `HolonomyData` (genus 1) | CCW parallelogram · edge identifications |
|
||
|
||
---
|
||
|
||
## The three geometry modes in detail
|
||
|
||
```
|
||
Euclidean Spherical Hyper-ideal
|
||
─────────────────────────────────────────────────────
|
||
Space ℝ² S² H² (Poincaré disk)
|
||
Curvature K = 0 K = +1 K = −1
|
||
Genus any (cone metrics) 0 ≥ 1
|
||
Angle sum Σα_v = Θ_v Σα_v = Θ_v Σβ_v = Θ_v
|
||
Hessian PSD (cotangent-Lap.) NSD (sign-flip) PSD (FD, strict conv.)
|
||
Holonomy translations ω_i rotations (2-D) Möbius maps T_i ∈ SU(1,1)
|
||
Period τ = ω₂/ω₁ ∈ ℍ — axis of T_i
|
||
Normalise PCA centring Rodrigues to N pole weighted Möbius centring
|
||
```
|
||
|
||
---
|
||
|
||
## Extension points
|
||
|
||
### Adding a new functional
|
||
|
||
1. Create `my_functional.hpp` with a `Maps` struct and `evaluate_my_functional()`.
|
||
2. The gradient must satisfy: `G_v = Σ(angle contributions) − theta_v[v]`.
|
||
3. Verify with a finite-difference gradient check (copy any `GradientCheck_*` test).
|
||
4. Pass to `solve_linear_system(H, -G)` or write a thin `newton_my` wrapper.
|
||
|
||
### Adding a new geometry mode
|
||
|
||
Implement `trilaterate_my()` with the correct local placement formula,
|
||
then follow the same BFS structure as `euclidean_layout` (see `layout.hpp`).
|
||
The priority BFS, holonomy tracking, and `halfedge_uv` population are geometry-agnostic.
|
||
|
||
### Adding a new processing unit
|
||
|
||
Declare its preconditions and capabilities explicitly (see table above).
|
||
The pipeline validation is currently manual (documented contracts); a
|
||
compile-time or runtime check is a natural Phase 8 extension.
|
||
|
||
---
|
||
|
||
## Declarative pipeline (target for Phase 8)
|
||
|
||
A lightweight YAML description for reproducible experiments:
|
||
|
||
```yaml
|
||
pipeline:
|
||
name: flat_torus_period
|
||
geometry: euclidean
|
||
|
||
input:
|
||
source: data/torus.off
|
||
|
||
steps:
|
||
- id: setup
|
||
unit: setup_euclidean_maps
|
||
provide: [maps_initialised]
|
||
|
||
- id: gauss_bonnet
|
||
unit: enforce_gauss_bonnet
|
||
require: [maps_initialised]
|
||
provide: [gauss_bonnet_satisfied]
|
||
|
||
- id: solve
|
||
unit: newton_euclidean
|
||
require: [gauss_bonnet_satisfied]
|
||
params:
|
||
tol: 1.0e-10
|
||
max_iter: 200
|
||
provide: [x_converged]
|
||
|
||
- id: cut
|
||
unit: compute_cut_graph
|
||
require: [mesh_closed]
|
||
provide: [cut_graph]
|
||
|
||
- id: layout
|
||
unit: euclidean_layout
|
||
require: [x_converged, cut_graph]
|
||
params:
|
||
normalise: true
|
||
provide: [layout_uv, holonomy]
|
||
|
||
- id: period
|
||
unit: compute_period_matrix
|
||
require: [holonomy]
|
||
provide: [tau]
|
||
|
||
output:
|
||
layout: out/torus_layout.off
|
||
json: out/torus_result.json
|
||
tau: out/torus_tau.txt
|
||
```
|
||
|
||
Each unit declares `require` (preconditions) and `provide` (capabilities).
|
||
A pipeline is valid if for every step, all `require` keys are satisfied by the
|
||
accumulated `provide` set of all preceding steps.
|
||
This mirrors exactly the contract table in this document.
|
||
|
||
---
|
||
|
||
## Development Roadmap
|
||
|
||
> **Grenze Portierung / neue Forschung:**
|
||
> Phase 1–7 sind direkte Portierungen aus dem Java-Original (Sechelmann 2016).
|
||
> Ab Phase 8 geht die Arbeit über den Umfang der Java-Bibliothek hinaus.
|
||
> — Phase 8 (CGAL-Paket) ist **Infrastruktur**, kein neuer Algorithmus.
|
||
> — Phase 9 (Inversive-Distance, Analytischer Hessian, 4g-Polygon) ist **Portierung** ausstehender Java-Features.
|
||
> — Phase 10+ ist **eigenständige Forschung**, die über das Java-Original hinausgeht.
|
||
|
||
---
|
||
|
||
### ◼ Portierungsphase abgeschlossen — Phase 1–7
|
||
|
||
```
|
||
Phase 1 Clausen / Lobachevsky / ImLi₂ ✅
|
||
Phase 2 Hyper-ideal Geometrie (ζ, lᵢⱼ, αᵢⱼ, σᵢ) ✅
|
||
Phase 3 CGAL-Infrastruktur + alle drei Funktionale (E/S/H) ✅
|
||
Phase 4 Newton-Solver (SimplicialLDLT + SparseQR-Fallback) ✅ 68 Tests
|
||
Phase 5 Priority-BFS-Layout + CLI + JSON/XML ✅ 95 Tests
|
||
Phase 6 Gauss–Bonnet, Tree-Cotree-Schnittgraph, Normalisierung ✅ 121 Tests
|
||
Phase 7 MobiusMap, halfedge_uv, Möbius-Holonomie, Periodenmatrix,
|
||
Fundamentalbereich (Genus 1), Java-Parität abgeschlossen ✅ 158 Tests
|
||
```
|
||
|
||
---
|
||
|
||
### ◼ Infrastruktur (über Java-Bibliothek hinaus) — Phase 8: CGAL-Paket
|
||
|
||
```
|
||
8a Traits-Klasse & Konzepte → include/CGAL/Conformal_map_traits.h
|
||
8b Öffentliche CGAL-Header-Hierarchie → include/CGAL/Discrete_conformal_map.h etc.
|
||
8c Dokumentation im CGAL-Stil → doc/Conformal_map/PackageDescription.txt
|
||
8d CGAL-Testformat → test/Conformal_map/
|
||
8e Declarative YAML-Pipeline → pipeline validator (require/provide tokens)
|
||
```
|
||
|
||
See the [Declarative pipeline](#declarative-pipeline-target-for-phase-8) section above
|
||
for the YAML schema that Phase 8e will validate at runtime.
|
||
|
||
---
|
||
|
||
### ◼ Ausstehende Portierung (Java-Features noch nicht übertragen) — Phase 9
|
||
|
||
```
|
||
9a Inversive-Distance-Funktional (Luo 2004)
|
||
→ InversiveDistanceMaps + functional + Hessian
|
||
→ discrete uniformization via inversive distances
|
||
9b Analytischer HyperIdeal-Hessian (ζ-Kette)
|
||
→ replace FD Hessian in hyper_ideal_hessian.hpp
|
||
→ reduces Newton iterations for large meshes
|
||
9c 4g-Polygon-Randlauf (Genus g > 1)
|
||
→ extend compute_fundamental_domain() beyond genus 1
|
||
→ algorithm outline already in fundamental_domain.hpp as TODO(Phase 9)
|
||
```
|
||
|
||
---
|
||
|
||
### ◼ Neue Forschung (über das Java-Original hinaus) — Phase 10+
|
||
|
||
```
|
||
Phase 10 Globale Uniformisierung Genus g ≥ 2
|
||
10a Holomorphe Differentiale auf diskreten Flächen
|
||
→ discrete harmonic 1-forms; integration along cut graph cycles
|
||
10b Siegel-Periodenmatrix Ω ∈ H_g (g×g komplex-symmetrisch, Im(Ω) > 0)
|
||
→ extend compute_period_matrix() to genus g ≥ 2
|
||
→ requires holomorphic differentials from 10a
|
||
10c Vollständige Uniformisierung
|
||
→ uniformize arbitrary genus-g surface to canonical constant-curvature metric
|
||
→ depends on 10a + 10b
|
||
```
|
||
|
||
---
|
||
|
||
## Recommended reading
|
||
|
||
### Primary source — the dissertation this library implements
|
||
|
||
| | |
|
||
|---|---|
|
||
| **Sechelmann** — *Variational Methods for Discrete Surface Parameterization: Applications and Implementation*, TU Berlin 2016 | The mathematical foundation of the entire library: discrete conformal equivalence, variational angle-sum functionals, Newton solver, uniformization, period matrices. DOI: [10.14279/depositonce-5415](https://depositonce.tu-berlin.de/items/8e2988b2-d991-45b5-aad5-9fb7988f3b2f) |
|
||
| **Java original** — [github.com/varylab/conformallab](https://github.com/varylab/conformallab) | Reference implementation in Java — the direct source for all algorithms ported to C++ |
|
||
|
||
### Further references
|
||
|
||
| Source | Relevance in conformallab++ |
|
||
|--------|----------------------------|
|
||
| Springborn — *Ideal Hyperbolic Polyhedra and Discrete Uniformization* (2020) | HyperIdeal functional; ζ₁₃/ζ₁₄/ζ₁₅ in `hyper_ideal_geometry.hpp` |
|
||
| Pinkall, Polthier — *Computing Discrete Minimal Surfaces* (1993) | Cotangent-Laplace Hessian in `euclidean_hessian.hpp` |
|
||
| Bobenko, Springborn — *Variational Principles for Circle Patterns* (2004) | Angle-sum variational framework used throughout |
|
||
| Luo — *Combinatorial Yamabe Flow on Surfaces* (2004) | Inversive-distance functional (not yet ported) |
|
||
| Erickson, Whittlesey — *Greedy Optimal Homotopy Generators* (SODA 2005) | Tree-cotree algorithm in `cut_graph.hpp` |
|