docs(doxygen): 100% public-API coverage (228 → 0 undocumented)
Completes the work begun in the previous commit on this branch. Every
public symbol under code/include/ now carries a brief Doxygen comment
(0 undocumented per scripts/doxygen-coverage.sh, with the `detail::`
implementation namespaces excluded as before).
Trajectory on this branch:
start (after Doxyfile fix): 24.0 % (165 / 437 in the no-detail set
was 105 / 437 when detail counted)
after PR #17 base commit : 42.4 % (165 / 396)
this commit : 100.0 % (396 / 396)
Files touched (all .hpp / .h headers under code/include/):
* cgal/Conformal_map_traits.h
* clausen.hpp, conformal_mesh.hpp, constants.hpp (already docd)
* cp_euclidean_functional.hpp, cut_graph.hpp, discrete_elliptic_utility.hpp
* euclidean_functional.hpp, euclidean_geometry.hpp, euclidean_hessian.hpp
* fundamental_domain.hpp, gauss_bonnet.hpp
* hyper_ideal_{functional,geometry,hessian,utility,visualization_utility}.hpp
* inversive_distance_functional.hpp, layout.hpp
* matrix_utility.hpp, mesh_builder.hpp, mesh_io.hpp
* newton_solver.hpp, p2_utility.hpp, period_matrix.hpp, projective_math.hpp
* serialization.hpp, spherical_functional.hpp, spherical_geometry.hpp
* spherical_hessian.hpp, viewer_utils.h
CI:
.gitea/workflows/doxygen-pages.yml now enforces
`scripts/doxygen-coverage.sh --threshold 100`, so any future regression
(a new public function landed without a `///` brief) fails the build
before the Doxygen HTML is published to Codeberg Pages.
Doxygen warnings remain at 0.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -40,19 +40,24 @@ namespace conformallab {
|
||||
|
||||
// ── Property-map type aliases ─────────────────────────────────────────────────
|
||||
|
||||
/// Property map vertex → `double` for the Spherical functional.
|
||||
using SpherVMapD = ConformalMesh::Property_map<Vertex_index, double>;
|
||||
/// Property map vertex → `int` for the Spherical functional.
|
||||
using SpherVMapI = ConformalMesh::Property_map<Vertex_index, int>;
|
||||
/// Property map edge → `double` for the Spherical functional.
|
||||
using SpherEMapD = ConformalMesh::Property_map<Edge_index, double>;
|
||||
/// Property map edge → `int` for the Spherical functional.
|
||||
using SpherEMapI = ConformalMesh::Property_map<Edge_index, int>;
|
||||
|
||||
// ── Persistent map bundle ─────────────────────────────────────────────────────
|
||||
|
||||
/// Bundle of the five property maps consumed by the Spherical functional.
|
||||
struct SphericalMaps {
|
||||
SpherVMapI v_idx; // DOF index per vertex (-1 = pinned / u_v = 0)
|
||||
SpherEMapI e_idx; // DOF index per edge (-1 = no edge DOF)
|
||||
SpherVMapD theta_v; // target cone angle Θ_v (default 2π)
|
||||
SpherEMapD theta_e; // target edge angle θ_e (default π)
|
||||
SpherEMapD lambda0; // base log-length λ°_e (default 0.0)
|
||||
SpherVMapI v_idx; ///< DOF index per vertex (−1 = pinned / u_v = 0).
|
||||
SpherEMapI e_idx; ///< DOF index per edge (−1 = no edge DOF).
|
||||
SpherVMapD theta_v; ///< Target cone angle Θᵥ (default 2π).
|
||||
SpherEMapD theta_e; ///< Target edge angle θₑ (default π).
|
||||
SpherEMapD lambda0; ///< Base log-length λ⁰ₑ (default 0).
|
||||
};
|
||||
|
||||
// Defaults: theta_v = 2π, theta_e = π, lambda0 = 0.
|
||||
@@ -133,18 +138,21 @@ inline void compute_lambda0_from_mesh(ConformalMesh& mesh, SphericalMaps& m)
|
||||
|
||||
// ── Evaluation result ─────────────────────────────────────────────────────────
|
||||
|
||||
/// Output of `evaluate_spherical()` — energy plus optional gradient.
|
||||
struct SphericalResult {
|
||||
double energy = 0.0;
|
||||
std::vector<double> gradient;
|
||||
double energy = 0.0; ///< Functional value at input DOFs.
|
||||
std::vector<double> gradient; ///< Gradient ∇E (empty if not requested).
|
||||
};
|
||||
|
||||
// ── Internal helpers ──────────────────────────────────────────────────────────
|
||||
|
||||
/// Read DOF value from `x` for index `idx`; return 0 if pinned (idx < 0).
|
||||
static inline double spher_dof_val(int idx, const std::vector<double>& x)
|
||||
{
|
||||
return idx >= 0 ? x[static_cast<std::size_t>(idx)] : 0.0;
|
||||
}
|
||||
|
||||
/// Convert a CGAL half-edge index to a plain `std::size_t` for vector indexing.
|
||||
static inline std::size_t spher_hidx(Halfedge_index h)
|
||||
{
|
||||
return static_cast<std::size_t>(static_cast<std::uint32_t>(h));
|
||||
@@ -152,14 +160,13 @@ static inline std::size_t spher_hidx(Halfedge_index h)
|
||||
|
||||
// ── Gradient only (no energy) ─────────────────────────────────────────────────
|
||||
|
||||
// Compute gradient G(x).
|
||||
// G_v = Θ_v − Σ_faces α_v(face)
|
||||
// G_e = α_opp(face+) + α_opp(face−) − θ_e
|
||||
//
|
||||
// The corner angle α_v is stored on halfedges using the convention:
|
||||
// h_alpha[h] = corner angle at source(prev(h)) = corner angle at the vertex
|
||||
// ACROSS FROM the edge of halfedge h in its face.
|
||||
// This convention makes both the vertex and edge gradient accumulators natural.
|
||||
/// Compute the Spherical-functional gradient G(x):
|
||||
/// * `G_v = Θ_v − Σ_faces α_v(face)`
|
||||
/// * `G_e = α_opp(face⁺) + α_opp(face⁻) − θ_e`
|
||||
///
|
||||
/// The corner angle α_v is stored on half-edges via the convention
|
||||
/// `h_alpha[h] = corner angle at the vertex ACROSS FROM the edge of h
|
||||
/// in its face`, which makes both gradient accumulators natural.
|
||||
inline std::vector<double> spherical_gradient(
|
||||
ConformalMesh& mesh,
|
||||
const std::vector<double>& x,
|
||||
@@ -274,6 +281,9 @@ inline std::vector<double> spherical_gradient(
|
||||
//
|
||||
// 10-point GL nodes and weights on [0, 1] (transformed from [-1, 1]):
|
||||
// t_k = (1 + s_k) / 2, w_k = w_GL_k / 2
|
||||
/// Spherical energy `E(x) = ∫₀¹ ⟨G(t·x), x⟩ dt`, evaluated with
|
||||
/// 10-point Gauss-Legendre quadrature. This is the correct potential
|
||||
/// for any conservative `G = ∇E`; error ≈ O(h²⁰) for smooth G.
|
||||
inline double spherical_energy(
|
||||
ConformalMesh& mesh,
|
||||
const std::vector<double>& x,
|
||||
@@ -318,6 +328,8 @@ inline double spherical_energy(
|
||||
|
||||
// ── Full evaluation (energy + gradient) ──────────────────────────────────────
|
||||
|
||||
/// Evaluate the Spherical functional at DOFs `x`. Returns energy and
|
||||
/// gradient (toggle via `need_energy` / `need_gradient`).
|
||||
inline SphericalResult evaluate_spherical(
|
||||
ConformalMesh& mesh,
|
||||
const std::vector<double>& x,
|
||||
@@ -333,10 +345,8 @@ inline SphericalResult evaluate_spherical(
|
||||
return res;
|
||||
}
|
||||
|
||||
// ── Finite-difference gradient check ─────────────────────────────────────────
|
||||
//
|
||||
// Tests |G[i] − fd[i]| / max(1, |G[i]|) < tol for all DOFs.
|
||||
// Same defaults as the hyper-ideal gradient check (Java FunctionalTest).
|
||||
/// Finite-difference gradient check for the Spherical functional
|
||||
/// (central differences). Same defaults as the Java `FunctionalTest`.
|
||||
inline bool gradient_check_spherical(
|
||||
ConformalMesh& mesh,
|
||||
const std::vector<double>& x0,
|
||||
@@ -390,6 +400,8 @@ inline bool gradient_check_spherical(
|
||||
//
|
||||
// Returns 0.0 if the zero cannot be bracketed (already at gauge maximum,
|
||||
// or open surface — no shift needed).
|
||||
/// Find the global-scale gauge shift `t*` for the closed-spherical case
|
||||
/// (see comment block above for the maths). Apply via `apply_spherical_gauge`.
|
||||
inline double spherical_gauge_shift(
|
||||
ConformalMesh& mesh,
|
||||
const std::vector<double>& x,
|
||||
@@ -470,7 +482,8 @@ inline double spherical_gauge_shift(
|
||||
return t;
|
||||
}
|
||||
|
||||
// Apply the gauge shift in-place: x_v ← x_v + t* for all variable vertices.
|
||||
/// Apply the spherical gauge shift in-place: `x_v ← x_v + t*` for every
|
||||
/// variable vertex, where `t* = spherical_gauge_shift(mesh, x, m, ...)`.
|
||||
inline void apply_spherical_gauge(
|
||||
ConformalMesh& mesh,
|
||||
std::vector<double>& x,
|
||||
|
||||
Reference in New Issue
Block a user