Phase 8b-Lite extension: output_uv_map named parameter for integrated layout

Closes the UX gap identified in the Phase-8b-Lite design discussion:
the four classical-DCE CGAL entries now optionally run their `*_layout()`
step internally if the caller supplies `CGAL::parameters::output_uv_map(pmap)`.

Before this PR, the workflow was:

    auto res = CGAL::discrete_conformal_map_euclidean(mesh);
    // ... user has to re-set up maps, re-pin vertex, then ...
    auto layout = euclidean_layout(mesh, res.x, maps);
    // ... and copy coordinates into a property map manually.

After this PR:

    auto uv = mesh.add_property_map<Vertex_index, K::Point_2>("uv", ...).first;
    CGAL::discrete_conformal_map_euclidean(
        mesh, CGAL::parameters::output_uv_map(uv));
    // ... uv now populated for every vertex.

Coverage
────────
* `discrete_conformal_map_euclidean`  — `Point_2` per vertex.
* `discrete_conformal_map_spherical`  — `Point_3` per vertex (on S²).
* `discrete_conformal_map_hyper_ideal` — `Point_2` per vertex (Poincaré disk).

CP-Euclidean and Inversive-Distance entries do not yet support
`output_uv_map` — face-based packing has no per-vertex UV concept, and
inversive-distance needs a dedicated layout routine that uses Luo's
edge-length formula (planned follow-up).

New named parameters (`code/include/CGAL/Conformal_map/internal/parameters.h`)
─────────────────────────────────────────────────────────────────────────────
* `output_uv_map(pmap)` — write coordinates into pmap after layout.
* `normalise_layout(bool)` — apply post-layout canonical normalisation
  (PCA centroid for Euclidean, north-pole alignment for Spherical,
  Möbius centring for Hyper-ideal).

Both follow the existing Phase-8a-MVP named-parameter convention.
Chained syntax (`.output_uv_map(...).normalise_layout(true)`) is not
yet supported — pass them one at a time.

Tests (5 new in test_cgal_phase8b_lite.cpp)
───────────────────────────────────────────
* `OutputUvMap_Euclidean_PopulatesPmap`         — UVs are finite + non-trivial.
* `OutputUvMap_Spherical_PopulatesXyz`          — every output on unit S².
* `OutputUvMap_HyperIdeal_PointsInPoincareDisk` — |p|² ≤ 1 if converged.
* `OutputUvMap_Absent_DoesNotRunLayout`         — no parameter ⇒ no layout.
* `OutputUvMap_NormaliseLayout_TakesEffect`     — both raw + norm calls
  return finite UVs (named-parameter chaining limitation documented).

All five pass.  Full CGAL suite: 232/232, 0 skipped (was 227).

doc/api/tests.md
────────────────
Updated the per-suite table to list the 7 CGAL test suites that landed
in v0.9.0 (8a MVP + 9a + 9b + 8b-Lite) but had not yet been added to the
canonical table.  Total: 227 → 232.  This brings the doc back in sync
with `ctest` output and unblocks future `scripts/check-test-counts.sh`
runs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Tarik Moussa
2026-05-22 08:40:37 +02:00
parent 79f6757646
commit b7e837815f
4 changed files with 266 additions and 1 deletions

View File

@@ -58,8 +58,15 @@ All tests have CTest prefix `cgal.` (set via `TEST_PREFIX "cgal."` in CMakeLists
| `SphericalLayout` | `test_geometry_utils.cpp` | 1 | Spherical layout on unit sphere |
| `HomologyGenerators` | `test_geometry_utils.cpp` | 1 | Genus-2 cut graph: χ = 2, 4 cut edges (`brezel2.obj`) |
| `SmokeEuclidean` | `test_scalability_smoke.cpp` | 3 | Smoke tests on real meshes: CatHead (open), Brezel genus-1, Brezel2 genus-2 |
| `CGALConformalTraits` | `test_cgal_traits_mvp.cpp` | 2 | Phase 8a MVP traits + Default model |
| `CGALDiscreteConformalMap` | `test_cgal_traits_mvp.cpp` | 6 | Phase 8a MVP wrapper smoke tests |
| `CPEuclideanFunctional` | `test_cp_euclidean_functional.cpp` | 10 | Phase 9a.1 — BPS-2010 face-based packing (Java parity) |
| `InversiveDistanceFunctional` | `test_inversive_distance_functional.cpp` | 11 | Phase 9a.2 — Luo-2004 vertex-based packing (from literature) |
| `HyperIdealHessian` | `test_hyper_ideal_hessian.cpp` | 7 | Phase 9b — block-FD vs full-FD cross-validation + PSD + speed-up |
| `NewtonPhase9a` | `test_newton_phase9a.cpp` | 7 | Phase 9a-Newton — convergence for the two new circle-packing solvers |
| `CGALPhase8bLite` | `test_cgal_phase8b_lite.cpp` | 13 | Phase 8b-Lite — CGAL entries for all 5 DCE models + `output_uv_map` |
**Total: 227 tests, 0 skipped.**
**Total: 232 tests, 0 skipped.**
---