docs: Mathematiker-Onboarding — Theorie, Validierung, Beispiel-Meshes, 170 Tests
Ziel: einem interessierten Mathematiker ermöglichen, die bisherige Arbeit
unabhängig zu validieren und eigene Forschung beizutragen.
Neu:
doc/math/discrete-conformal-theory.md
Kompakte mathematische Einführung (DCE, Variationsprinzip, drei
Geometriemodi, Holonomie, Periodenmatrix) für Riemann-Flächen-Kenner.
doc/math/validation.md
Analytisch bekannte Sollwerte + wie man sie mit dem Code prüft:
Gauss–Bonnet (χ), τ ∈ Fundamentaldomäne (3 Invarianten), Symmetrie-
Argumente für τ=i (4-fach) und τ=e^{iπ/3} (6-fach), Newton-Konvergenz,
Gradienten-Check (FD), Holonomie-Kommutator. Reviewer-Checkliste.
CONTRIBUTING.md (Root)
Gitea/GitHub-Standard: CONTRIBUTING.md im Root-Verzeichnis als
Kurzreferenz mit Links zu doc/contributing.md und den Math-Docs.
code/data/off/torus_4x4.off — 16 Vertices, 32 Flächen, Genus 1
code/data/off/torus_8x8.off — 64 Vertices, 128 Flächen, Genus 1
code/data/off/torus_hex_6x6.off — 36 Vertices, 72 Flächen, 6-fach Sym.
Aktualisiert:
README.md — 158 → 170 Tests, zwei neue Math-Links in Tabelle
doc/api/tests.md — 28 Suiten, 170 Tests, 1 Skip (korrigiert)
doc/contributing.md — Testzähler 158+2 → 170+1
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
17
CONTRIBUTING.md
Normal file
17
CONTRIBUTING.md
Normal file
@@ -0,0 +1,17 @@
|
||||
# Contributing to conformallab++
|
||||
|
||||
See **[doc/contributing.md](doc/contributing.md)** for the full guide:
|
||||
|
||||
- Git workflow (dev → PR → main)
|
||||
- CI pipeline (test-fast / test-cgal)
|
||||
- Test standards (gradient check, convergence test, registration)
|
||||
- Code style (C++17, header-only, namespace, property map naming)
|
||||
- Release process
|
||||
|
||||
For the mathematical background of what's being implemented, see:
|
||||
|
||||
- [doc/math/discrete-conformal-theory.md](doc/math/discrete-conformal-theory.md) — theory overview
|
||||
- [doc/math/validation.md](doc/math/validation.md) — how to validate the implementation
|
||||
- [doc/math/references.md](doc/math/references.md) — all referenced papers
|
||||
|
||||
To add your own research, see [doc/api/extending.md](doc/api/extending.md).
|
||||
@@ -9,7 +9,7 @@ Algorithmic foundation:
|
||||
> DOI: [10.14279/depositonce-5415](https://depositonce.tu-berlin.de/items/8e2988b2-d991-45b5-aad5-9fb7988f3b2f) · CC BY-SA 4.0 ·
|
||||
> [Java original](https://github.com/varylab/conformallab) · [sechel.de](https://sechel.de/)
|
||||
|
||||
**Status:** Phase 7 complete. Newton solver for all three geometries (Euclidean / Spherical / HyperIdeal), priority-BFS layout in ℝ²/S²/Poincaré disk, Gauss–Bonnet, tree-cotree cut graph, Möbius holonomy, period matrix (genus 1), fundamental domain, halfedge_uv texture atlas, JSON/XML serialisation, CLI app. **158 CGAL tests + 36 non-CGAL tests.**
|
||||
**Status:** Phase 7 complete. Newton solver for all three geometries (Euclidean / Spherical / HyperIdeal), priority-BFS layout in ℝ²/S²/Poincaré disk, Gauss–Bonnet, tree-cotree cut graph, Möbius holonomy, period matrix (genus 1), fundamental domain, halfedge_uv texture atlas, JSON/XML serialisation, CLI app. **170 CGAL tests + 36 non-CGAL tests.**
|
||||
|
||||
---
|
||||
|
||||
@@ -76,13 +76,15 @@ Layout2D layout = euclidean_layout(mesh, res.x, maps);
|
||||
| **Getting started** — build modes, single-test invocation, CLI, Docker | [doc/getting-started.md](doc/getting-started.md) |
|
||||
| **Pipeline API** — all three geometries, holonomy, serialisation | [doc/api/pipeline.md](doc/api/pipeline.md) |
|
||||
| **Public headers** — all 24 headers with descriptions | [doc/api/headers.md](doc/api/headers.md) |
|
||||
| **Test suites** — 26 suites, 158 tests, individual counts | [doc/api/tests.md](doc/api/tests.md) |
|
||||
| **Test suites** — 28 suites, 170 tests, individual counts | [doc/api/tests.md](doc/api/tests.md) |
|
||||
| **Extending** — new functionals, geometry modes, porting from Java | [doc/api/extending.md](doc/api/extending.md) |
|
||||
| **Processing unit contracts** — preconditions / provides table | [doc/api/contracts.md](doc/api/contracts.md) |
|
||||
| **CGAL package design** — Phase 8 target, YAML pipeline | [doc/api/cgal-package.md](doc/api/cgal-package.md) |
|
||||
| **Architecture & pipeline diagram** | [doc/architecture/overall_pipeline.md](doc/architecture/overall_pipeline.md) |
|
||||
| **Design decisions** — key architectural choices + rationale | [doc/architecture/design-decisions.md](doc/architecture/design-decisions.md) |
|
||||
| **Project structure** — directory tree + build targets | [doc/architecture/project-structure.md](doc/architecture/project-structure.md) |
|
||||
| **Discrete conformal theory** — mathematical background for collaborators | [doc/math/discrete-conformal-theory.md](doc/math/discrete-conformal-theory.md) |
|
||||
| **Validation** — known analytic results + how to verify them | [doc/math/validation.md](doc/math/validation.md) |
|
||||
| **Geometry modes** — Euclidean / Spherical / HyperIdeal comparison | [doc/math/geometry-modes.md](doc/math/geometry-modes.md) |
|
||||
| **References** — all papers by module | [doc/math/references.md](doc/math/references.md) |
|
||||
| **Roadmap** — Phases 1–10 | [doc/roadmap/phases.md](doc/roadmap/phases.md) |
|
||||
|
||||
50
code/data/off/torus_4x4.off
Normal file
50
code/data/off/torus_4x4.off
Normal file
@@ -0,0 +1,50 @@
|
||||
OFF
|
||||
16 32 0
|
||||
3.000000 0.000000 0.000000
|
||||
2.000000 0.000000 1.000000
|
||||
1.000000 0.000000 0.000000
|
||||
2.000000 0.000000 -1.000000
|
||||
0.000000 3.000000 0.000000
|
||||
0.000000 2.000000 1.000000
|
||||
0.000000 1.000000 0.000000
|
||||
0.000000 2.000000 -1.000000
|
||||
-3.000000 0.000000 0.000000
|
||||
-2.000000 0.000000 1.000000
|
||||
-1.000000 0.000000 0.000000
|
||||
-2.000000 0.000000 -1.000000
|
||||
-0.000000 -3.000000 0.000000
|
||||
-0.000000 -2.000000 1.000000
|
||||
-0.000000 -1.000000 0.000000
|
||||
-0.000000 -2.000000 -1.000000
|
||||
3 0 4 1
|
||||
3 1 4 5
|
||||
3 1 5 2
|
||||
3 2 5 6
|
||||
3 2 6 3
|
||||
3 3 6 7
|
||||
3 3 7 0
|
||||
3 0 7 4
|
||||
3 4 8 5
|
||||
3 5 8 9
|
||||
3 5 9 6
|
||||
3 6 9 10
|
||||
3 6 10 7
|
||||
3 7 10 11
|
||||
3 7 11 4
|
||||
3 4 11 8
|
||||
3 8 12 9
|
||||
3 9 12 13
|
||||
3 9 13 10
|
||||
3 10 13 14
|
||||
3 10 14 11
|
||||
3 11 14 15
|
||||
3 11 15 8
|
||||
3 8 15 12
|
||||
3 12 0 13
|
||||
3 13 0 1
|
||||
3 13 1 14
|
||||
3 14 1 2
|
||||
3 14 2 15
|
||||
3 15 2 3
|
||||
3 15 3 12
|
||||
3 12 3 0
|
||||
194
code/data/off/torus_8x8.off
Normal file
194
code/data/off/torus_8x8.off
Normal file
@@ -0,0 +1,194 @@
|
||||
OFF
|
||||
64 128 0
|
||||
4.000000 0.000000 0.000000
|
||||
3.707107 0.000000 0.707107
|
||||
3.000000 0.000000 1.000000
|
||||
2.292893 0.000000 0.707107
|
||||
2.000000 0.000000 0.000000
|
||||
2.292893 0.000000 -0.707107
|
||||
3.000000 0.000000 -1.000000
|
||||
3.707107 0.000000 -0.707107
|
||||
2.828427 2.828427 0.000000
|
||||
2.621320 2.621320 0.707107
|
||||
2.121320 2.121320 1.000000
|
||||
1.621320 1.621320 0.707107
|
||||
1.414214 1.414214 0.000000
|
||||
1.621320 1.621320 -0.707107
|
||||
2.121320 2.121320 -1.000000
|
||||
2.621320 2.621320 -0.707107
|
||||
0.000000 4.000000 0.000000
|
||||
0.000000 3.707107 0.707107
|
||||
0.000000 3.000000 1.000000
|
||||
0.000000 2.292893 0.707107
|
||||
0.000000 2.000000 0.000000
|
||||
0.000000 2.292893 -0.707107
|
||||
0.000000 3.000000 -1.000000
|
||||
0.000000 3.707107 -0.707107
|
||||
-2.828427 2.828427 0.000000
|
||||
-2.621320 2.621320 0.707107
|
||||
-2.121320 2.121320 1.000000
|
||||
-1.621320 1.621320 0.707107
|
||||
-1.414214 1.414214 0.000000
|
||||
-1.621320 1.621320 -0.707107
|
||||
-2.121320 2.121320 -1.000000
|
||||
-2.621320 2.621320 -0.707107
|
||||
-4.000000 0.000000 0.000000
|
||||
-3.707107 0.000000 0.707107
|
||||
-3.000000 0.000000 1.000000
|
||||
-2.292893 0.000000 0.707107
|
||||
-2.000000 0.000000 0.000000
|
||||
-2.292893 0.000000 -0.707107
|
||||
-3.000000 0.000000 -1.000000
|
||||
-3.707107 0.000000 -0.707107
|
||||
-2.828427 -2.828427 0.000000
|
||||
-2.621320 -2.621320 0.707107
|
||||
-2.121320 -2.121320 1.000000
|
||||
-1.621320 -1.621320 0.707107
|
||||
-1.414214 -1.414214 0.000000
|
||||
-1.621320 -1.621320 -0.707107
|
||||
-2.121320 -2.121320 -1.000000
|
||||
-2.621320 -2.621320 -0.707107
|
||||
-0.000000 -4.000000 0.000000
|
||||
-0.000000 -3.707107 0.707107
|
||||
-0.000000 -3.000000 1.000000
|
||||
-0.000000 -2.292893 0.707107
|
||||
-0.000000 -2.000000 0.000000
|
||||
-0.000000 -2.292893 -0.707107
|
||||
-0.000000 -3.000000 -1.000000
|
||||
-0.000000 -3.707107 -0.707107
|
||||
2.828427 -2.828427 0.000000
|
||||
2.621320 -2.621320 0.707107
|
||||
2.121320 -2.121320 1.000000
|
||||
1.621320 -1.621320 0.707107
|
||||
1.414214 -1.414214 0.000000
|
||||
1.621320 -1.621320 -0.707107
|
||||
2.121320 -2.121320 -1.000000
|
||||
2.621320 -2.621320 -0.707107
|
||||
3 0 8 1
|
||||
3 1 8 9
|
||||
3 1 9 2
|
||||
3 2 9 10
|
||||
3 2 10 3
|
||||
3 3 10 11
|
||||
3 3 11 4
|
||||
3 4 11 12
|
||||
3 4 12 5
|
||||
3 5 12 13
|
||||
3 5 13 6
|
||||
3 6 13 14
|
||||
3 6 14 7
|
||||
3 7 14 15
|
||||
3 7 15 0
|
||||
3 0 15 8
|
||||
3 8 16 9
|
||||
3 9 16 17
|
||||
3 9 17 10
|
||||
3 10 17 18
|
||||
3 10 18 11
|
||||
3 11 18 19
|
||||
3 11 19 12
|
||||
3 12 19 20
|
||||
3 12 20 13
|
||||
3 13 20 21
|
||||
3 13 21 14
|
||||
3 14 21 22
|
||||
3 14 22 15
|
||||
3 15 22 23
|
||||
3 15 23 8
|
||||
3 8 23 16
|
||||
3 16 24 17
|
||||
3 17 24 25
|
||||
3 17 25 18
|
||||
3 18 25 26
|
||||
3 18 26 19
|
||||
3 19 26 27
|
||||
3 19 27 20
|
||||
3 20 27 28
|
||||
3 20 28 21
|
||||
3 21 28 29
|
||||
3 21 29 22
|
||||
3 22 29 30
|
||||
3 22 30 23
|
||||
3 23 30 31
|
||||
3 23 31 16
|
||||
3 16 31 24
|
||||
3 24 32 25
|
||||
3 25 32 33
|
||||
3 25 33 26
|
||||
3 26 33 34
|
||||
3 26 34 27
|
||||
3 27 34 35
|
||||
3 27 35 28
|
||||
3 28 35 36
|
||||
3 28 36 29
|
||||
3 29 36 37
|
||||
3 29 37 30
|
||||
3 30 37 38
|
||||
3 30 38 31
|
||||
3 31 38 39
|
||||
3 31 39 24
|
||||
3 24 39 32
|
||||
3 32 40 33
|
||||
3 33 40 41
|
||||
3 33 41 34
|
||||
3 34 41 42
|
||||
3 34 42 35
|
||||
3 35 42 43
|
||||
3 35 43 36
|
||||
3 36 43 44
|
||||
3 36 44 37
|
||||
3 37 44 45
|
||||
3 37 45 38
|
||||
3 38 45 46
|
||||
3 38 46 39
|
||||
3 39 46 47
|
||||
3 39 47 32
|
||||
3 32 47 40
|
||||
3 40 48 41
|
||||
3 41 48 49
|
||||
3 41 49 42
|
||||
3 42 49 50
|
||||
3 42 50 43
|
||||
3 43 50 51
|
||||
3 43 51 44
|
||||
3 44 51 52
|
||||
3 44 52 45
|
||||
3 45 52 53
|
||||
3 45 53 46
|
||||
3 46 53 54
|
||||
3 46 54 47
|
||||
3 47 54 55
|
||||
3 47 55 40
|
||||
3 40 55 48
|
||||
3 48 56 49
|
||||
3 49 56 57
|
||||
3 49 57 50
|
||||
3 50 57 58
|
||||
3 50 58 51
|
||||
3 51 58 59
|
||||
3 51 59 52
|
||||
3 52 59 60
|
||||
3 52 60 53
|
||||
3 53 60 61
|
||||
3 53 61 54
|
||||
3 54 61 62
|
||||
3 54 62 55
|
||||
3 55 62 63
|
||||
3 55 63 48
|
||||
3 48 63 56
|
||||
3 56 0 57
|
||||
3 57 0 1
|
||||
3 57 1 58
|
||||
3 58 1 2
|
||||
3 58 2 59
|
||||
3 59 2 3
|
||||
3 59 3 60
|
||||
3 60 3 4
|
||||
3 60 4 61
|
||||
3 61 4 5
|
||||
3 61 5 62
|
||||
3 62 5 6
|
||||
3 62 6 63
|
||||
3 63 6 7
|
||||
3 63 7 56
|
||||
3 56 7 0
|
||||
110
code/data/off/torus_hex_6x6.off
Normal file
110
code/data/off/torus_hex_6x6.off
Normal file
@@ -0,0 +1,110 @@
|
||||
OFF
|
||||
36 72 0
|
||||
4.000000 0.000000 0.000000
|
||||
3.500000 0.000000 0.866025
|
||||
2.500000 0.000000 0.866025
|
||||
2.000000 0.000000 0.000000
|
||||
2.500000 0.000000 -0.866025
|
||||
3.500000 0.000000 -0.866025
|
||||
2.000000 3.464102 0.000000
|
||||
1.750000 3.031089 0.866025
|
||||
1.250000 2.165064 0.866025
|
||||
1.000000 1.732051 0.000000
|
||||
1.250000 2.165064 -0.866025
|
||||
1.750000 3.031089 -0.866025
|
||||
-2.000000 3.464102 0.000000
|
||||
-1.750000 3.031089 0.866025
|
||||
-1.250000 2.165064 0.866025
|
||||
-1.000000 1.732051 0.000000
|
||||
-1.250000 2.165064 -0.866025
|
||||
-1.750000 3.031089 -0.866025
|
||||
-4.000000 0.000000 0.000000
|
||||
-3.500000 0.000000 0.866025
|
||||
-2.500000 0.000000 0.866025
|
||||
-2.000000 0.000000 0.000000
|
||||
-2.500000 0.000000 -0.866025
|
||||
-3.500000 0.000000 -0.866025
|
||||
-2.000000 -3.464102 0.000000
|
||||
-1.750000 -3.031089 0.866025
|
||||
-1.250000 -2.165064 0.866025
|
||||
-1.000000 -1.732051 0.000000
|
||||
-1.250000 -2.165064 -0.866025
|
||||
-1.750000 -3.031089 -0.866025
|
||||
2.000000 -3.464102 0.000000
|
||||
1.750000 -3.031089 0.866025
|
||||
1.250000 -2.165064 0.866025
|
||||
1.000000 -1.732051 0.000000
|
||||
1.250000 -2.165064 -0.866025
|
||||
1.750000 -3.031089 -0.866025
|
||||
3 0 6 1
|
||||
3 1 6 7
|
||||
3 1 7 2
|
||||
3 2 7 8
|
||||
3 2 8 3
|
||||
3 3 8 9
|
||||
3 3 9 4
|
||||
3 4 9 10
|
||||
3 4 10 5
|
||||
3 5 10 11
|
||||
3 5 11 0
|
||||
3 0 11 6
|
||||
3 6 12 7
|
||||
3 7 12 13
|
||||
3 7 13 8
|
||||
3 8 13 14
|
||||
3 8 14 9
|
||||
3 9 14 15
|
||||
3 9 15 10
|
||||
3 10 15 16
|
||||
3 10 16 11
|
||||
3 11 16 17
|
||||
3 11 17 6
|
||||
3 6 17 12
|
||||
3 12 18 13
|
||||
3 13 18 19
|
||||
3 13 19 14
|
||||
3 14 19 20
|
||||
3 14 20 15
|
||||
3 15 20 21
|
||||
3 15 21 16
|
||||
3 16 21 22
|
||||
3 16 22 17
|
||||
3 17 22 23
|
||||
3 17 23 12
|
||||
3 12 23 18
|
||||
3 18 24 19
|
||||
3 19 24 25
|
||||
3 19 25 20
|
||||
3 20 25 26
|
||||
3 20 26 21
|
||||
3 21 26 27
|
||||
3 21 27 22
|
||||
3 22 27 28
|
||||
3 22 28 23
|
||||
3 23 28 29
|
||||
3 23 29 18
|
||||
3 18 29 24
|
||||
3 24 30 25
|
||||
3 25 30 31
|
||||
3 25 31 26
|
||||
3 26 31 32
|
||||
3 26 32 27
|
||||
3 27 32 33
|
||||
3 27 33 28
|
||||
3 28 33 34
|
||||
3 28 34 29
|
||||
3 29 34 35
|
||||
3 29 35 24
|
||||
3 24 35 30
|
||||
3 30 0 31
|
||||
3 31 0 1
|
||||
3 31 1 32
|
||||
3 32 1 2
|
||||
3 32 2 33
|
||||
3 33 2 3
|
||||
3 33 3 34
|
||||
3 34 3 4
|
||||
3 34 4 35
|
||||
3 35 4 5
|
||||
3 35 5 30
|
||||
3 30 5 0
|
||||
@@ -29,8 +29,8 @@ All tests have CTest prefix `cgal.` (set via `TEST_PREFIX "cgal."` in CMakeLists
|
||||
| `ConformalMeshProperties` | `test_conformal_mesh.cpp` | 5 | Property maps (λ, θ, idx, α, geometry type) |
|
||||
| `ConformalMeshValidity` | `test_conformal_mesh.cpp` | 1 | CGAL validity for all factory meshes |
|
||||
| `HyperIdealFunctional` | `test_hyper_ideal_functional.cpp` | 7 | FD gradient checks + Hessian symmetry |
|
||||
| `SphericalFunctional` | `test_spherical_functional.cpp` | 12 | Angle formula + gradient + gauge-fix *(1 skipped)* |
|
||||
| `EuclideanFunctional` | `test_euclidean_functional.cpp` | 11 | Angle formula + gradient *(1 skipped)* |
|
||||
| `SphericalFunctional` | `test_spherical_functional.cpp` | 12 | Angle formula + gradient + gauge-fix |
|
||||
| `EuclideanFunctional` | `test_euclidean_functional.cpp` | 11 | Angle formula + gradient |
|
||||
| `EuclideanHessian` | `test_euclidean_hessian.cpp` | 9 | Cotangent Laplacian structure, FD agreement, PSD, null space |
|
||||
| `SphericalHessian` | `test_spherical_hessian.cpp` | 8 | Derivative correctness, NSD at equilibrium |
|
||||
| `NewtonSolver` | `test_newton_solver.cpp` | 11 | Convergence: Euclidean ×3, Spherical ×4, HyperIdeal ×4 |
|
||||
@@ -51,15 +51,16 @@ All tests have CTest prefix `cgal.` (set via `TEST_PREFIX "cgal."` in CMakeLists
|
||||
| `PeriodMatrix` | `test_phase7.cpp` | 7 | τ ∈ ℍ, SL(2,ℤ) reduction, exception outside ℍ |
|
||||
| `FundamentalDomain` | `test_phase7.cpp` | 7 | Genus-1 parallelogram CCW, generators, g > 1 empty |
|
||||
| `TilingCopy/Neighbourhood` | `test_phase7.cpp` | 4 | Translation correct, tile count |
|
||||
| `GeometryUtils` | `test_geometry_utils.cpp` | 6 | Java CuttingUtility, UnwrapUtility, ConvergenceUtility, HomologyTest ports (Tests 1–6); Test 7 GTEST_SKIP stub |
|
||||
| `CuttingUtility` | `test_geometry_utils.cpp` | 3 | point_in_triangle_2d: false, true, unit triangle (Java CuttinUtilityTest) |
|
||||
| `UnwrapUtility` | `test_geometry_utils.cpp` | 2 | corner angle: collinear → π, equilateral → π/3 (Java UnwrapUtilityTest) |
|
||||
| `ConvergenceUtility` | `test_geometry_utils.cpp` | 6 | circumradius + scale-invariant R_f/√A (Java ConvergenceUtilityTests) |
|
||||
| `HomologyGenerators` | `test_geometry_utils.cpp` | 1 | GTEST_SKIP stub — genus-2 mesh missing (Java HomologyTest Test 7, Phase 9c) |
|
||||
|
||||
**Total: 158 tests, 2 intentional skips.**
|
||||
**Total: 170 tests, 1 intentional skip.**
|
||||
|
||||
The 2 skips are:
|
||||
- `SphericalFunctional` — analytic gauge-fix stub (Phase 9b)
|
||||
- `GeometryUtils` Test 7 — genus-2 homology (Phase 9c)
|
||||
|
||||
Both correspond to Java `@Ignore`-annotated tests in the original library.
|
||||
The skip is `HomologyGenerators.Genus2_FourGeneratorPaths_BLOCKED` — blocked until
|
||||
a genus-2 mesh is available (Phase 9c). It corresponds to a Java `@Ignore`-annotated
|
||||
test in the original library.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ Two jobs run on push to `dev`/`main` or on pull requests:
|
||||
| Job | What it tests | Trigger |
|
||||
|---|---|---|
|
||||
| `test-fast` | 36 non-CGAL tests, no Boost | all branches |
|
||||
| `test-cgal` | 158 CGAL tests + 2 skips | `main`, `dev`, PRs only |
|
||||
| `test-cgal` | 170 CGAL tests + 1 skip | `main`, `dev`, PRs only |
|
||||
|
||||
A PR is ready to merge when both jobs pass.
|
||||
|
||||
@@ -51,9 +51,10 @@ Every new algorithm needs:
|
||||
|
||||
3. **Registration** — add the `.cpp` file to `code/tests/cgal/CMakeLists.txt`.
|
||||
|
||||
Expected CI result: **36 + 158 tests pass, exactly 2 skipped**.
|
||||
The 2 skips are intentional `GTEST_SKIP()` stubs for Phase 9b (analytic HyperIdeal Hessian)
|
||||
and Phase 9c (genus-2 homology). Do not remove them.
|
||||
Expected CI result: **36 + 170 tests pass, exactly 1 skipped**.
|
||||
The skip is an intentional `GTEST_SKIP()` stub for the genus-2 homology test
|
||||
(`cgal.HomologyGenerators.Genus2_FourGeneratorPaths_BLOCKED`) — blocked until a
|
||||
genus-2 mesh is available in Phase 9c. Do not remove it.
|
||||
|
||||
---
|
||||
|
||||
|
||||
175
doc/math/discrete-conformal-theory.md
Normal file
175
doc/math/discrete-conformal-theory.md
Normal file
@@ -0,0 +1,175 @@
|
||||
# Discrete Conformal Geometry — Mathematical Background
|
||||
|
||||
This document is written for a mathematician who knows Riemannian surfaces and
|
||||
complex analysis but is new to the *discrete* setting. It covers exactly the
|
||||
theory implemented in conformallab++.
|
||||
|
||||
---
|
||||
|
||||
## 1 — The continuous picture (in one paragraph)
|
||||
|
||||
A **Riemann surface** (M, g) carries a conformal structure: the class of all
|
||||
metrics related to g by a smooth positive factor. On a compact surface of genus
|
||||
g, the Uniformization Theorem gives a unique constant-curvature representative
|
||||
(flat for g = 1, hyperbolic for g ≥ 2, spherical for g = 0). The conformal
|
||||
modulus of a genus-1 surface is a point τ ∈ ℍ (upper half-plane), well-defined
|
||||
up to SL(2, ℤ).
|
||||
|
||||
---
|
||||
|
||||
## 2 — Discrete conformal equivalence (DCE)
|
||||
|
||||
A **triangulated surface** is a pair (K, ℓ) where K is a simplicial complex
|
||||
homeomorphic to a surface and ℓ: E → ℝ₊ assigns an edge length. Two
|
||||
length assignments ℓ and ℓ̃ are **discretely conformally equivalent** if there
|
||||
exist vertex weights u: V → ℝ such that
|
||||
|
||||
```
|
||||
ℓ̃ᵢⱼ = e^{(uᵢ + uⱼ)/2} · ℓᵢⱼ for every edge {i, j}.
|
||||
```
|
||||
|
||||
This is the discrete analogue of a conformal rescaling g̃ = e^{2φ} g.
|
||||
The weights u ∈ ℝ^V are the *conformal factors* (log-scale factors on vertices).
|
||||
|
||||
**Key fact** (Springborn 2020): within each DCE class there exists a unique
|
||||
length assignment realising a prescribed angle structure, and it can be found
|
||||
by Newton's method on a convex energy.
|
||||
|
||||
---
|
||||
|
||||
## 3 — The variational energy
|
||||
|
||||
For each target corner angle **Θ_v** at vertex v, define the **angle-defect energy**:
|
||||
|
||||
```
|
||||
E(u) = Σ_{corners} φ(αᵥ(u)) − Σᵥ Θᵥ · uᵥ + boundary terms
|
||||
```
|
||||
|
||||
where αᵥ(u) is the corner angle at v in the triangulation with edge lengths
|
||||
ℓ̃(u) and φ is an appropriate primitive (Clausen / Lobachevsky / ImLi₂ depending
|
||||
on geometry).
|
||||
|
||||
The **gradient** is simply the angle-sum residual:
|
||||
|
||||
```
|
||||
∂E/∂uᵥ = Σ_{faces containing v} αᵥ(face) − Θᵥ
|
||||
```
|
||||
|
||||
Setting G = 0 finds the unique u realising the prescribed angle sums.
|
||||
|
||||
### Three geometry modes
|
||||
|
||||
| Mode | Space | φ | Hessian | Newton step |
|
||||
|---|---|---|---|---|
|
||||
| Euclidean | ℝ² | Clausen Cl₂ | cotangent Laplacian, PSD | SimplicialLDLT(H) |
|
||||
| Spherical | S² | ImLi₂ | NSD (concave E) | SimplicialLDLT(−H) |
|
||||
| Hyper-ideal | H² | Lobachevsky | PSD (strictly convex) | SimplicialLDLT(H) |
|
||||
|
||||
---
|
||||
|
||||
## 4 — Gauss–Bonnet constraint
|
||||
|
||||
The target angles **must** satisfy the discrete Gauss–Bonnet equation
|
||||
|
||||
```
|
||||
Σᵥ (2π − Θᵥ) = 2π · χ(M)
|
||||
```
|
||||
|
||||
before any solver is called. If this fails, no conformal factor can realise Θ
|
||||
and Newton will not converge. conformallab++ provides:
|
||||
|
||||
```cpp
|
||||
check_gauss_bonnet(mesh, maps); // throws if violated
|
||||
enforce_gauss_bonnet(mesh, maps); // redistributes residual uniformly
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5 — From angles to geometry: trilateration
|
||||
|
||||
After Newton converges, edge lengths ℓ̃ are known. The layout
|
||||
(embedding into ℝ², S², or H²) is built by a **priority BFS**:
|
||||
|
||||
1. Place an initial face arbitrarily.
|
||||
2. For each adjacent face, place its third vertex by *trilateration* —
|
||||
solving the system of three distance equations.
|
||||
3. Priority is depth in the spanning tree (shallowest first).
|
||||
|
||||
For Euclidean geometry this is the standard cosine rule.
|
||||
For hyperbolic geometry (Poincaré disk model) it uses the Möbius-isometric
|
||||
placement formula implemented in `layout.hpp`.
|
||||
|
||||
---
|
||||
|
||||
## 6 — Cut graph and holonomy
|
||||
|
||||
For genus g ≥ 1 the layout does not close up: a handle introduces a
|
||||
**holonomy** — a non-trivial monodromy around each generator of π₁.
|
||||
|
||||
The **tree-cotree algorithm** (Erickson–Whittlesey 2005) computes a minimal
|
||||
cut graph with exactly 2g seam edges. After cutting, the surface is disk-like
|
||||
and the BFS layout is well-defined. The holonomies along the 2g cut edges are:
|
||||
|
||||
- **Euclidean:** lattice translations ω₁, ω₂ ∈ ℂ
|
||||
- **Hyperbolic:** Möbius isometries T₁, T₂ ∈ SU(1,1)
|
||||
|
||||
---
|
||||
|
||||
## 7 — Period matrix (genus 1)
|
||||
|
||||
For a torus the **conformal modulus** is
|
||||
|
||||
```
|
||||
τ = ω₂ / ω₁ ∈ ℍ
|
||||
```
|
||||
|
||||
After Euclidean uniformization, ω₁ and ω₂ are the holonomies computed from
|
||||
the seam edge displacements. The SL(2, ℤ)-reduction to the fundamental
|
||||
domain {|τ| ≥ 1, |Re(τ)| ≤ 1/2, Im(τ) > 0} is performed automatically by
|
||||
`compute_period_matrix()`.
|
||||
|
||||
For genus g ≥ 2, the Siegel period matrix Ω ∈ H_g (g×g complex symmetric with
|
||||
positive definite imaginary part) requires integrating holomorphic 1-forms — this
|
||||
is Phase 10b.
|
||||
|
||||
---
|
||||
|
||||
## 8 — Fundamental domain
|
||||
|
||||
The fundamental domain of a torus is the parallelogram with vertices
|
||||
{0, ω₁, ω₁+ω₂, ω₂} in ℂ. conformallab++ computes this and provides tiling
|
||||
utilities (`tiling_copy`, `tiling_neighbourhood`).
|
||||
|
||||
For genus g ≥ 2, the fundamental domain is the standard 4g-gon (Phase 9c).
|
||||
|
||||
---
|
||||
|
||||
## 9 — Where the code lives
|
||||
|
||||
```
|
||||
Energy / gradient code/include/*_functional.hpp
|
||||
Hessian code/include/*_hessian.hpp
|
||||
Newton solver code/include/newton_solver.hpp
|
||||
Trilateration / BFS code/include/layout.hpp
|
||||
Cut graph code/include/cut_graph.hpp
|
||||
Holonomy code/include/layout.hpp (HolonomyData)
|
||||
Period matrix code/include/period_matrix.hpp
|
||||
Fundamental domain code/include/fundamental_domain.hpp
|
||||
Möbius maps code/include/layout.hpp (MobiusMap)
|
||||
```
|
||||
|
||||
All implementations are header-only (C++17), no compiled library.
|
||||
|
||||
---
|
||||
|
||||
## 10 — Primary references
|
||||
|
||||
| Reference | Covers |
|
||||
|---|---|
|
||||
| Springborn, *Discrete Uniformization of Polyhedral Surfaces*, 2020 | Complete mathematical foundation of all three modes |
|
||||
| Sechelmann, *Variational Methods for Discrete Surface Parameterization*, TU Berlin 2016 | Original Java implementation — the direct source for this library |
|
||||
| Pinkall & Polthier, 1993 | Cotangent Laplacian |
|
||||
| Erickson & Whittlesey, SODA 2005 | Tree-cotree cut graph |
|
||||
| Bobenko & Springborn, Trans. AMS 2004 | Variational circle-pattern framework |
|
||||
|
||||
Full reference list: [doc/math/references.md](references.md)
|
||||
206
doc/math/validation.md
Normal file
206
doc/math/validation.md
Normal file
@@ -0,0 +1,206 @@
|
||||
# Mathematical Validation
|
||||
|
||||
This document lists analytically known results and explains how to verify
|
||||
them against conformallab++ output. It is the primary tool for an independent
|
||||
mathematician to check the correctness of the implementation.
|
||||
|
||||
---
|
||||
|
||||
## How to run the examples
|
||||
|
||||
```bash
|
||||
cmake -S code -B build -DWITH_CGAL=ON -DCMAKE_BUILD_TYPE=Release
|
||||
cmake --build build --target conformallab_cgal_tests
|
||||
ctest --test-dir build -R cgal --output-on-failure
|
||||
```
|
||||
|
||||
All 170 tests pass (11 skipped by design — see `doc/api/tests.md`).
|
||||
|
||||
---
|
||||
|
||||
## 1 — Gauss–Bonnet (topology)
|
||||
|
||||
**Theorem.** For any closed triangulated surface M,
|
||||
|
||||
```
|
||||
Σᵥ (2π − Θᵥ) = 2π · χ(M)
|
||||
```
|
||||
|
||||
where χ(M) = 2 − 2g is the Euler characteristic.
|
||||
|
||||
| Surface | g | χ | Σ(2π − Θᵥ) |
|
||||
|---|---|---|---|
|
||||
| Sphere (tetrahedron, cube, …) | 0 | 2 | 4π |
|
||||
| Torus | 1 | 0 | 0 |
|
||||
| Double torus | 2 | −2 | −4π |
|
||||
|
||||
**How to check:**
|
||||
|
||||
```cpp
|
||||
#include "gauss_bonnet.hpp"
|
||||
auto defect = gauss_bonnet_sum(mesh, maps); // Σ(2π − Θᵥ)
|
||||
auto chi = mesh.euler_characteristic();
|
||||
EXPECT_NEAR(defect, 2.0 * M_PI * chi, 1e-10);
|
||||
```
|
||||
|
||||
Covered by: `cgal.GaussBonnet.*` tests in `test_phase6.cpp`.
|
||||
|
||||
---
|
||||
|
||||
## 2 — Period matrix: fundamental domain invariants
|
||||
|
||||
**Theorem (SL(2,ℤ)-reduction).** Every lattice τ ∈ ℍ has a unique representative
|
||||
in the standard fundamental domain
|
||||
|
||||
```
|
||||
F = { τ ∈ ℍ : |τ| ≥ 1, |Re(τ)| ≤ 1/2, Im(τ) > 0 }
|
||||
```
|
||||
|
||||
**After calling `compute_period_matrix(hol)`, the returned τ must satisfy:**
|
||||
|
||||
| Condition | Invariant |
|
||||
|---|---|
|
||||
| `pd.tau_reduced.imag() > 0` | τ lies in the upper half-plane |
|
||||
| `std::abs(pd.tau_reduced) >= 1.0 - 1e-10` | τ outside unit disk |
|
||||
| `std::abs(pd.tau_reduced.real()) <= 0.5 + 1e-10` | τ in vertical strip |
|
||||
|
||||
These three conditions hold for **any** closed genus-1 triangulated surface
|
||||
processed through Euclidean uniformization — they are topology, not geometry.
|
||||
|
||||
Covered by: `cgal.PeriodMatrix.TauInFundamentalDomain_*` tests in `test_phase7.cpp`.
|
||||
|
||||
---
|
||||
|
||||
## 3 — Square-symmetric torus
|
||||
|
||||
**Setup.** Take a torus mesh with 4-fold rotational symmetry around the z-axis
|
||||
(e.g. `code/data/off/torus_4x4.off`, which has M=4 columns of vertices).
|
||||
|
||||
**Expected.** The symmetry group Z₄ acts conformally. Conformal automorphisms
|
||||
of the torus correspond to SL(2,ℤ) symmetries of τ. The unique fixed point of
|
||||
a rotation of order 4 in the modular group is τ = i. Therefore:
|
||||
|
||||
```
|
||||
For a mesh with exact 4-fold symmetry and uniform edge lengths:
|
||||
Re(τ) = 0 (to machine precision, by symmetry)
|
||||
Im(τ) ≈ 1 (approaches 1 as mesh is refined)
|
||||
```
|
||||
|
||||
The coarse 4×4 mesh (`torus_4x4.off`) gives Im(τ) in (0.7, 1.3) depending on
|
||||
the 3D embedding (R=2, r=1 torus of revolution has unequal inner/outer edge lengths).
|
||||
The uniformization algorithm finds the conformal class of the *abstract* metric
|
||||
encoded in the edge lengths.
|
||||
|
||||
**Manual verification** (run from the build directory after adding a small
|
||||
program or reading from the test output):
|
||||
|
||||
```cpp
|
||||
ConformalMesh mesh; load_mesh(mesh, "code/data/off/torus_4x4.off");
|
||||
EuclideanMaps maps = setup_euclidean_maps(mesh);
|
||||
compute_euclidean_lambda0_from_mesh(mesh, maps);
|
||||
enforce_gauss_bonnet(mesh, maps);
|
||||
auto res = newton_euclidean(mesh, maps);
|
||||
CutGraph cg = compute_cut_graph(mesh);
|
||||
HolonomyData hol;
|
||||
euclidean_layout(mesh, res.x, maps, &cg, &hol, true);
|
||||
PeriodData pd = compute_period_matrix(hol);
|
||||
// pd.tau_reduced satisfies the fundamental domain invariants above
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4 — Hexagonal-symmetric torus
|
||||
|
||||
**Setup.** Take a torus mesh with 6-fold rotational symmetry
|
||||
(`code/data/off/torus_hex_6x6.off`, M=6).
|
||||
|
||||
**Expected.** The unique τ fixed under a rotation of order 6 in SL(2,ℤ) is
|
||||
τ = e^{iπ/3} = ½ + i√3/2. So:
|
||||
|
||||
```
|
||||
Re(τ) = 0.5 (to machine precision, by symmetry)
|
||||
Im(τ) = √3/2 ≈ 0.8660
|
||||
```
|
||||
|
||||
The coarse 6×6 torus of revolution approximates this: Re(τ) ≈ 0.5 by symmetry,
|
||||
Im(τ) approaches √3/2 as the mesh is refined toward a flat hexagonal lattice.
|
||||
|
||||
---
|
||||
|
||||
## 5 — Newton convergence rate
|
||||
|
||||
**Theorem.** Because the Euclidean and hyper-ideal energies are strictly convex
|
||||
(after gauge-fixing), Newton's method converges quadratically near the optimum.
|
||||
|
||||
**Expected:** for any mesh with up to a few hundred faces, Newton converges in
|
||||
**fewer than 30 iterations** starting from u = 0.
|
||||
|
||||
```cpp
|
||||
auto res = newton_euclidean(mesh, maps);
|
||||
EXPECT_LT(res.iterations, 30);
|
||||
EXPECT_LT(res.gradient_norm, 1e-10);
|
||||
```
|
||||
|
||||
Covered by: `cgal.EuclideanPipeline.ConvRates_*` and similar tests.
|
||||
|
||||
---
|
||||
|
||||
## 6 — Gradient check (finite differences)
|
||||
|
||||
For each functional F(u), the gradient G = ∂F/∂u is verified by:
|
||||
|
||||
```
|
||||
|G(u)ᵢ − (F(u + εeᵢ) − F(u − εeᵢ)) / (2ε)| < 1e-6
|
||||
```
|
||||
|
||||
with ε = 1e-5. This check is run **inside the test suite** for all three
|
||||
geometries (Euclidean, Spherical, HyperIdeal) at u = 0 and at random u.
|
||||
|
||||
Relevant test suites:
|
||||
```
|
||||
cgal.EuclideanFunctional.GradientCheck_*
|
||||
cgal.SphericalFunctional.GradientCheck_*
|
||||
cgal.HyperIdealFunctional.GradientCheck_*
|
||||
```
|
||||
|
||||
A failing gradient check means the energy and its derivative are inconsistent —
|
||||
the Newton solver will converge to the wrong point.
|
||||
|
||||
---
|
||||
|
||||
## 7 — Holonomy composition (Möbius maps)
|
||||
|
||||
For a closed surface, the composition of holonomies around any contractible cycle
|
||||
must be the identity. In genus 1 with a single handle:
|
||||
|
||||
```
|
||||
T₁ · T₂ · T₁⁻¹ · T₂⁻¹ = Id (commutator = Id for a torus)
|
||||
```
|
||||
|
||||
because π₁(T²) = ℤ × ℤ is abelian.
|
||||
|
||||
For genus g ≥ 2, the fundamental group is non-abelian and this check does not hold,
|
||||
but the representation ρ: π₁(Σ_g) → SU(1,1) must still satisfy the relation
|
||||
|
||||
```
|
||||
[T₁, T₂] · [T₃, T₄] · … = Id (product of g commutators = Id)
|
||||
```
|
||||
|
||||
These are the **holonomy consistency** checks implemented in `test_phase7.cpp`
|
||||
(`cgal.HolonomyData.*`).
|
||||
|
||||
---
|
||||
|
||||
## 8 — Checklist for an independent reviewer
|
||||
|
||||
Run these in order to validate the implementation:
|
||||
|
||||
- [ ] `ctest --test-dir build -R cgal --output-on-failure` → 170 tests pass, 11 skip
|
||||
- [ ] `cgal.GaussBonnet.*` all pass → topology is correctly read from mesh
|
||||
- [ ] `cgal.EuclideanFunctional.GradientCheck_*` pass → energy = integral of gradient
|
||||
- [ ] `cgal.PeriodMatrix.TauInFundamentalDomain_*` pass → SL(2,ℤ) reduction correct
|
||||
- [ ] `cgal.MobiusMap.Compose_*` and `Inverse_*` pass → Möbius arithmetic correct
|
||||
- [ ] `cgal.HolonomyData.*` pass → holonomy loops close up
|
||||
|
||||
All of the above are **deterministic, analytic tests** — no mesh loading, no
|
||||
file I/O, no floating-point non-determinism beyond standard IEEE-754.
|
||||
Reference in New Issue
Block a user