Files
ConformalLabpp/doc/roadmap/porting-status.md
Tarik Moussa 039cc26e36
Some checks failed
C++ Tests / test-fast (push) Successful in 1m58s
C++ Tests / test-fast (pull_request) Successful in 2m33s
API Docs / doc-build (pull_request) Successful in 51s
C++ Tests / test-cgal (push) Has been skipped
C++ Tests / test-cgal (pull_request) Failing after 10m32s
Phase 8b-Lite: pipe-operator chaining for named parameters
Adds `operator|` in `namespace CGAL` so package-local named parameters
can be combined left-to-right without modifying CGAL upstream:

    auto p = CGAL::parameters::gradient_tolerance(1e-12)
           | CGAL::parameters::max_iterations(500)
           | CGAL::parameters::output_uv_map(uv);
    CGAL::discrete_conformal_map_euclidean(mesh, p);

Why not the canonical `.a().b().c()` syntax
───────────────────────────────────────────
CGAL's standard chaining mechanism requires registering each named
parameter as a member function on `Named_function_parameters` via the
`CGAL_add_named_parameter` macro in
`CGAL/STL_Extension/internal/parameters_interface.h` — a vendored
upstream file that conformallab++ deliberately treats as read-only.

Adding member-function chainers for our package-local tags would
require either forking CGAL or modifying the vendored copy.  Neither
is acceptable for a library that wants to remain portable across
future CGAL releases.

The pipe-operator achieves the same compositional semantics via a
free function in `namespace CGAL` (so ADL finds it for
`Named_function_parameters` operands).  Implementation: rebuild the
right-hand-side `Named_function_parameters` with the left-hand-side
as its `Base`, producing an indistinguishable chain that every entry
function accepts unchanged.

Implementation: `code/include/CGAL/Conformal_map/internal/parameters.h`
lines 158-187.  The operator is constrained to right-hand-sides with
`No_property` base (i.e. fresh single-parameter packs from the helper
functions), so it never collides with any future CGAL operator on the
same type.

Tests (2 new, total Phase-8b-Lite suite 15 → 17)
────────────────────────────────────────────────
* CGALPhase8bLite.NamedParamPipe_MultipleParamsTakeEffect
    Chain three parameters; verify all three take effect (tight
    tolerance respected + UV pmap populated + iteration cap honoured).
* CGALPhase8bLite.NamedParamPipe_TwoParams
    Chain two parameters; verify max_iterations(0) blocks the loop
    even when combined with another param.

Full CGAL suite: 234/234 PASSED, 0 SKIPPED (was 232).
Total: 257/257 PASSED, 0 SKIPPED (was 255).
scripts/check-test-counts.sh: OK.

Documentation updates
─────────────────────
* doc/tutorials/add-output-uv-map.md §3.4: "Current limitation: no
  chaining" → "Chaining: use the pipe operator `|`".  Explains why
  CGAL's `.member()` syntax isn't available and shows the `|`
  workaround with a working code example.
* doc/architecture/locked-vs-flexible.md §8: chaining now flagged as
  shipped via pipe; recommended posture says `.member()` chaining
  only if a user pushes for the CGAL-canonical syntax.
* doc/roadmap/porting-status.md §5: API limitations table updated.
* doc/api/tests.md: CGALPhase8bLite row 15 → 17, total 232 → 234.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-22 13:43:52 +02:00

15 KiB
Raw Blame History

Porting status overview

Snapshot date: 2026-05-22 (commit graph at v0.9.0 + 2 open PRs).

Audience. External collaborators evaluating whether to use, extend, or contribute to conformallab++. This document is the operational truth of which Java mathematics is reachable from C++ today, with what API, and with which caveats. For the longer plan see phases.md, for the formal port-vs-research classification see research-track.md, for the cross-reference with the Java original see java-parity.md.


1. The 25 000 lines of Java in one table

de.varylab.discreteconformal
├── functional/              ~3 000 LoC   ████████████░░░░  Phase 3 + 9a  ✅
├── unwrapper/               ~3 500 LoC   ████████░░░░░░░░  Phase 5/6/7 (basic 3 modes) ✅
│                                          residual: Stereographic, CircleDomain, Koebe, CirclePattern
├── util/                    ~5 000 LoC   ████░░░░░░░░░░░░  partial — main utilities ported
│                                          residual: Homology, Holomorphic / Harmonic forms,
│                                                    FundamentalPolygon, Surgery, Cutting
├── heds/  (Co* data struct) ~3 000 LoC   ░░░░░░░░░░░░░░░░  REPLACED by CGAL::Surface_mesh ❌ intentional
├── plugin/                  ~7 000 LoC   ░░░░░░░░░░░░░░░░  SKIP (Swing UI, GLSL viewer) ❌ intentional
├── numerics/   (PETSc glue) ~1 500 LoC   ░░░░░░░░░░░░░░░░  REPLACED by Eigen ❌ intentional
├── math/, logging/, ...     ~2 000 LoC   ░░░░░░░░░░░░░░░░  REPLACED by std::* / Eigen ❌ intentional
└── total                    ~25 000 LoC

Coverage of the mathematics: about 4 500 of the 11 000 LoC of genuinely mathematical Java code is portrayed in C++ — ~41% of the maths, ~75% of the "core math we actually want" (Phase 17 + 9a + 9b together cover the algorithmically central mass).

The remaining ~6 500 LoC of port-worthy maths is catalogued in java-parity.md and broken into Phases 9c / 10a / 10b / 10b' / 11.


2. Five DCE models — operational status matrix

The library supports five discrete-conformal-equivalence models on the same CGAL::Surface_mesh<P>. All can be used from both the legacy API (code/include/*.hpp) and the CGAL public API (<CGAL/Discrete_*.h>).

Model Native space DOF location Java port? Hessian Newton CGAL entry UV out
Euclidean ℝ² vertex EuclideanCyclic 530 LoC analytic (cot-Laplace) discrete_conformal_map_euclidean Point_2
Spherical vertex Spherical 458 LoC analytic discrete_conformal_map_spherical Point_3
Hyper-ideal H² (Poincaré) vertex + edge HyperIdeal 311 LoC (no Hess) block-FD (Phase 9b, 96× speed-up); analytic planned discrete_conformal_map_hyper_ideal Point_2
CP-Euclidean (BPS) face circles face CPEuclidean 260 LoC analytic 2×2-per-edge discrete_circle_packing_euclidean N/A
Inversive Distance vertex circles vertex no Java (Luo 2004 + Glickenstein 2011 from literature) FD (analytic planned) discrete_inversive_distance_map pending

Total: 250+ tests covering all five models, 0 skipped. Per-suite breakdown: doc/api/tests.md.

What "UV out" means

The output_uv_map(pmap) named parameter, when supplied, runs the relevant *_layout() step internally and writes per-vertex coordinates into pmap — no separate user code needed. See doc/tutorials/add-output-uv-map.md.

  • Euclidean / Spherical / HyperIdeal: shipped.
  • CP-Euclidean: conceptually not applicable (face-based packing produces face-circles, not per-vertex UV — needs a separate output_circle_map design).
  • Inversive Distance: requires inversive_distance_layout() using Luo's edge-length formula ℓ² = r_i² + r_j² + 2 I_ij r_i r_j. ~3 days work, on the wishlist.

3. Topology infrastructure

Feature Status Notes
Mesh I/O (OFF / OBJ / PLY) mesh_io.hpp via CGAL::IO
GaussBonnet check & enforce gauss_bonnet.hpp
Cut graph (tree-cotree, EricksonWhittlesey) cut_graph.hpp, produces 2g seam edges
Layout / embedding (priority-BFS trilateration) ℝ² / S² / Poincaré disk
Halfedge UV (seam-aware texture atlas) layout.hpp
Möbius holonomy SU(1,1) for hyperbolic mode, genus 1
Period matrix τ ∈ + SL(2,) reduction genus 1 only
Fundamental domain (parallelogram) genus 1 only
Fundamental domain (4g-polygon) 🔲 Phase 9c — biggest remaining Java-port item
Real mesh cuts (CuttingUtility ops) 🔲 Phase 9c prerequisite

4. Solver infrastructure

Feature Status Notes
Newton with line search newton_solver.hpp, all five solvers
SimplicialLDLT + SparseQR fallback gauge-singular meshes handled automatically
Block-FD Hessian framework shipped for HyperIdeal (Phase 9b); 96× speed-up
Analytic Hessian via Schläfli 🔲 Phase 9b-analytic; derivation in hyperideal-hessian-derivation.md

5. CGAL public API (<CGAL/Discrete_*.h>)

After Phase 8a MVP + 8b-Lite (both shipped in v0.9.0):

Public header Provides
<CGAL/Discrete_conformal_map.h> discrete_conformal_map_euclidean / _spherical / _hyper_ideal + Conformal_map_result<FT>
<CGAL/Discrete_circle_packing.h> Default_cp_euclidean_traits + discrete_circle_packing_euclidean + Circle_packing_result<FT>
<CGAL/Discrete_inversive_distance.h> Default_inversive_distance_traits + discrete_inversive_distance_map
<CGAL/Conformal_layout.h> Thin re-exports of layout functions in the CGAL:: namespace
<CGAL/Conformal_map_traits.h> ConformalMapTraits concept + Default_conformal_map_traits
<CGAL/Conformal_map/internal/parameters.h> (private) Named-parameter tags

Named parameters available:

Parameter Effect
vertex_curvature_map(pmap) Per-vertex Θ targets; if omitted, "natural-theta" makes x = 0 the equilibrium
fixed_vertex_map(pmap) Gauge pin; if omitted, first vertex is pinned
gradient_tolerance(eps) Newton stop threshold (default 1e-10)
max_iterations(n) Newton iteration cap (default 200)
output_uv_map(pmap) Run layout + write per-vertex coordinates
normalise_layout(flag) Canonical post-layout normalisation (PCA / north-pole / Möbius)

Known limitations (documented for the meeting):

  1. Chaining via pipe operator. CGAL-style .a().b().c() is not yet implemented for package-local tags (would require modifying CGAL upstream). conformallab++ provides operator| instead — see code/include/CGAL/Conformal_map/internal/parameters.h and the test CGALPhase8bLite.NamedParamPipe_MultipleParamsTakeEffect. Example: gradient_tolerance(1e-12) | max_iterations(500) | output_uv_map(uv).

  2. Generic FaceGraph not yet supported. All Default traits specialise on CGAL::Surface_mesh<P> only. Adding Polyhedron_3, OpenMesh-adapter, pmp::SurfaceMesh is Phase 8a.2 — speculative, waiting on a concrete user request.

  3. CGAL submission-readiness incomplete. User_manual / PackageDescription.txt / CGAL-format tests are not yet written (Phase 8c / 8d). Required for upstream submission, not for current users.


6. What's reachable from the Java original today

Cross-reference between Java classes and their C++ port status. For the full list see java-parity.md; the table below gives the operational summary for a Java user wondering "where is X?".

Direct ports

Java C++
EuclideanCyclicFunctional euclidean_functional.hpp
SphericalFunctional spherical_functional.hpp
HyperIdealFunctional hyper_ideal_functional.hpp
HyperIdealUtility, …Geometry hyper_ideal_utility.hpp, hyper_ideal_geometry.hpp
HyperIdealHyperellipticUtility hyper_ideal_visualization_utility.hpp
CPEuclideanFunctional cp_euclidean_functional.hpp
Clausen clausen.hpp
MeshIO (jReality JRS) mesh_io.hpp (CGAL::IO, OFF/OBJ/PLY)
CuttingUtility::point_in_triangle_2d geometry_utils.hpp partial port
ConvergenceUtility::circumradius geometry_utils.hpp
HomologyUtility::compute_generators cut_graph.hpp (different algorithm: tree-cotree)
PeriodMatrixUtility (genus 1) period_matrix.hpp
UnwrapperUtility::EuclideanUnwrapper newton_euclidean() + euclidean_layout()
UnwrapperUtility::SphericalUnwrapper newton_spherical() + spherical_layout()
UnwrapperUtility::HyperbolicUnwrapper newton_hyper_ideal() + hyper_ideal_layout()

Not-yet-ported, in roadmap

Java Suggested phase Lines Notes
FundamentalPolygonUtility + CanonicalFormUtility 9c 698+532 genus > 1 fundamental domain
CuttingUtility + SurgeryUtility (full ops) 9c 584+217 real mesh-cut operations
DiscreteHarmonicFormUtility 10a 657 harmonic 1-forms
DiscreteHolomorphicFormUtility 10a 285 holomorphic differentials
CanonicalBasisUtility 10a 337 symplectic homology basis
DualityUtility, HomologyUtility (full) 10a 308+122 primal/dual cohomology
DiscreteRiemannUtility 10b 186 period matrix for genus > 1
HyperbolicCyclicFunctional 10bc 530 hyperbolic energy (different from hyper-ideal)
QuasiisothermicUtility + SinConditionApplication 10b ~1200 Lawson correspondence
StereographicUnwrapper 10b' 266 S² → atlas
KoebePolyhedron 10c 321 KAT circle packing
MobiusCenteringFunctional 10c 289 sphere pre-processing
CircleDomainUnwrapper 11c 570 multiply-connected planar regions

Intentionally not ported

  • CoHDS (half-edge data structure) — replaced by CGAL::Surface_mesh. ~3 000 Java LoC saved.
  • plugin/* Swing UI — out of scope; C++ project is a library, not an application.
  • unwrapper/numerics/* PETSc/Tao wrappers — replaced by Eigen, which is header-only and bundled.
  • math/CP1, math/Cn, … — redundant with std::complex, Eigen::Matrix.

7. Things in C++ that the Java original does NOT have

These are conformallab++ contributions beyond porting — the "research extensions" track (research-track.md).

Item Status
Block-FD HyperIdeal Hessian (96× speed-up) shipped (Phase 9b)
HyperIdeal Hessian (any kind) shipped — Java has hasHessian()==false
Inversive-Distance functional (Luo 2004) shipped — implemented from paper, not from Java
<CGAL/Discrete_*.h> public-API surface shipped (Phase 8a + 8b-Lite)
Cross-validation framework (4 acceptance criteria) documented in add-inversive-distance.md
Genus-2 test mesh + brezel2.obj scalability shipped
Memory-safe layout via halfedge_uv storage shipped
doc/release-policy.md formal release policy shipped (PR #13)
Analytic HyperIdeal Hessian via Schläfli 🔲 derivation written (hyperideal-hessian-derivation.md); implementation Phase 9b-analytic
Output UV map integrated into wrappers shipped (PR #14) for 3 of 5 models
Full uniformisation for genus g ≥ 2 🔲 Phase 10c — fully new research

8. How to "use the library today"

The fastest path for a mathematician evaluating the library:

# Build + run the full test suite
git clone <repo> && cd ConformalLabpp
cmake -S code -B build -DWITH_CGAL_TESTS=ON
cmake --build build --target conformallab_cgal_tests -j$(nproc)
ctest --test-dir build -R "^cgal\." --output-on-failure

# Try the CGAL API on a mesh
./build/examples/example_layout my_mesh.off

To experiment with a new functional, follow doc/tutorials/add-inversive-distance.md.

To extend the CGAL API with new named parameters, follow doc/tutorials/add-output-uv-map.md.

To optimise an FD Hessian, follow doc/tutorials/block-fd-hessian.md.

For the architectural commitments that constrain future contributions, see doc/architecture/locked-vs-flexible.md.