docs: Layout2D index semantics, CLI table, CLI roadmap (U9+U10+U11)
Some checks failed
C++ Tests / test-fast (push) Has been cancelled
C++ Tests / test-cgal (push) Has been cancelled
C++ Tests / quality-gates (push) Has been cancelled
API Docs / doc-build (push) Has been cancelled
Markdown link check / check (push) Has been cancelled
C++ Tests / test-fast (pull_request) Successful in 2m10s
C++ Tests / quality-gates (pull_request) Has been skipped
C++ Tests / test-cgal (pull_request) Has been skipped

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<size_t>(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 <noreply@anthropic.com>
This commit is contained in:
Tarik Moussa
2026-05-31 01:51:04 +02:00
parent ccbfd852b2
commit 37b538aae4
5 changed files with 81 additions and 12 deletions

View File

@@ -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<std::size_t>(v.idx())];
std::cout << " v" << v.idx()
<< ": (" << std::fixed << std::setprecision(6)
<< p.x() << ", " << p.y() << ")\n";

View File

@@ -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<Eigen::Vector2d> 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<Eigen::Vector2d> halfedge_uv;
bool success = false; ///< `true` iff the BFS placed every vertex.

View File

@@ -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

View File

@@ -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

View File

@@ -287,6 +287,37 @@ mesh type.
no new library surface). Effort: small (~23 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 (~24 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: ~24 h. Requires: 9a complete ✅.
Java reference: none (both functionals are research / literature ports).
```
---
## ◼ New research directions — Phases 10d10g (2026 library scan)