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
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:
@@ -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";
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user