Files
ConformalLabpp/README.md
Tarik Moussa a4c2a89e7e feat(phase3c): port SphericalFunctional onto ConformalMesh; update README
New headers:
- spherical_geometry.hpp: spherical arc length l(λ) and half-angle formula
  for interior angles of a spherical triangle (SphericalFaceAngles struct)
- spherical_functional.hpp: SphericalMaps bundle, setup/assign DOF helpers,
  compute_lambda0_from_mesh(), gradient (Θ_v − Σα_v; Schläfli edge formula),
  energy via 10-point Gauss-Legendre path integral, gradient_check_spherical()

Updated:
- mesh_builder.hpp: add make_spherical_tetrahedron() (vertices on unit sphere)
  and make_octahedron_face() (single right-angled spherical triangle)
- tests/cgal/CMakeLists.txt: enable test_spherical_functional.cpp
- README.md: rewrite for CGAL-package goal, two test targets, all headers,
  updated project tree, Phase progress table, key design decisions

Tests (cgal.SphericalFunctional.*): 8 active + 1 skip
- OctaFaceAnglesAreRightAngles, SpherTetAngleSumExceedsPi
- GradientCheck_{OctaFaceVertex, SpherTetVertex, SpherTetAllDofs,
  SpherFan4Vertex, MixedPinnedVertices}
- AnglesFiniteAtKnownPoint
All 30 cgal.* tests pass (2 @Ignore skips).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-12 00:01:24 +02:00

198 lines
8.4 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 complete. Core geometry (Clausen, hyper-ideal, spherical) and the CGAL mesh infrastructure are in place. Solvers and full CLI pipeline are coming next.
---
## 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 | 🔜 Phase 4 |
| 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: **30 tests pass, 2 skipped** (the two `@Ignore` Hessian stubs).
### 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 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 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 # 8 spherical 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` | 8 | Angle formula correctness + gradient checks on spherical meshes |
---
## 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/
```
---
## License
conformallab++ is released under the MIT License (see [LICENSE](LICENSE)).