|
conformallab++ 0.7.0
Discrete conformal maps on triangle meshes — C++17 reimplementation of ConformalLab (TU Berlin)
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
conformallab++ is a C++17 reimplementation of ConformalLab — Stefan Sechelmann's Java research library for discrete conformal geometry (TU Berlin, ~850 commits, v1.0.0 2018). The algorithmic foundation is his dissertation:
Stefan Sechelmann — Variational Methods for Discrete Surface Parameterization: Applications and Implementation, TU Berlin 2016. DOI: 10.14279/depositonce-5415 · CC BY-SA 4.0
The long-term goal is a CGAL package — a submission to the CGAL library that brings discrete conformal maps (hyper-ideal, spherical, Euclidean) to the CGAL ecosystem using CGAL::Surface_mesh as the underlying halfedge data structure, with a traits-class design compatible with arbitrary CGAL-conforming mesh types.
The project has four distinct phase blocks (updated 2026-05-22):
All code, comments, documentation, commit messages, and test descriptions must be in English. The project is intended for international collaboration and CGAL submission. Existing German-language comments in older files should be replaced with English when editing those files.
All source lives under code/. Three build modes:
-DWITH_CGAL=ON automatically enables -DWITH_VIEWER=ON, which pulls in GLFW and requires wayland-scanner. Never use this in headless CI.
All algorithms live in code/include/*.hpp. There is no compiled library. The three CMake targets (conformallab_tests, conformallab_cgal_tests, conformallab_core) compile headers directly from their .cpp entry points. To add a new algorithm: create a .hpp in code/include/, add a test in code/tests/cgal/, and register the test file in code/tests/cgal/CMakeLists.txt.
conformal_mesh.hpp defines the core type:
This replaces the Java CoHDS (half-edge data structure) and its intrusive CoVertex/CoEdge/CoFace types. Data is attached via named CGAL property maps instead of intrusive fields:
| Property map name | Type | Meaning |
|---|---|---|
| "v:lambda" | double per vertex | log scale factor (conformal variable uᵢ) |
| "v:theta" | double per vertex | target cone angle Θᵥ |
| "v:idx" | int per vertex | solver DOF index; -1 = pinned/boundary |
| "e:alpha" | double per edge | intersection angle αᵢⱼ (hyperbolic only) |
| "f:type" | int per face | geometry type (0=Euclidean, 1=Hyperbolic, 2=Spherical) |
CGAL_DISABLE_GMP and CGAL_DISABLE_MPFR are defined for all CGAL targets — the library deliberately uses Simple_cartesian<double> (floating-point, no exact arithmetic) because conformal geometry does not require exact predicates.
Each model has its own Maps struct that bundles all property maps, plus a functional, optional Hessian, Newton solver, and (since v0.9.0) a CGAL public-API entry function:
| Model | Space | DOFs | Maps struct | Key headers | Newton function | CGAL entry |
|---|---|---|---|---|---|---|
| Euclidean | ℝ² | vertex | EuclideanMaps | euclidean_functional.hpp, euclidean_hessian.hpp | newton_euclidean() | discrete_conformal_map_euclidean() |
| Spherical | S² | vertex | SphericalMaps | spherical_functional.hpp, spherical_hessian.hpp | newton_spherical() | discrete_conformal_map_spherical() |
| Hyper-ideal | H² (Poincaré disk) | vertex + edge | HyperIdealMaps | hyper_ideal_functional.hpp, hyper_ideal_hessian.hpp (block-FD, Phase 9b) | newton_hyper_ideal() | discrete_conformal_map_hyper_ideal() |
| CP-Euclidean (BPS 2010) | face-based circle packing | face | CPEuclideanMaps | cp_euclidean_functional.hpp | newton_cp_euclidean() | discrete_circle_packing_euclidean() |
| Inversive-Distance (Luo 2004) | vertex-based circle packing | vertex | InversiveDistanceMaps | inversive_distance_functional.hpp | newton_inversive_distance() | discrete_inversive_distance_map() |
DOF-assignment patterns:
After compute_*_lambda0_from_mesh() the original vertex positions are no longer used — all subsequent computation is in log-length/scale-factor space.
Gradient sign convention differs across the five models:
Hessian sign and solver per model:
When SimplicialLDLT fails (rank-deficient H — gauge mode on a closed mesh without pinned vertex/face), the solver automatically retries with Eigen::SparseQR to find the minimum-norm step orthogonal to the null space. Public API: solve_linear_system(H, rhs, &used_fallback).
BFS-trilateration with a priority min-heap on BFS depth (depth = max(depth[src], depth[tgt]) + 1). Root face = largest 3-D area face. This minimises trilateration error accumulation compared to simple BFS.
Key output fields:
MobiusMap is defined in layout.hpp: T(z) = (az+b)/(cz+d). Key methods: from_three() (fit to 3 point correspondences via 3×3 complex linear system), compose(), inverse(), apply(Vector2d).
| Header | Java original | Key reference |
|---|---|---|
| hyper_ideal_geometry.hpp | HyperIdealGeometry.java | Springborn (2020) — ζ₁₃/ζ₁₄/ζ₁₅ functions |
| euclidean_hessian.hpp | EuclideanHessian.java | Pinkall & Polthier (1993) — cotangent Laplacian |
| spherical_hessian.hpp | SphericalHessian.java | ∂α/∂u from spherical law of cosines |
| cut_graph.hpp | CuttingUtility.java | Erickson & Whittlesey (SODA 2005) — tree-cotree |
| period_matrix.hpp | PeriodMatrixUtility.java | Sechelmann (2016) §4 — SL(2,ℤ) reduction |
| gauss_bonnet.hpp | (distributed across Java) | Gauss–Bonnet: Σ(2π−Θᵥ) = 2π·χ(M) |
The Java library under de.varylab.discreteconformal contains these items not yet in C++:
| Java class | Planned C++ header | Phase |
|---|---|---|
| InversiveDistanceFunctional | inversive_distance_functional.hpp | 9a |
| Analytic HyperIdeal Hessian | hyper_ideal_hessian.hpp (replace FD) | 9b |
| 4g-polygon boundary walk in FundamentalDomainUtility | fundamental_domain.hpp (extend) | 9c |
| DiscreteHarmonicFormUtility | Phase 10a prerequisite | 10 |
| DiscreteHolomorphicFormUtility | Phase 10a | 10 |
| HomologyUtility, CanonicalBasisUtility | Phase 10 | 10 |
When porting a Java class, locate the original in de.varylab.discreteconformal.* at github.com/varylab/conformallab and use it as the reference implementation.
This is used in virtually every Newton convergence test — it avoids hardcoding specific angle values.
All new functionals must have a gradient-check test before being considered complete.
Two jobs in .gitea/workflows/cpp-tests.yml:
| Job | CMake flags | Deps | Triggers on |
|---|---|---|---|
| test-fast | (none) | Eigen + GTest only | all branches |
| test-cgal | -DWITH_CGAL_TESTS=ON | + Boost | pull requests only |
Runner: eulernest — self-hosted Raspberry Pi, ARM64, Ubuntu 22.04. Docker image: git.eulernest.eu/conformallab/ci-cpp:latest. test-cgal needs test-fast to pass first (needs: test-fast).
Expected results: full test suite passing, 0 skipped, 0 failed. The canonical counts live in doc/api/tests.md — do not hardcode them anywhere else (see doc/release-policy.md).
Current release: v0.9.0 (tag on main, released 2026-05-22). Phases 1–9a complete, Phase 8b-Lite CGAL API surface complete (all 5 DCE models reachable via <CGAL/Discrete_*.h>), Phase 9b block-FD HyperIdeal Hessian shipped (~96× speed-up). Next planned milestones: Phase 9c (4g-polygon, genus g > 1) and Phase 9b-analytic (Schläfli identity). See doc/release-policy.md for the version-tag policy and doc/roadmap/phases.md for the phase plan.
The CGAL-package architecture was frozen on 2026-05-19. Full design: doc/api/cgal-package.md. Key decisions:
| Decision | Choice |
|---|---|
| Submission to upstream CGAL | Pre-submission-ready, not bound. 12+ months horizon. |
| License | MIT preserved (no LGPL switch). |
| Mesh-type flexibility | Generic FaceGraph + HalfedgeGraph in target design; MVP starts Surface_mesh-only. |
| Parameter style | Named Parameters (CGAL::parameters::...). |
| Default kernel | Simple_cartesian<double> (status quo). |
| Backward compatibility | Dual-layer wrapper — code/include/*.hpp stays as implementation, include/CGAL/*.h is thin wrapper. No algorithm duplication. |
| Implementation strategy | Hybrid MVP — minimum Phase 8 (traits + one wrapper) first, then Phase 9 in full, then Phase 8 extensions only on concrete demand. |
| Phase-8 MVP acceptance test | Phase 9a (Inversive-Distance) as the first new client of the new traits API. |
Phase 8 extensions (8a.2 generic FaceGraph, 8c full Doxygen manuals, 8d CGAL-format tests, 8e YAML pipeline) are deferred to on-demand status — no speculative architecture for an uncertain submission.
Root-level files added at v0.7.0:
Before claiming something "ports X from Java", verify empirically:
If zero matches, the work is new research — add it to doc/roadmap/research-track.md with primary literature citations, not to doc/roadmap/java-parity.md.
The 2026-05-21 audit found four pre-existing mis-labels:
| Item | Wrong claim | Reality |
|---|---|---|
| InversiveDistanceFunctional | "Java port (Luo 2004)" | No such Java class exists |
| HyperIdeal Hessian (FD) | "Phase 4a" | Research — Java has hasHessian()==false |
| HyperIdeal Hessian (analytic) | "Phase 9b port" | Research — derivation via Schläfli 1858 |
| Tutorial framing | "ports `InversiveDistanceFunctional.java`" | Implementation from Luo 2004 + Glickenstein 2011 |
All four are corrected as of this commit. Future contributors must follow the empirical verification rule above before any new claim.
24 documents across 6 categories. Read the relevant one before reasoning from scratch — do not hallucinate content that is already written down.
| Question | Document |
|---|---|
| What problem does this library solve mathematically? | doc/math/discrete-conformal-theory.md |
| How do the three geometry modes differ (Euclidean/Spherical/HyperIdeal)? | doc/math/geometry-modes.md |
| What analytic invariants can be used to validate correctness? | doc/math/validation.md |
| What are the exact ctest commands with expected terminal output? | doc/math/validation-protocol.md |
| What is the O() complexity and how does it scale with mesh size? | doc/math/complexity.md |
| Which papers are referenced by which header? | doc/math/references.md |
| How does conformallab++ compare to libigl, CGAL, geometry-central, pmp-library? | doc/math/software-landscape.md |
| What is unique about conformallab++ (novelty, target audience)? | doc/math/novelty-statement.md |
| Question | Document |
|---|---|
| Full pipeline diagram and data-flow overview | doc/architecture/overall_pipeline.md |
| Directory tree, build targets, file organisation | doc/architecture/project-structure.md |
| Key architectural decisions and their rationale | doc/architecture/design-decisions.md |
| Detailed comparison with geometry-central (CMU): overlap, adoption, scientific value | doc/architecture/geometry-central-comparison.md |
| Phase 9a validation report (CP-Euclidean port + Luo-inversive-distance literature check) | doc/architecture/phase-9a-validation.md |
| Question | Document |
|---|---|
| All 24 public headers with descriptions | doc/api/headers.md |
| Full pipeline API for all three geometries | doc/api/pipeline.md |
| What does each processing unit require/provide (contracts)? | doc/api/contracts.md |
| How to add a new functional / geometry mode / port from Java | doc/api/extending.md |
| Per-suite breakdown and counts (single source of truth) | doc/api/tests.md |
| Phase 8 CGAL package design + Declarative YAML pipeline spec | doc/api/cgal-package.md |
| Question | Document |
|---|---|
| Declarative YAML pipeline: token vocabulary, 5 examples, validation algorithm | doc/concepts/declarative-pipeline.md |
| Question | Document |
|---|---|
| Phases 1–10 with status and sub-tasks | doc/roadmap/phases.md |
| Which Java classes are ported, which are planned, which are skipped? | doc/roadmap/java-parity.md |
| New research items (beyond Java) — citations, acceptance criteria | doc/roadmap/research-track.md |
| Question | Document |
|---|---|
| Build modes, single-test invocation, CLI, Docker image rebuild | doc/getting-started.md |
| Step-by-step: port the Inversive Distance functional (Phase 9a template) | doc/tutorials/add-inversive-distance.md |
| Language policy, test standards, release flow | doc/contributing.md |
| Versioning rules + release process + single-source-of-truth list | doc/release-policy.md |
geometry-central (Keenan Crane, CMU) implements the same discrete conformal equivalence problem (Gillespie, Springborn & Crane, SIGGRAPH 2021) but uses Ptolemaic flips on intrinsic triangulations instead of Newton on the original mesh. It has no period matrix, holonomy, or spherical geometry mode. The shared mathematical core (Springborn 2020) means cross-validation is meaningful. Full analysis: doc/architecture/geometry-central-comparison.md. Optional adoption roadmap (GC-1/2/3): doc/roadmap/phases.md (Optional section).