Files
ConformalLabpp/README.md
Tarik Moussa 5841646017 docs: update README — Phase 3 vollständig abgeschlossen (62 Tests)
Mark all Phase 3 sub-phases (3a–3g) as done in the roadmap.
Add euclidean_hessian and spherical_hessian to the feature table.
Update status banner: 62 tests, Phase 4 is next.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-05-12 17:25:26 +02:00

263 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# conformallab++
conformallab++ is a modern C++ reimplementation of the [ConformalLab](https://github.com/sechel/conformallab) software by Stefan Sechelmann for experiments in discrete conformal geometry and related mesh transformations.
The long-term goal is a **CGAL package** that brings discrete conformal maps (hyper-ideal, spherical, Euclidean) to the CGAL ecosystem using `CGAL::Surface_mesh` as the underlying half-edge data structure.
> **Status:** Phase 3 vollständig abgeschlossen. Alle drei Kern-Geometrien (Hyper-Ideal, Sphärisch, Euklidisch) plus analytische Hessians (Kotangenten-Laplace) sind auf `ConformalMesh` portiert. **62 Tests, 3 skipped**. Nächster Schritt: Phase 4 (Newton-Solver) — siehe [Roadmap](#roadmap).
---
## Features
| Area | Status |
|------|--------|
| Clausen / Lobachevsky / ImLi₂ functions | ✅ Phase 1 |
| Hyper-ideal geometry (ζ, lᵢⱼ, αᵢⱼ, σᵢ, σᵢⱼ) | ✅ Phase 2 |
| Hyper-ideal functional (energy + gradient, CGAL mesh) | ✅ Phase 3b |
| Spherical functional (energy + gradient, CGAL mesh) | ✅ Phase 3c |
| CGAL `Surface_mesh` infrastructure + mesh builders | ✅ Phase 3a |
| Euclidean functional (energy + gradient, CGAL mesh) | ✅ Phase 3d |
| Spherical gauge-fix (scale gauge for closed surfaces) | ✅ Phase 3e |
| Euclidean Hessian (cotangent-Laplace operator) | ✅ Phase 3f |
| Spherical Hessian (∂α/∂u from law of cosines) | ✅ Phase 3f |
| Solvers (Newton, gradient flow) | 🔜 Phase 4 |
| XML serialisation / mesh I/O | 🔜 Phase 5 |
| Full CLI app | 🔜 Phase 5 |
---
## Build modes
| Mode | CMake flag | What gets built | CI |
|------|-----------|-----------------|-----|
| **Tests only** (default) | *(none)* | `conformallab_tests` · Eigen + GTest | ✅ runs automatically |
| **CGAL tests** | `-DWITH_CGAL=ON` | `conformallab_cgal_tests` · above + CGAL + system Boost | local only |
| **Viewer** | `-DWITH_VIEWER=ON` | `viewer` library · libigl / GLFW / GLAD | local only |
| **Full app** | `-DWITH_CGAL=ON` | `conformallab_core` CLI · all of the above | local only |
External dependencies are bundled as tarballs in `code/deps/tarballs/` and extracted lazily at CMake configure time (GTest is fetched from GitHub via `FetchContent`).
**Note on Boost:** `-DWITH_CGAL=ON` requires a system-installed Boost (header-only use by CGAL). The default `Tests only` mode needs no Boost.
---
## Prerequisites
| Tool | Minimum version |
|------|----------------|
| C++ compiler (GCC or Clang) | C++17 |
| CMake | 3.20 |
| Boost headers | 1.70 *(only with `-DWITH_CGAL=ON`)* |
---
## Getting started
```bash
git clone https://codeberg.org/TMoussa/ConformalLabpp
cd ConformalLabpp
```
### Tests only (CI default — no system deps needed)
```bash
cmake -S code -B build
cmake --build build --target conformallab_tests -j$(nproc)
ctest --test-dir build --output-on-failure
```
### CGAL mesh + functional tests (requires system Boost)
```bash
cmake -S code -B build -DWITH_CGAL=ON
cmake --build build --target conformallab_cgal_tests -j$(nproc)
ctest --test-dir build -R "^cgal\." --output-on-failure
```
Expected output: **45 tests pass, 3 skipped** (the three `@Ignore` Hessian stubs, one per functional).
### Full CLI app (CGAL + viewer)
```bash
cmake -S code -B build -DWITH_CGAL=ON
cmake --build build -j$(nproc)
./code/bin/conformallab_core --input data/off/example.off --show
```
---
## Public headers (`code/include/`)
| Header | Description |
|--------|-------------|
| `clausen.hpp` | Clausen integral Cl₂, Lobachevsky Л, ImLi₂ |
| `hyper_ideal_geometry.hpp` | Pure-math ζ functions, lᵢⱼ, αᵢⱼ, σᵢ, σᵢⱼ |
| `hyper_ideal_utility.hpp` | Tetrahedron volume (Meyerhoff / KolpakovMednykh) |
| `hyper_ideal_functional.hpp` | Hyper-ideal energy + gradient on `ConformalMesh` |
| `spherical_geometry.hpp` | Spherical arc length, half-angle angle formula |
| `spherical_functional.hpp` | Spherical energy + gradient + gauge-fix on `ConformalMesh` |
| `euclidean_geometry.hpp` | Euclidean corner-angle formula (t-value / atan2) |
| `euclidean_functional.hpp` | Euclidean energy + gradient on `ConformalMesh` |
| `conformal_mesh.hpp` | `ConformalMesh` = `CGAL::Surface_mesh<Point3>`, index types, property-map helpers |
| `mesh_builder.hpp` | Factory meshes: triangle, tetrahedron, quad strip, fan, spherical tetrahedron, octahedron face |
| `discrete_elliptic_utility.hpp` | Discrete elliptic integrals |
| `matrix_utility.hpp` | Small linear-algebra helpers |
| `projective_math.hpp` | Projective geometry utilities |
---
## Project structure
```
code/
├── include/
│ ├── conformal_mesh.hpp # CGAL mesh type + property-map helpers
│ ├── mesh_builder.hpp # make_triangle / make_tetrahedron / …
│ ├── hyper_ideal_geometry.hpp # ζ, lᵢⱼ, αᵢⱼ — pure math
│ ├── hyper_ideal_functional.hpp # HyperIdealFunctional on ConformalMesh
│ ├── spherical_geometry.hpp # spherical arc length + angles
│ ├── spherical_functional.hpp # SphericalFunctional + gauge-fix on ConformalMesh
│ ├── euclidean_geometry.hpp # Euclidean corner-angle formula (t-value)
│ ├── euclidean_functional.hpp # EuclideanCyclicFunctional on ConformalMesh
│ ├── clausen.hpp # Clausen / Lobachevsky / ImLi₂
│ └── hyper_ideal_utility.hpp # Tetrahedron volumes
├── src/
│ ├── apps/v0/ # conformallab_core CLI (requires WITH_CGAL)
│ └── viewer/ # simple_viewer (requires WITH_VIEWER)
├── tests/
│ ├── CMakeLists.txt
│ ├── *.cpp # conformallab_tests (no CGAL)
│ └── cgal/
│ ├── CMakeLists.txt
│ ├── test_conformal_mesh.cpp # 14 mesh infrastructure tests
│ ├── test_hyper_ideal_functional.cpp # 6 hyper-ideal gradient checks
│ ├── test_spherical_functional.cpp # 11 spherical gradient + gauge-fix checks
│ └── test_euclidean_functional.cpp # 11 Euclidean gradient checks
└── deps/
├── tarballs/ # bundled dependency archives
├── eigen-3.4.0/ # header-only linear algebra (always extracted)
├── CGAL-6.1.1/ # header-only geometry (extracted with WITH_CGAL)
├── libigl-2.6.0/ # header-only viewer toolkit (extracted with WITH_VIEWER)
├── glfw-3.4/ # windowing (extracted with WITH_VIEWER)
├── libigl-glad/ # OpenGL loader (extracted with WITH_VIEWER)
└── single_includes/ # CLI11, json.hpp
```
---
## Test suites
### `conformallab_tests` (always built, runs in CI)
Pure-math tests requiring only Eigen:
- Clausen function, Lobachevsky function, ImLi₂
- Hyper-ideal geometry (ζ₁₃, ζ₁₄, ζ₁₅, lᵢⱼ, αᵢⱼ)
- Tetrahedron volume formulas (Meyerhoff, KolpakovMednykh)
### `conformallab_cgal_tests` (built with `-DWITH_CGAL=ON`)
CGAL `Surface_mesh` tests (test prefix `cgal.`):
| Suite | Tests | Description |
|-------|-------|-------------|
| `ConformalMeshTopology` | 4 | Euler characteristic, vertex/edge/face counts |
| `ConformalMeshTraversal` | 4 | Halfedge iteration, valence, opposite-halfedge |
| `ConformalMeshProperties` | 5 | Property maps: λ, θ, idx, α, geometry type |
| `ConformalMeshValidity` | 1 | CGAL validity check for all factory meshes |
| `HyperIdealFunctional` | 6 | Finite-difference gradient checks on triangle, tetrahedron, quad strip, fan |
| `SphericalFunctional` | 11 | Angle formula + gradient checks on spherical meshes + 3 gauge-fix tests |
| `EuclideanFunctional` | 11 | Angle formula + gradient checks on Euclidean meshes (triangle, quad strip, fan, tetrahedron) |
---
## Key design decisions
**CGAL as CoHDS replacement.** `CGAL::Surface_mesh<Point3>` replaces the Java `CoHDS` half-edge data structure. Vertex/edge/face/halfedge descriptors are `Vertex_index`, `Edge_index`, `Face_index`, `Halfedge_index` (typed integers, not raw handles).
**Property maps.** `mesh.add_property_map<Vertex_index, double>("v:lambda", 0.0)` replaces the Java adapter/decorator pattern. Multiple maps can be attached to one mesh without subclassing.
**Energy parameterisation.** Both functionals use a **DOF vector** `x` indexed by `v_idx[v]` / `e_idx[e]` (1 = pinned). This matches the Java `FunctionalTest` gradient-check convention.
**Spherical edge gradient.** For the spherical parameterisation where `Λᵢⱼ = λ°ᵢⱼ + uᵢ + uⱼ + λₑ` (additive edge DOF), the Schläfli identity gives `∂E/∂λₑ = (2α_opp S_f)/2` per face (Euclidean limit: `S_f = π`, recovering the familiar `α_opp⁺ + α_opp⁻ π`).
---
## CI
Tests run automatically on push to `main`, `dev`, and `claude/**` branches via a self-hosted Gitea Actions runner (`eulernest`, ARM64 Raspberry Pi). The pipeline uses a minimal Docker image (`git.eulernest.eu/conformallab/ci-cpp:latest`) with cmake, g++, git, and Node.js 20 pre-installed. **Only `conformallab_tests` runs in CI** (no Boost/CGAL dependency in the CI image).
The Dockerfile for the CI image lives in `.gitea/docker/Dockerfile.ci-cpp`. Build and push it once whenever the image needs updating:
```bash
docker buildx build \
--platform linux/arm64 \
-f .gitea/docker/Dockerfile.ci-cpp \
-t git.eulernest.eu/conformallab/ci-cpp:latest \
--push \
.gitea/docker/
```
---
## Roadmap
Phase 3 ist vollständig abgeschlossen. Phase 4 (Newton-Solver) ist der nächste Schritt.
Die Zeitangaben sind grobe Schätzungen.
---
```
Phase 3a CGAL Surface_mesh Infrastruktur ✅ abgeschlossen
→ conformal_mesh.hpp, mesh_builder.hpp
→ 14 Tests: Topologie, Traversal, Properties, Validity
Phase 3b HyperIdealFunctional portieren ✅ abgeschlossen
→ hyper_ideal_functional.hpp: Energie + Gradient
→ 6 Tests (1 skipped): Gradient-Checks, FD-Tests
Phase 3c SphericalFunctional portieren ✅ abgeschlossen
→ spherical_functional.hpp: Energie + Gradient
→ Tests: Winkelformel, Gradient-Checks
Phase 3d EuclideanCyclicFunctional portieren ✅ abgeschlossen
→ euclidean_functional.hpp: Energie + Gradient auf ConformalMesh
→ Tests: Winkelformel, Gradient-Checks, NaN-Test, Fan, Mixed-Pinned
Phase 3e Gauge-Fix für SphericalFunctional ✅ abgeschlossen
→ spherical_gauge_shift() + apply_spherical_gauge() in
spherical_functional.hpp — Newton + Backtracking
→ Tests: ZerosSumGv, ApplyInPlace, AlreadyAtGauge
Phase 3f Analytische Hessians ✅ abgeschlossen
→ euclidean_hessian.hpp: Kotangenten-Laplace (PinkallPolthier 1993)
mit korrektem 1/2-Normierungsfaktor; 8 Tests
→ spherical_hessian.hpp: ∂α_i/∂u_j direkt aus sphärischem
Cosinussatz abgeleitet + Chain-Rule mit ∂l/∂λ = tan(l/2); 8 Tests
→ Erkenntnis: Sphärische Energie ist konkav (H ist NSD), nicht konvex
Phase 3g PI-Konstante konsolidieren ✅ abgeschlossen
→ constants.hpp mit conformallab::PI und TWO_PI
→ 5 Dateien bereinigt; PI_SPHER-Alias rückwärtskompatibel
Phase 4a Minimaler Newton-Solver (12 Tage)
→ Eigen SimplicialLDLT (bereits Projektabhängigkeit)
→ Newton-Schritt: Δx = H⁻¹·g mit Hessian aus 3f
→ Kein externer PETSc-Solver nötig für erste Tests
→ Konvergenzkriterium: ||g||∞ < tol
Phase 4b CGAL::IO für Mesh-Import/Export (< 1 Tag)
→ CGAL::IO::read_OBJ / write_OBJ auf Surface_mesh:
null Eigenentwicklung, sofort nutzbar
→ Ermöglicht Round-Trip-Tests gegen Java-Referenz-Meshes
→ Mittelfristig: CGAL::IO::read_OFF für .off-Dateien
(ersetzt Java-XML-Serialisierung für Testzwecke)
```
---
## License
conformallab++ is released under the MIT License (see [LICENSE](LICENSE)).