From 37b538aae46bed898fd6c9df113133ae53c14a6b Mon Sep 17 00:00:00 2001 From: Tarik Moussa Date: Sun, 31 May 2026 01:51:04 +0200 Subject: [PATCH] docs: Layout2D index semantics, CLI table, CLI roadmap (U9+U10+U11) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit U9 (layout.hpp + example_layout.cpp) Layout2D.uv and .halfedge_uv now have explicit Doxygen docs stating: - indexing: v.idx() / h.idx() (raw integer index) - length: mesh.number_of_vertices() / number_of_halfedges() - precondition: no vertex removal / collect_garbage() after loading - access pattern example in the doc comment example_layout.cpp: access site comment + static_cast(v.idx()) U10 (getting-started.md) New 'CLI parameter reference' table (7 rows) added directly below the CLI usage examples; cross-references --help as the canonical source U11 (doc/roadmap/phases.md) New Phase 9h 'CLI usability extensions' section inserted before Phase 10: 9h.1 --tol / --max-iter solver-tuning params (~30 min, no deps) 9h.2 -g cp_euclidean / -g inversive_distance (~2-4 h, needs 9a ✅) Each sub-task has effort estimate, implementation sketch, and acceptance criteria so a future session can pick it up cold. Co-Authored-By: Claude Sonnet 4.6 --- code/examples/example_layout.cpp | 4 ++- code/include/layout.hpp | 36 +++++++++++++++++----- doc/getting-started.md | 16 ++++++++++ doc/reviewer/usability-audit-2026-05-31.md | 6 ++-- doc/roadmap/phases.md | 31 +++++++++++++++++++ 5 files changed, 81 insertions(+), 12 deletions(-) diff --git a/code/examples/example_layout.cpp b/code/examples/example_layout.cpp index 65abc96..b7bbce4 100644 --- a/code/examples/example_layout.cpp +++ b/code/examples/example_layout.cpp @@ -128,7 +128,9 @@ int main(int argc, char* argv[]) if (layout.success) { std::cout << "UV coordinates:\n"; for (auto v : mesh.vertices()) { - auto& p = layout.uv[v.idx()]; + // layout.uv is indexed by v.idx() (raw integer vertex index). + // Valid as long as no vertices were removed/compacted after loading. + auto& p = layout.uv[static_cast(v.idx())]; std::cout << " v" << v.idx() << ": (" << std::fixed << std::setprecision(6) << p.x() << ", " << p.y() << ")\n"; diff --git a/code/include/layout.hpp b/code/include/layout.hpp index 6a52f08..11eb688 100644 --- a/code/include/layout.hpp +++ b/code/include/layout.hpp @@ -138,18 +138,38 @@ struct MobiusMap { /// per-vertex UV coordinates plus a per-half-edge UV atlas for seamed /// textures. struct Layout2D { - /// uv[v.idx()] — primary 2-D position (first / shallowest-BFS-depth visit). + /// Primary 2-D position per vertex (first / shallowest-BFS-depth visit). + /// + /// **Indexing:** `uv[v.idx()]` — indexed by the raw integer vertex index. + /// **Length:** `mesh.number_of_vertices()`. + /// + /// \pre No vertices have been removed from `mesh` after loading (i.e. + /// `mesh.is_valid()` and no compaction was performed). On a fresh + /// `Surface_mesh` loaded from file, `v.idx()` is always in + /// `[0, number_of_vertices())` and contiguous. If vertices were + /// deleted and `mesh.collect_garbage()` was called, re-run the + /// layout — indices will have shifted. + /// + /// Access pattern: + /// ```cpp + /// for (auto v : mesh.vertices()) + /// Eigen::Vector2d uv_v = layout.uv[v.idx()]; + /// ``` std::vector uv; - /// halfedge_uv[h.idx()] — UV of source(h) as seen from face(h). + /// UV of `source(h)` as seen from `face(h)`, indexed by `h.idx()`. /// - /// For interior (non-seam) halfedges: equals uv[source(h).idx()]. - /// For seam halfedges: carries the UV from the virtual unfolding across - /// the cut (i.e. the trilaterated position that was NOT used as the - /// primary uv). This gives each face its own copy of a seam vertex, - /// enabling a proper GPU texture atlas without vertex duplication. + /// **Indexing:** `halfedge_uv[h.idx()]` — raw integer halfedge index. + /// **Length:** `mesh.number_of_halfedges()`. Same no-compaction precondition + /// as `uv` (see above). /// - /// Size = mesh.number_of_halfedges(). Border halfedges = (0,0). + /// For interior (non-seam) halfedges: equals `uv[source(h).idx()]`. + /// For seam halfedges: carries the UV from the virtual unfolding across the + /// cut — the trilaterated position that was NOT used as the primary `uv`. + /// This gives each face its own copy of a seam vertex, enabling a proper + /// per-halfedge GPU texture atlas without vertex duplication. + /// + /// Border halfedges (outer face) hold `(0, 0)`. std::vector halfedge_uv; bool success = false; ///< `true` iff the BFS placed every vertex. diff --git a/doc/getting-started.md b/doc/getting-started.md index 53e35d1..933b592 100644 --- a/doc/getting-started.md +++ b/doc/getting-started.md @@ -129,6 +129,22 @@ After a full build (`-DWITH_CGAL=ON`): ./bin/conformallab_core --help ``` +### CLI parameter reference + +| Flag | Default | Description | +|------|---------|-------------| +| `-i / --input` | *required* | Input mesh file (OFF / OBJ / PLY) | +| `-o / --output` | *(none)* | Save layout as OFF file | +| `-j / --json` | *(none)* | Serialise solver result + UV to JSON | +| `-x / --xml` | *(none)* | Serialise solver result + UV to XML | +| `-g / --geometry` | `euclidean` | Target geometry: `euclidean` · `spherical` · `hyper_ideal` | +| `-s / --show` | `false` | Open the input mesh in the interactive viewer | +| `-v / --verbose` | `false` | Print mesh topology, DOF counts, convergence details | + +> **Tip:** `./bin/conformallab_core --help` always shows the canonical up-to-date +> list generated by CLI11. The table above matches `conformallab_cli.cpp` +> as of v0.10.0. + ## Example programs ```bash diff --git a/doc/reviewer/usability-audit-2026-05-31.md b/doc/reviewer/usability-audit-2026-05-31.md index 2840ef6..a2e9b3a 100644 --- a/doc/reviewer/usability-audit-2026-05-31.md +++ b/doc/reviewer/usability-audit-2026-05-31.md @@ -544,9 +544,9 @@ exposed via the CGAL public API, but a CLI user cannot reach them. | U6 | README + 2 examples | Stale | 🟡 Medium | ✅ Fixed 2026-05-31 | | U7 | `getting-started.md` | Missing | 🟠 Minor | ✅ Fixed 2026-05-31 | | U8 | `README.md` | Missing | 🟠 Minor | ✅ Fixed 2026-05-31 | -| U9 | `layout.hpp` + example | Missing | 🟠 Minor | 🟡 Open | -| U10 | `getting-started.md` | Missing | 🟠 Minor | 🟡 Open | -| U11 | `conformallab_cli.cpp` | Roadmap | 🟠 Minor | 🟡 Open | +| U9 | `layout.hpp` + example | Missing | 🟠 Minor | ✅ Fixed 2026-05-31 | +| U10 | `getting-started.md` | Missing | 🟠 Minor | ✅ Fixed 2026-05-31 | +| U11 | `conformallab_cli.cpp` | Roadmap | 🟠 Minor | ✅ Added to phases.md (9h) | **Priority order for fixing:** 1. ~~U1 + U2~~ ✅ done diff --git a/doc/roadmap/phases.md b/doc/roadmap/phases.md index 3a939f4..7a70672 100644 --- a/doc/roadmap/phases.md +++ b/doc/roadmap/phases.md @@ -287,6 +287,37 @@ mesh type. no new library surface). Effort: small (~2–3 days). ``` +9h — CLI usability extensions (infrastructure — no Java equivalent) +────────────────────────────────────────────────────────────────── + +Identified by usability-audit-2026-05-31 (Finding-U11). Two independent +sub-tasks; either can land independently. + +``` +9h.1 Newton solver tuning parameters (~30 min) + Currently hardcoded in all three run_*() helpers: + tol = 1e-8, max_iter = 200 + Add to conformallab_cli.cpp: + app.add_option("--tol", tol, "Newton gradient tolerance [1e-8]"); + app.add_option("--max-iter", max_iter, "Newton iteration limit [200]"); + Thread both through run_euclidean / run_spherical / run_hyper_ideal. + Update getting-started.md CLI parameter table. + Status: 🔲 planned. Effort: ~30 min. No dependencies. + +9h.2 Phase-9a models in CLI (~2–4 hours) + The CP-Euclidean and Inversive-Distance functionals are fully + implemented in the library and exposed via the CGAL public API + (Discrete_circle_packing.h, Discrete_inversive_distance.h), but + a CLI user cannot reach them. Add: + -g cp_euclidean → run_cp_euclidean() + -g inversive_distance → run_inversive_distance() + Following the existing run_euclidean() pattern (~60 lines each). + Add both geometry strings to the CLI::IsMember validator. + Update README + getting-started.md parameter table. + Status: 🔲 planned. Effort: ~2–4 h. Requires: 9a complete ✅. + Java reference: none (both functionals are research / literature ports). +``` + --- ## ◼ New research directions — Phases 10d–10g (2026 library scan)