Commit Graph

8 Commits

Author SHA1 Message Date
Tarik Moussa
d9c1dec3de feat: output_uv_map for InversiveDistance, error for CP-Euclidean, reviewer trio
Some checks failed
C++ Tests / test-fast (pull_request) Successful in 2m24s
API Docs / doc-build (pull_request) Successful in 1m5s
Markdown link check / check (pull_request) Successful in 50s
C++ Tests / test-cgal (pull_request) Failing after 12m53s
C++ Tests / quality-gates (pull_request) Successful in 2m33s
Three reviewer-meeting deliverables in one commit.

(1) output_uv_map for the two remaining DCE entries
    ─────────────────────────────────────────────────
    * Discrete_inversive_distance.h: full implementation.  After Newton,
      reconstruct effective Euclidean edge lengths from the converged
      log-radii via the Bowers-Stephenson identity
      `ℓᵢⱼ² = rᵢ² + rⱼ² + 2·Iᵢⱼ·rᵢ·rⱼ`, populate a temporary
      EuclideanMaps with `lambda0 = log(ℓᵢⱼ²)`, and reuse the existing
      `euclidean_layout(mesh, 0, eucl)` priority-BFS.  Per-vertex
      Point_2 coordinates written into the user-supplied pmap.
      Optional `normalise_layout(true)` applies the canonical PCA
      centroid + major-axis rotation, same as the other 3 entries.

    * Discrete_circle_packing.h: throws std::runtime_error with a
      clear pointer to Phase 9c rather than silently producing
      nonsense.  CP-Euclidean is face-based; the faithful output is a
      per-face circle packing in ℝ², not a per-vertex Point_2 map.
      A true layout requires BPS-2010 §6 (~150 lines, on the porting
      roadmap as Phase 9c).  Failing loudly is the honest default.

    Tests: 2 new cases in test_cgal_phase8b_lite.cpp
    (OutputUvMap_InversiveDistance_PopulatesPmap;
    OutputUvMap_CPEuclidean_ThrowsClearly).  Both green.
    Suite total now 259 (was 257, +2).  CGAL subtotal: 234 → 236.

(2) Reviewer meeting documents
    ──────────────────────────
    New directory doc/reviewer/ with three files:

    * briefing.md  — one-page orientation for the reviewer.
      What the project is, where to look first
      (https://tmoussa.codeberg.page/ConformalLabpp/), the headline
      evidence (tests/coverage/sanitizers/license), what we want from
      them, what's deferred and why, and the 5 questions in a separate
      file.

    * questions.md — the 5 concrete decisions we want their second
      opinion on:
        Q1 Phase 9c (port-literal vs re-derive)
        Q2 Phase 9b-analytic (worth ~2 weeks for ~6× speedup?)
        Q3 CP-Euclidean output_uv_map (build now or defer?)
        Q4 CGAL submission strategy (one package or five?)
        Q5 geometry-central cross-validation co-authorship
      Plus an explicit "what would you say no to?" question at the
      bottom — negative feedback is the highest-value information.

    * agenda.md   — my own internal playbook (NOT to be sent).
      60-min flow: 5-min thank-you, 10-min architecture tour,
      30-min for Q1-Q5 in the order Q4-Q1-Q2-Q5-Q3, 5-min "no"
      question, 5-min wrap-up.  Includes post-meeting memo template
      to fill out in the 30 min after.

    * README.md    — index for the directory; says which file goes
      to whom and when to send.

(3) locked-vs-flexible.md known-limitations update
    ─────────────────────────────────────────────
    "output_uv_map covers 3 of 5 entries" → "covers 4 of 5".
    CP-Euclidean's throws-clearly behaviour documented as a Phase 9c
    deliverable rather than a passive gap.

Bonus: extended .codespellrc ignore list (acknowledgement, the
British-English spelling I used in agenda.md).

Verifications on this commit:
  259/259 tests pass (0 skipped)
  scripts/check-test-counts.sh:                OK (23 + 236 = 259)
  scripts/quality/license-headers.sh:          OK (66/66 SPDX)
  python3 scripts/quality/cgal-conventions.py: OK (0/6 violations)
  scripts/quality/codespell.sh:                OK (0 typos)
  scripts/quality/shellcheck.sh:               OK (0 findings)
  python3 scripts/check-markdown-links.py:     OK (143/143)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-24 21:15:19 +02:00
Tarik Moussa
039cc26e36 Phase 8b-Lite: pipe-operator chaining for named parameters
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
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
Tarik Moussa
b7e837815f 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>
2026-05-22 13:24:37 +02:00
Tarik Moussa
540f71a629 release: v0.9.0 — finalise PR #11 with CHANGELOG, version bump, stub cleanup
Some checks failed
C++ Tests / test-fast (pull_request) Successful in 2m25s
API Docs / doc-build (pull_request) Successful in 53s
C++ Tests / test-cgal (pull_request) Failing after 10m32s
Closes the v0.9.0 release loop on top of Phase 9a-Newton + Phase 8b-Lite:

* CHANGELOG.md (NEW) — Keep-A-Changelog format, with v0.9.0 entry
  detailing all Phase 9a / 9b / 8b-Lite contents and the doc-audit
  corrections that landed via PR #10.

* CITATION.cff — version 0.7.0 → 0.9.0, date 2026-05-18 → 2026-05-22.

* Stale HDS-port stubs removed (13 GTEST_SKIPs total):
  - code/tests/test_spherical_functional.cpp
  - code/tests/test_hyper_ideal_functional.cpp
  - code/tests/test_hyper_ideal_hyperelliptic_utility.cpp
  These referenced a "HDS port (Phase 4)" that never happened —
  CoHDS was intentionally replaced by CGAL::Surface_mesh, and the
  functional tests live in code/tests/cgal/test_*_functional.cpp.

* Test-count updates everywhere:
  - Non-CGAL  36 → 23  (drop = 13 deleted stubs)
  - CGAL      176 → 227
  - Total     212 → 250  (+38 net, 0 skipped)
  Files: README.md, CLAUDE.md, CHANGELOG.md, scripts/try_it.sh,
         doc/api/tests.md, doc/contributing.md, doc/getting-started.md,
         doc/math/validation.md.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-22 04:27:24 +02:00
Tarik Moussa
52f61cec36 Update all doc test counts to 176 CGAL tests, 0 skipped
Some checks failed
C++ Tests / test-fast (push) Successful in 2m10s
C++ Tests / test-cgal (push) Has been skipped
C++ Tests / test-fast (pull_request) Successful in 2m3s
C++ Tests / test-cgal (pull_request) Failing after 2m51s
Propagates the new baseline (176 passed, 0 skipped) established by the
GradientCheck_Hessian implementation across all documentation files that
previously referenced the stale counts (174/173/170 + 1-2 skips).

Files updated: CLAUDE.md, doc/api/tests.md, doc/contributing.md,
doc/getting-started.md, doc/math/novelty-statement.md,
doc/math/validation.md, doc/math/validation-protocol.md, scripts/try_it.sh

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 23:33:31 +02:00
Tarik Moussa
88a99d8bd1 fix: correct 16 inconsistencies found by consistency audit
All checks were successful
C++ Tests / test-fast (push) Successful in 1m59s
C++ Tests / test-cgal (push) Has been skipped
Math / code:
- layout.hpp: add explanatory comment for Möbius deck transformation
  (from_three with z1=w1, z2=w2 encodes T fixing cut-edge endpoints)
- layout.hpp: document spherical holonomy limitation — Vector2d stores
  only (x,y) of 3-D position diff; full SO(3) representation deferred

Gradient sign convention (CLAUDE.md was wrong):
- Euclidean and Spherical both use G_v = Θ_v − actual (target minus actual)
- HyperIdeal uses G_v = actual − Θ_v
- Hessian sign differs: Euclidean PSD, Spherical NSD → −H, HyperIdeal PSD

Test counts (were inconsistent across all files):
- Actual: 176 CGAL tests, 2 GTEST_SKIP (not 173/170/174, not 1 skip)
- The 2 skips are EuclideanFunctional + SphericalFunctional Hessian gradient
  checks (Java @Ignore ports) — not HyperIdeal Hessian as previously stated
- doc/api/tests.md: add missing SmokeEuclidean suite (3 tests),
  EuclideanLayout (2), SphericalLayout (1), fix GaussBonnet 8→12,
  MeshIO 9→6, Layout 8→6, EuclideanFunctional 11→12,
  HomologyGenerators no longer a GTEST_SKIP stub (live test on brezel2.obj)
- doc/roadmap/phases.md: Phase 7 cumulative 158→176 tests
- doc/roadmap/phases.md: Phase 3 clarified — HyperIdeal Hessian is FD
- CLAUDE.md: suite count 28→34, test ref 173+36→174+36
- scripts/try_it.sh: expected output 173/1 skipped → 174/2 skipped

CI table (CLAUDE.md):
- test-cgal now triggers on pull requests only (not main/dev pushes)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 23:24:44 +02:00
Tarik Moussa
e28aee7051 docs: Mathematiker-Onboarding — Theorie, Validierung, Beispiel-Meshes, 170 Tests
All checks were successful
C++ Tests / test-fast (push) Successful in 2m20s
C++ Tests / test-cgal (push) Has been skipped
Ziel: einem interessierten Mathematiker ermöglichen, die bisherige Arbeit
      unabhängig zu validieren und eigene Forschung beizutragen.

Neu:
  doc/math/discrete-conformal-theory.md
      Kompakte mathematische Einführung (DCE, Variationsprinzip, drei
      Geometriemodi, Holonomie, Periodenmatrix) für Riemann-Flächen-Kenner.

  doc/math/validation.md
      Analytisch bekannte Sollwerte + wie man sie mit dem Code prüft:
      Gauss–Bonnet (χ), τ ∈ Fundamentaldomäne (3 Invarianten), Symmetrie-
      Argumente für τ=i (4-fach) und τ=e^{iπ/3} (6-fach), Newton-Konvergenz,
      Gradienten-Check (FD), Holonomie-Kommutator. Reviewer-Checkliste.

  CONTRIBUTING.md (Root)
      Gitea/GitHub-Standard: CONTRIBUTING.md im Root-Verzeichnis als
      Kurzreferenz mit Links zu doc/contributing.md und den Math-Docs.

  code/data/off/torus_4x4.off   — 16 Vertices, 32 Flächen, Genus 1
  code/data/off/torus_8x8.off   — 64 Vertices, 128 Flächen, Genus 1
  code/data/off/torus_hex_6x6.off — 36 Vertices, 72 Flächen, 6-fach Sym.

Aktualisiert:
  README.md              — 158 → 170 Tests, zwei neue Math-Links in Tabelle
  doc/api/tests.md       — 28 Suiten, 170 Tests, 1 Skip (korrigiert)
  doc/contributing.md    — Testzähler 158+2 → 170+1

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 01:11:00 +02:00
Tarik Moussa
95d48c434a chore: .gitignore + vergessene Doc-Dateien nachgetragen
.gitignore: build-Verzeichnisse, .DS_Store, .claude/, CMake-Artefakte
Doc-Dateien die beim Restructure-Commit fehlten:
  doc/api/headers.md             — alle 24 Public-Header mit Beschreibung
  doc/api/tests.md               — 26 Suiten, 158 Tests, Einzelzahlen
  doc/architecture/design-decisions.md — Architekturentscheidungen + Begründung
  doc/architecture/project-structure.md — Verzeichnisbaum + Build-Targets
README.md: Links zu den vier neuen Doc-Dateien ergänzt

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17 21:40:05 +02:00