docs(euclidean-hessian): fix wrong cotangent formula in two comment blocks
Finding-C from doc/reviewer/external-audit-2026-05-30.md. The box comment at the top and the function-level comment above euclidean_cot_weights() both stated: cot_k = (t_adj1·l123 − t_adj2·t_opp) / denom2 ← WRONG The correct formula (verified numerically on a 3-4-5 right triangle, expected cot1=4/3, cot2=3/4, cot3=0) is: cot_k = (t_opp · l123 − t_a · t_b) / denom2 where t_opp is the t-value of the edge OPPOSITE vertex k, and t_a/t_b are the t-values of the two edges ADJACENT to vertex k. The implementation in euclidean_cot_weights() was already correct; only the documentation was wrong. Changes (documentation only, zero code changes): - Box comment: rewritten with correct formula and explicit per-vertex assignment (cot1: t_opp=t23, t_a=t12, t_b=t31; etc.) - Box comment: added missing ½ factor to Hessian contribution lines - Function-level comment: corrected to (t_opp·l123 − t_a·t_b)/(8·Area) with a pointer to the box comment for the full assignment - Inline return comment in euclidean_cot_weights(): now shows the mapping (cot1: t_opp=t23, t_a=t12, t_b=t31) directly at the formula 263/263 CGAL tests pass, 0 failed. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -17,18 +17,21 @@
|
|||||||
// │ side lengths lij = exp(Λ̃ij/2): │
|
// │ side lengths lij = exp(Λ̃ij/2): │
|
||||||
// │ │
|
// │ │
|
||||||
// │ t12 = −l12+l23+l31, t23 = l12−l23+l31, t31 = l12+l23−l31 │
|
// │ t12 = −l12+l23+l31, t23 = l12−l23+l31, t31 = l12+l23−l31 │
|
||||||
// │ denom2 = 2·sqrt(t12·t23·t31·l123) = 8·Area │
|
// │ l123 = l12+l23+l31, denom2 = 2·sqrt(t12·t23·t31·l123) = 8·Area │
|
||||||
// │ │
|
// │ │
|
||||||
// │ cot_k = (t_adj1·l123 − t_adj2·t_opp) / denom2 │
|
// │ Cotangent at vertex k (opposite t_opp, adjacent t_a and t_b): │
|
||||||
// │ = cotangent of the angle αk at vertex k │
|
// │ cot_k = (t_opp · l123 − t_a · t_b) / denom2 │
|
||||||
// │ │
|
// │ │
|
||||||
// │ Hessian contributions per face: │
|
// │ Assignment (k ↔ opposite edge ↔ opposite t-value): │
|
||||||
// │ H[vi, vi] += cot_vj + cot_vk (diagonal, both non-opp angles) │
|
// │ cot1 (v1, opp l23): t_opp=t23, t_a=t12, t_b=t31 │
|
||||||
// │ H[vi, vj] -= cot_vk (off-diagonal, for variable vi,vj│
|
// │ cot2 (v2, opp l31): t_opp=t31, t_a=t12, t_b=t23 │
|
||||||
|
// │ cot3 (v3, opp l12): t_opp=t12, t_a=t23, t_b=t31 │
|
||||||
// │ │
|
// │ │
|
||||||
// │ This is exactly the cotangent-Laplace operator from Pinkall–Polthier. │
|
// │ Hessian contributions per face (Pinkall–Polthier ½ factor): │
|
||||||
|
// │ H[vi, vi] += (cot_vj + cot_vk) / 2 (diagonal) │
|
||||||
|
// │ H[vi, vj] −= cot_vk / 2 (off-diagonal, variable pairs) │
|
||||||
// │ │
|
// │ │
|
||||||
// │ Pinned vertices (v_idx = −1) contribute to diagonal of neighbours but │
|
// │ Pinned vertices (v_idx = −1) contribute to diagonal of neighbours but │
|
||||||
// │ do not create a column/row in H themselves. │
|
// │ do not create a column/row in H themselves. │
|
||||||
// └──────────────────────────────────────────────────────────────────────────┘
|
// └──────────────────────────────────────────────────────────────────────────┘
|
||||||
//
|
//
|
||||||
@@ -54,7 +57,11 @@ namespace conformallab {
|
|||||||
// Given three Euclidean SIDE LENGTHS l12, l23, l31 (already exp(Λ̃/2)),
|
// Given three Euclidean SIDE LENGTHS l12, l23, l31 (already exp(Λ̃/2)),
|
||||||
// return the three cotangent weights (cot1, cot2, cot3).
|
// return the three cotangent weights (cot1, cot2, cot3).
|
||||||
//
|
//
|
||||||
// cot_k = (t_adj·l123 − t_opp·t_other) / (8·Area)
|
// cot_k = (t_opp · l123 − t_a · t_b) / (8·Area)
|
||||||
|
//
|
||||||
|
// where t_opp is the t-value of the edge OPPOSITE vertex k, and t_a, t_b are
|
||||||
|
// the t-values of the two edges ADJACENT to vertex k. See the box comment at
|
||||||
|
// the top of this file for the explicit assignment of t_opp/t_a/t_b per vertex.
|
||||||
//
|
//
|
||||||
// Returns {0,0,0} for degenerate faces (triangle inequality violated or Area=0).
|
// Returns {0,0,0} for degenerate faces (triangle inequality violated or Area=0).
|
||||||
/// Three Euclidean cotangent weights `(cot1, cot2, cot3)` for the
|
/// Three Euclidean cotangent weights `(cot1, cot2, cot3)` for the
|
||||||
@@ -85,9 +92,10 @@ inline EuclCotWeights euclidean_cot_weights(double l12, double l23, double l31)
|
|||||||
// denom2 = 2·sqrt(t12·t23·t31·l123) = 8·Area
|
// denom2 = 2·sqrt(t12·t23·t31·l123) = 8·Area
|
||||||
const double denom2 = 2.0 * std::sqrt(denom2_sq);
|
const double denom2 = 2.0 * std::sqrt(denom2_sq);
|
||||||
|
|
||||||
// cot at v1 (opposite l23): adjacent t-values are t12 and t31.
|
// Formula: cot_k = (t_opp · l123 − t_a · t_b) / denom2
|
||||||
// cot at v2 (opposite l31): adjacent t-values are t12 and t23.
|
// cot1: t_opp=t23, t_a=t12, t_b=t31 (v1 opposite l23)
|
||||||
// cot at v3 (opposite l12): adjacent t-values are t23 and t31.
|
// cot2: t_opp=t31, t_a=t12, t_b=t23 (v2 opposite l31)
|
||||||
|
// cot3: t_opp=t12, t_a=t23, t_b=t31 (v3 opposite l12)
|
||||||
return {
|
return {
|
||||||
(t23 * l123 - t31 * t12) / denom2, // cot1
|
(t23 * l123 - t31 * t12) / denom2, // cot1
|
||||||
(t31 * l123 - t12 * t23) / denom2, // cot2
|
(t31 * l123 - t12 * t23) / denom2, // cot2
|
||||||
|
|||||||
@@ -701,7 +701,7 @@ index. Add a comment:
|
|||||||
|----|------|-------|------|----------|--------|
|
|----|------|-------|------|----------|--------|
|
||||||
| A | `hyper_ideal_functional.hpp` | 319–344 | Bug | Critical (mixed config) | ✅ Fixed 2026-05-30 |
|
| A | `hyper_ideal_functional.hpp` | 319–344 | Bug | Critical (mixed config) | ✅ Fixed 2026-05-30 |
|
||||||
| B | `gauss_bonnet.hpp` | 87–88, 128–134 | API error | Medium | ✅ Fixed 2026-05-31 |
|
| B | `gauss_bonnet.hpp` | 87–88, 128–134 | API error | Medium | ✅ Fixed 2026-05-31 |
|
||||||
| C | `euclidean_hessian.hpp` | 26–27, 57–58 | Doc error | Medium | 🟡 Open |
|
| C | `euclidean_hessian.hpp` | 26–27, 57–58 | Doc error | Medium | ✅ Fixed 2026-05-31 |
|
||||||
| D | `euclidean_functional.hpp` + 2 others | 97–107 | Doc error | Medium | 🟡 Open |
|
| D | `euclidean_functional.hpp` + 2 others | 97–107 | Doc error | Medium | 🟡 Open |
|
||||||
| E | `cp_euclidean_functional.hpp` | 338–349, 373–387 | Inconsistency | Medium | 🟡 Open |
|
| E | `cp_euclidean_functional.hpp` | 338–349, 373–387 | Inconsistency | Medium | 🟡 Open |
|
||||||
| F | test files | — | Test gap | Medium | 🟠 Open |
|
| F | test files | — | Test gap | Medium | 🟠 Open |
|
||||||
|
|||||||
Reference in New Issue
Block a user