Files
ConformalLabpp/README.md
Tarik Moussa 8c353bb884 feat(phase3d+3e): port EuclideanCyclicFunctional + add SphericalFunctional gauge-fix
Phase 3d — EuclideanCyclicFunctional:
  • euclidean_geometry.hpp: t-value / atan2 corner-angle formula with
    centering trick (μ = (Λ̃₁₂+Λ̃₂₃+Λ̃₃₁)/6) for numerical stability
  • euclidean_functional.hpp: EuclideanMaps bundle, gradient (G_v = Θ_v − Σα_v,
    G_e = α_opp⁺ + α_opp⁻ − φ_e), 10-point GL path-integral energy,
    gradient_check_euclidean — identical halfedge convention to SphericalFunctional
  • test_euclidean_functional.cpp: 11 tests (1 skip) covering angle formula,
    right-isosceles triangle, angle sum = π, degenerate detection, gradient
    checks on triangle/quad-strip/tetrahedron/fan-5/mixed-pinned, NaN check

Phase 3e — Spherical gauge-fix:
  • spherical_gauge_shift(): Newton + backtracking line search to find t*
    where ΣG_v(x + t·1) = 0 (maximises E along the global scale direction);
    bisection used when sign change is detectable, Newton+backtrack otherwise
  • apply_spherical_gauge(): in-place wrapper
  • 3 new tests: GaugeFix_SpherTetVertexZerosSumGv, GaugeFix_ApplyInPlace,
    GaugeFix_AlreadyAtGaugeReturnsTNearZero

Total: 45 cgal tests pass, 3 skipped (@Ignore Hessian stubs, one per functional)

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

11 KiB
Raw Blame History

conformallab++

conformallab++ is a modern C++ reimplementation of the 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: Phasen 3d + 3e abgeschlossen. Alle drei Kern-Geometrien (Hyper-Ideal, Sphärisch, Euklidisch) plus Sphärischer Gauge-Fix sind auf ConformalMesh portiert. 45 Tests, 3 skipped (Hessian-Stubs). Nächster Schritt: Phase 3f (Hessian) → Phase 4 (Newton-Solver) — siehe 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
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

git clone https://codeberg.org/TMoussa/ConformalLabpp
cd ConformalLabpp

Tests only (CI default — no system deps needed)

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)

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)

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:

docker buildx build \
  --platform linux/arm64 \
  -f .gitea/docker/Dockerfile.ci-cpp \
  -t git.eulernest.eu/conformallab/ci-cpp:latest \
  --push \
  .gitea/docker/

Roadmap

Die Phasen 13 sind abgeschlossen. Die folgenden Schritte schließen Phase 3 ab und bereiten Phase 4 (Solver) vor. Die Zeitangaben sind grobe Schätzungen.


Phase 3d  EuclideanCyclicFunctional portieren          ✅ abgeschlossen
          → euclidean_geometry.hpp: t-Wert / atan2 Winkelformel
          → euclidean_functional.hpp: Energie + Gradient auf ConformalMesh
          → 11 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
          → 3 neue Tests: ZerosSumGv, ApplyInPlace, AlreadyAtGauge

Phase 3f  Hessian (Sphärisch → Euklidisch)            (23 Tage)
          → Analytischer Hessian = Kotangenten-Laplace-Operator
          → CGAL::Weights::cotangent_weight() als Basis für
            die Kantenbeiträge nutzen (bereits in CGAL 6.0 enthalten)
          → Entsperrt Newton-/Trust-Region-Verfahren
          → Reihenfolge: Sphärisch zuerst (kleinster Hessian),
            dann Euklidisch

Phase 3g  PI-Konstante konsolidieren                  (< 1 Stunde)
          → conformallab::PI in hyper_ideal_geometry.hpp und
            lokales pi in hyper_ideal_utility.hpp zusammenführen
          → Einzelne constants.hpp oder in conformal_mesh.hpp

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).