fix: correct 16 inconsistencies found by consistency audit
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:
@@ -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()),
|
||||
|
||||
Reference in New Issue
Block a user