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>
This commit is contained in:
Tarik Moussa
2026-05-18 23:24:44 +02:00
parent 7edf699ac2
commit 88a99d8bd1
5 changed files with 50 additions and 21 deletions

View File

@@ -698,6 +698,12 @@ inline Layout3D spherical_layout(
result.pos[vs.idx()], result.pos[vt.idx()],
arc_len(mesh.prev(hx)), arc_len(mesh.next(hx)));
Eigen::Vector3d diff = p_tri - result.pos[vn.idx()];
// Note: spherical holonomy is geometrically a 3-D rotation, not a 2-D
// translation. The Vector2d here stores only the (x,y) component of the
// S²-position difference across the cut, which is an approximation.
// For accurate spherical holonomy (rotation axis + angle) use the full
// 3-D positions in result.pos[] directly. Phase 10+ will replace this
// with a proper SO(3) representation.
holonomy->translations.push_back(Eigen::Vector2d(diff.x(), diff.y()));
}
}
@@ -823,6 +829,13 @@ inline Layout2D hyper_ideal_layout(
Eigen::Vector2d p_tri = detail::trilaterate_hyp(result.uv[vs.idx()], result.uv[vt.idx()], D, da, db);
detail::set_face_huv_2d(result.halfedge_uv, mesh, hx, result.uv, p_tri);
using C = std::complex<double>;
// Möbius deck transformation T across cut edge (vs,vt):
// T is the unique Möbius isometry of the Poincaré disk that:
// - fixes vs and vt (z1=w1, z2=w2: the cut-edge endpoints are
// identified across the seam, so T maps each to itself)
// - maps vn (placed side) → p_tri (virtual side)
// This uniquely determines the hyperbolic translation/rotation
// along the geodesic through vs and vt.
holonomy->mobius_maps.push_back(MobiusMap::from_three(
C(result.uv[vs.idx()].x(), result.uv[vs.idx()].y()),
C(result.uv[vs.idx()].x(), result.uv[vs.idx()].y()),