Files
ConformalLabpp/code/include/hyper_ideal_utility.hpp
Tarik Moussa ef3c448f4d
All checks were successful
C++ Tests / test-fast (pull_request) Successful in 2m13s
C++ Tests / quality-gates (pull_request) Has been skipped
C++ Tests / test-cgal (pull_request) Has been skipped
fix(citations): correct Kolpakov-Mednykh misattribution → Springborn 2008
arXiv:math/0603097 is Springborn 2008 ("A variational principle for weighted
Delaunay triangulations and hyperideal polyhedra"), not a Kolpakov-Mednykh paper.
The author pair Kolpakov & Mednykh has no joint publication from 2006; their
earliest collaboration is arXiv:1008.0312 (2010, on torus knots, unrelated).

The wrong author name was introduced during the Java→C++ port — the Java source
correctly links to math/0603097 without naming the authors; whoever ported it
invented "Kolpakov-Mednykh". The S1 citation audit (2026-05-31) then cemented
the error by adding the incorrect row to references.md.

Files corrected (7):
- code/include/hyper_ideal_utility.hpp
- code/include/hyper_ideal_functional.hpp
- code/tests/cgal/test_hyper_ideal_functional.cpp
- doc/math/references.md
- doc/roadmap/research-track.md
- doc/architecture/project-structure.md
- doc/api/tests.md

Also:
- doc/reviewer/math-derivation-citation-audit-2026-05-31.md: M1 post-correction noted
- doc/reviewer/finding-orchestration.md: lesson-learned section added (AI citation
  audits can introduce plausible-but-wrong attributions; human expert review required
  before CGAL submission)
- papers/MANUAL-DOWNLOAD.md: overview of papers requiring manual download (paywalled
  journals, TU Berlin theses, books)
- .gitignore: papers/*.pdf excluded (downloaded arXiv PDFs, not tracked)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 22:07:48 +02:00

111 lines
3.7 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#pragma once
// Copyright (c) 2024-2026 Tarik Moussa.
// SPDX-License-Identifier: MIT
// Hyperbolic tetrahedron volume formulas.
// Ported from de.varylab.discreteconformal.functional.HyperIdealUtility (Java).
#include "clausen.hpp"
#include "constants.hpp"
#include <Eigen/Dense>
#include <cmath>
#include <complex>
namespace conformallab {
/// Volume of a generalized hyperbolic tetrahedron with dihedral
/// angles `A,…,F` via the Meyerhoff / Ushijima 2006 formula.
/// Same as Java `HyperIdealUtility.calculateTetrahedronVolume()`.
inline double calculateTetrahedronVolume(double A, double B, double C,
double D, double E, double F) {
// PI from constants.hpp (conformallab::PI)
// Degenerate if any angle equals pi.
if (A == PI || B == PI || C == PI || D == PI || E == PI || F == PI)
return 0.0;
const double sA = std::sin(A), sB = std::sin(B), sC = std::sin(C);
const double sD = std::sin(D), sE = std::sin(E), sF = std::sin(F);
const double cA = std::cos(A), cB = std::cos(B), cC = std::cos(C);
const double cD = std::cos(D), cE = std::cos(E), cF = std::cos(F);
// Unit complex numbers e^(i*angle).
using Cx = std::complex<double>;
auto polar = [](double angle) { return std::polar(1.0, angle); };
Cx ad = polar(A + D), be = polar(B + E), cf = polar(C + F);
Cx abc = polar(A + B + C), abf = polar(A + B + F);
Cx ace = polar(A + C + E), aef = polar(A + E + F);
Cx bcd = polar(B + C + D), bdf = polar(B + D + F);
Cx def = polar(D + E + F), cde = polar(C + D + E);
Cx abde = ad * be, acdf = ad * cf, bcef = be * cf;
Cx abcdef = abc * def;
Cx z = ad + be + cf + abf + ace + bcd + def + abcdef;
// Gram matrix of the tetrahedron.
Eigen::Matrix4d G;
G << 1.0, -cA, -cB, -cF,
-cA, 1.0, -cC, -cE,
-cB, -cC, 1.0, -cD,
-cF, -cE, -cD, 1.0;
Cx sqrtG = std::sqrt(Cx(G.determinant(), 0.0));
Cx f = Cx(sA*sD + sB*sE + sC*sF, 0.0);
Cx f1 = f - sqrtG;
Cx f2 = f + sqrtG;
Cx z1 = -2.0 * f1 / z;
Cx z2 = -2.0 * f2 / z;
auto U = [&](Cx zi) {
return 0.5 * (
+ ImLi2(zi)
+ ImLi2(abde * zi)
+ ImLi2(acdf * zi)
+ ImLi2(bcef * zi)
- ImLi2(-abc * zi)
- ImLi2(-aef * zi)
- ImLi2(-bdf * zi)
- ImLi2(-cde * zi)
);
};
return (U(z1) - U(z2)) / 2.0;
}
/// Volume of a hyperideal tetrahedron with one ideal vertex at γ via
/// the Springborn 2008 formula (arxiv math/0603097). Same as Java
/// `HyperIdealUtility.calculateTetrahedronVolumeWithIdealVertexAtGamma()`.
inline double calculateTetrahedronVolumeWithIdealVertexAtGamma(
double gamma1, double gamma2, double gamma3,
double alpha23, double alpha31, double alpha12)
{
// PI from constants.hpp (conformallab::PI)
auto L = [](double x) { return Lobachevsky(x); };
double result = L(gamma1) + L(gamma2) + L(gamma3);
result += L((PI + alpha31 - alpha12 - gamma1) / 2.0);
result += L((PI + alpha12 - alpha23 - gamma2) / 2.0);
result += L((PI + alpha23 - alpha31 - gamma3) / 2.0);
result += L((PI - alpha31 + alpha12 - gamma1) / 2.0);
result += L((PI - alpha12 + alpha23 - gamma2) / 2.0);
result += L((PI - alpha23 + alpha31 - gamma3) / 2.0);
result += L((PI + alpha31 + alpha12 - gamma1) / 2.0);
result += L((PI + alpha12 + alpha23 - gamma2) / 2.0);
result += L((PI + alpha23 + alpha31 - gamma3) / 2.0);
result += L((PI - alpha31 - alpha12 - gamma1) / 2.0);
result += L((PI - alpha12 - alpha23 - gamma2) / 2.0);
result += L((PI - alpha23 - alpha31 - gamma3) / 2.0);
return result / 2.0;
}
} // namespace conformallab