Tarik Moussa a4438c9a1a
All checks were successful
C++ Tests / test-fast (push) Successful in 2m4s
C++ Tests / test-cgal (push) Has been skipped
test: Java-Geometrie-Utility-Tests portiert (Tests 1–6) + Genus-2-TODO-Stub
Portiert aus CuttinUtilityTest, UnwrapUtilityTest, ConvergenceUtilityTests
und HomologyTest (Java-Quelldatei unifgeo/test). Jetzt 170 CGAL-Tests.

Neue Suiten in test_geometry_utils.cpp:
  CuttingUtility       — point_in_triangle_2d (3 Tests, Java-Test 1–2)
  UnwrapUtility        — Eckwinkel law-of-cosines (2 Tests, Java-Test 3)
  ConvergenceUtility   — circumradius + scale-invariant R_f/sqrt(A) (6 Tests, Java-Test 4–6)
  HomologyGenerators   — GTEST_SKIP-Stub für Genus-2 (Java-Test 7, Phase 8)

Der Stub dokumentiert genau was fehlt (Genus-2-Mesh), welcher Code nötig ist
(compute_cut_graph → 4 cut edges) und die Java-Herkunft.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 11:09:27 +02:00
2026-02-09 18:39:03 +01:00

conformallab++

conformallab++ is a modern C++ reimplementation of the ConformalLab software by Stefan Sechelmann for experiments in discrete conformal geometry and related mesh transformations.

The long-term goal is a CGAL package that brings discrete conformal maps (hyper-ideal, spherical, Euclidean) to the CGAL ecosystem using CGAL::Surface_mesh as the underlying half-edge data structure.

Status: Phase 7 vollständig abgeschlossen. Alle drei Geometrien lösbar via Newton-Solver (SimplicialLDLT + SparseQR-Fallback). Priority-BFS-Layout in ℝ²/S²/Poincaré-Disk mit exakter hyperbolischer Trilateration, GaussBonnet, Tree-Cotree-Schnittgraph, Möbius-Holonomie, Periodenmatrix (Genus 1), Fundamentalbereich-Polygon, halfedge_uv-Texturatlas. JSON/XML-Serialisierung, vollständige CLI-App. 158 Tests, 2 skipped.


Features

Bereich Status
Clausen / Lobachevsky / ImLi₂ Funktionen Phase 1
Hyper-ideal Geometrie (ζ, lᵢⱼ, αᵢⱼ, σᵢ, σᵢⱼ) Phase 2
CGAL Surface_mesh Infrastruktur + Mesh-Builder Phase 3a
Hyper-ideal Funktional (Energie + Gradient) Phase 3b
Sphärisches Funktional (Energie + Gradient + Gauge-Fix) Phase 3c/3e
Euklidisches Funktional (Energie + Gradient) Phase 3d
Euklidischer Hessian (Kotangenten-Laplace, PinkallPolthier) Phase 3f
Sphärischer Hessian (∂α/∂u aus Kosinussatz) Phase 3f
Hyper-ideal Hessian (numerisch FD, symmetrisiert) Phase 4a
Newton-Solver — alle drei Geometrien Phase 4a
SparseQR-Fallback für rangdefiziente H (Gauge-Moden) Phase 4a
Mesh I/O (CGAL::IO — OFF / OBJ / PLY) Phase 4b
End-to-End-Pipeline-Tests Phase 4c
Beispiel-Programme (headless + interaktiver Viewer) Phase 4d
BFS-Layout (ℝ², S², Poincaré-Disk) Phase 5
CLI-App (conformallab_core) Phase 5
JSON + XML Serialisierung Phase 5
GaussBonnet Check + Enforce Phase 6
Tree-Cotree-Schnittgraph (2g Naht-Kanten) Phase 6
Exakte hyperbolische Trilateration (Möbius + Kosinussatz) Phase 6
Layout-Normalisierung (PCA-Zentrierung / Möbius-Zentrierung) Phase 6
Priority-BFS (Min-Heap über BFS-Tiefe, minimiert Fehlerakkumulation) Phase 7
MobiusMap — T(z)=(az+b)/(cz+d), from_three, compose, inverse Phase 7
halfedge_uv — Naht-bewusstes UV pro Halfedge (GPU-Texturatlas) Phase 7
Möbius-Holonomie — SU(1,1)-Isometrie pro Schnitt-Kante (hyperbolisch) Phase 7
Periodenmatrix — τ = ω₂/ω₁ ∈ , SL(2,)-Reduktion (Genus 1) Phase 7
Fundamentalbereich — CCW-Parallelogramm, Kachelkopien Phase 7
Analytischer HyperIdeal-Hessian (ζ-Kette) Phase 8 geplant
Inversive-Distance-Funktional (Luo 2004) nicht portiert
Vollständige globale Uniformisierung Genus g ≥ 2 Phase 8 geplant
Periodenmatrix Siegel Ω (g×g, g ≥ 2) Phase 8 geplant

Quick Start — CLI-App

cmake -S code -B build -DWITH_CGAL=ON
cmake --build build -j4

# Konformes Layout für beliebige OFF/OBJ/PLY-Netze
./bin/conformallab_core -i input.off -g euclidean -o layout.off -j result.json -x result.xml

# Geometrien: euclidean | spherical | hyper_ideal
./bin/conformallab_core -i input.off -g spherical -o sphere.off

# Interaktiver Viewer
./bin/conformallab_core -i input.off -s

Beispiel-Programme

./build/examples/example_layout    [input.off] [layout.off] [result.json] [result.xml]
./build/examples/example_euclidean [input.off] [output.off]
./build/examples/example_hyper_ideal [input.off] [output.off]
./build/examples/example_viewer    [input.off]   # interaktiv (WITH_VIEWER)

Bibliotheks-Nutzung

Minimale euklidische Pipeline

#include "conformal_mesh.hpp"
#include "mesh_io.hpp"
#include "euclidean_functional.hpp"
#include "newton_solver.hpp"
#include "layout.hpp"

using namespace conformallab;

int main() {
    ConformalMesh mesh = load_mesh("input.off");

    auto maps = setup_euclidean_maps(mesh);
    compute_euclidean_lambda0_from_mesh(mesh, maps);

    // DOFs zuweisen — ersten Vertex pinnen (Gauge-Fix)
    auto vit = mesh.vertices().begin();
    maps.v_idx[*vit++] = -1;
    int idx = 0;
    for (; vit != mesh.vertices().end(); ++vit)
        maps.v_idx[*vit] = idx++;

    // Zielwinkel: natürliches Gleichgewicht (x* = 0)
    std::vector<double> x0(idx, 0.0);
    auto G0 = euclidean_gradient(mesh, x0, maps);
    for (auto v : mesh.vertices()) {
        int iv = maps.v_idx[v];
        if (iv >= 0) maps.theta_v[v] -= G0[iv];
    }

    auto res = newton_euclidean(mesh, x0, maps);
    if (res.converged)
        save_mesh("output.off", mesh);
    return res.converged ? 0 : 1;
}

Layout + Holonomie (geschlossene Flächen)

#include "layout.hpp"
#include "cut_graph.hpp"
#include "period_matrix.hpp"
#include "fundamental_domain.hpp"

// Schnittgraph berechnen (Tree-Cotree, 2g Kanten)
CutGraph cg = compute_cut_graph(mesh);

// Layout mit Holonomie-Tracking
HolonomyData hol;
Layout2D lay = euclidean_layout(mesh, res.x, maps, &cg, &hol, /*normalise=*/true);

// Periodenmatrix (Genus 1)
PeriodData pd = compute_period_matrix(hol);   // τ = ω₂/ω₁ ∈ , SL(2,)-reduziert
std::cout << "τ = " << pd.tau << "\n";

// Fundamentalbereich-Parallelogramm
FundamentalDomain fd = compute_fundamental_domain(hol);
// fd.vertices  — 4 Ecken (CCW)
// fd.generators — ω₁, ω₂

// Kachelkopie für Universalüberlagerung
Layout2D tile = tiling_copy(lay, fd.generators[0], fd.generators[1], 1, -1);

// halfedge_uv — Naht-bewusstes UV pro Halfedge (GPU-Texturatlas)
// lay.halfedge_uv[h.idx()] = UV von source(h) aus Sicht von face(h)

HyperIdeal-Geometrie

auto maps = setup_hyper_ideal_maps(mesh);
int n = assign_all_dof_indices(mesh, maps);
auto result = newton_hyper_ideal(mesh, x0, maps);

// Möbius-Holonomie (SU(1,1)-Isometrien pro Schnitt-Kante)
HolonomyData hol;
Layout2D lay = hyper_ideal_layout(mesh, result.x, maps, &cg, &hol);
// hol.mobius_maps[i] = T_i  (Möbius-Abbildung für i-te Schnitt-Kante)

SparseQR-Fallback direkt nutzen

#include "newton_solver.hpp"

bool used_fallback = false;
auto dx = conformallab::solve_linear_system(H, rhs, &used_fallback);
if (used_fallback)
    std::cout << "SparseQR verwendet (H ist rangdefizient)\n";

Build-Modi

Modus CMake-Flags Was wird gebaut
Nur Tests (Standard) (keine) conformallab_tests — Eigen + GTest
CGAL-Tests + Beispiele -DWITH_CGAL=ON conformallab_cgal_tests, Beispiel-Programme, CLI
Interaktiver Viewer -DWITH_CGAL=ON + example_viewer, Viewer in CLI integriert

Externe Abhängigkeiten sind als Tarballs in code/deps/tarballs/ enthalten und werden beim CMake-Configure-Schritt extrahiert (GTest via FetchContent). Boost wird nur mit -DWITH_CGAL=ON benötigt (Header-Only durch CGAL 6.x).


Voraussetzungen

Tool Minimum
C++ Compiler (GCC oder Clang) C++17
CMake 3.20
Boost Headers 1.70 (nur mit -DWITH_CGAL=ON)

Einstieg

git clone https://codeberg.org/TMoussa/ConformalLabpp
cd ConformalLabpp

Nur Tests (CI-Standard — keine System-Abhängigkeiten)

cmake -S code -B build
cmake --build build --target conformallab_tests -j$(nproc)
ctest --test-dir build --output-on-failure

CGAL-Tests + Beispiele (benötigt System-Boost)

cmake -S code -B build -DWITH_CGAL=ON
cmake --build build -j$(nproc)
ctest --test-dir build -R "^cgal\." --output-on-failure
./build/examples/example_layout
./bin/conformallab_core -i input.off -g euclidean -o layout.off

Erwartet: 158 Tests bestanden, 2 skipped (die zwei @Ignore-Hessian-Stubs).

Interaktiver Viewer

cmake -S code -B build -DWITH_CGAL=ON
cmake --build build -t example_viewer -j$(nproc)
./build/examples/example_viewer data/off/example.off

Öffentliche Header (code/include/)

Header Beschreibung
clausen.hpp Clausen Cl₂, Lobachevsky Л, ImLi₂
hyper_ideal_geometry.hpp ζ-Funktionen, lᵢⱼ, αᵢⱼ, σᵢ, σᵢⱼ
hyper_ideal_utility.hpp Tetraeder-Volumen (Meyerhoff / KolpakovMednykh)
hyper_ideal_functional.hpp HyperIdeal Energie + Gradient auf ConformalMesh
hyper_ideal_hessian.hpp HyperIdeal Hessian (numerisch FD, symmetrisiert)
hyper_ideal_visualization_utility.hpp Poincaré-Disk-Projektion, Umkreis-Helfer
spherical_geometry.hpp Sphärische Bogenlänge, Halbwinkelformel
spherical_functional.hpp Sphärisch: Energie + Gradient + Gauge-Fix
spherical_hessian.hpp Sphärischer Hessian (∂α/∂u, Kosinussatz)
euclidean_geometry.hpp Euklidischer Eckenwinkel (t-Wert / atan2)
euclidean_functional.hpp Euklidisch: Energie + Gradient
euclidean_hessian.hpp Kotangenten-Laplace Hessian (PinkallPolthier)
newton_solver.hpp newton_{euclidean,spherical,hyper_ideal} + öffentliches solve_linear_system
conformal_mesh.hpp ConformalMesh = CGAL::Surface_mesh<Point3> + Property-Map-Helfer
mesh_builder.hpp make_triangle / make_tetrahedron / make_quad_strip / make_fan / …
mesh_io.hpp read_mesh / write_mesh / load_mesh / save_mesh
mesh_utils.hpp CGAL → Eigen Konvertierung (cgal_to_eigen)
serialization.hpp save/load_result_json + save/load_result_xml
gauss_bonnet.hpp euler_characteristic, genus, gauss_bonnet_sum/rhs/deficit, check_gauss_bonnet, enforce_gauss_bonnet
cut_graph.hpp CutGraph + compute_cut_graph (Tree-Cotree, EricksonWhittlesey 2005)
layout.hpp euclidean/spherical/hyper_ideal_layoutLayout2D/3D; MobiusMap; halfedge_uv; Priority-BFS; HolonomyData; normalise_*
period_matrix.hpp PeriodData, compute_period_matrix, reduce_to_fundamental_domain, is_in_fundamental_domain
fundamental_domain.hpp FundamentalDomain, compute_fundamental_domain_{genus1,}, tiling_copy, tiling_neighbourhood
constants.hpp conformallab::PI, TWO_PI

Projektstruktur

code/
├── include/                          # Alle öffentlichen Header (Header-Only-Bibliothek)
│   ├── conformal_mesh.hpp
│   ├── mesh_builder.hpp
│   ├── mesh_io.hpp / mesh_utils.hpp
│   ├── newton_solver.hpp             # 3 Newton-Solver + solve_linear_system
│   ├── layout.hpp                    # Priority-BFS, MobiusMap, halfedge_uv, Holonomie
│   ├── serialization.hpp
│   ├── gauss_bonnet.hpp
│   ├── cut_graph.hpp                 # Tree-Cotree
│   ├── period_matrix.hpp             # τ ∈ , SL(2,)-Reduktion (Genus 1)
│   ├── fundamental_domain.hpp        # Parallelogramm, Kacheln; 4g-Polygon TODO Phase 8
│   ├── hyper_ideal_{functional,hessian,geometry,utility,visualization_utility}.hpp
│   ├── spherical_{functional,hessian,geometry}.hpp
│   ├── euclidean_{functional,hessian,geometry}.hpp
│   ├── clausen.hpp
│   └── constants.hpp
├── examples/
│   ├── example_euclidean.cpp
│   ├── example_hyper_ideal.cpp
│   ├── example_layout.cpp            # Solve → Layout → OFF/JSON/XML + Round-Trip
│   └── example_viewer.cpp            # Interaktiver libigl-Viewer
├── src/
│   ├── apps/v0/conformallab_cli.cpp  # CLI-App (Phase 5)
│   └── viewer/simple_viewer.cpp
├── tests/
│   ├── *.cpp                         # conformallab_tests (kein CGAL)
│   └── cgal/
│       ├── test_conformal_mesh.cpp           # 14 Tests
│       ├── test_hyper_ideal_functional.cpp   #  7 Tests
│       ├── test_spherical_functional.cpp     # 12 Tests (1 skipped)
│       ├── test_euclidean_functional.cpp     # 11 Tests (1 skipped)
│       ├── test_euclidean_hessian.cpp        #  9 Tests
│       ├── test_spherical_hessian.cpp        #  8 Tests
│       ├── test_newton_solver.cpp            # 14 Tests
│       ├── test_mesh_io.cpp                  #  9 Tests
│       ├── test_pipeline.cpp                 #  5 Tests
│       ├── test_layout.cpp                   #  8 Tests (Layout + JSON/XML)
│       ├── test_phase6.cpp                   # 26 Tests (GB, CutGraph, Trilateration)
│       └── test_phase7.cpp                   # 37 Tests (MobiusMap, Priority-BFS,
│                                             #   halfedge_uv, Periodenmatrix, FD)
└── deps/
    ├── eigen-3.4.0/
    ├── CGAL-6.1.1/
    ├── libigl-2.6.0/
    ├── glfw-3.4/
    └── single_includes/              # CLI11, json.hpp

Test-Suiten

conformallab_tests (CI — immer gebaut)

Reine Mathe-Tests, nur Eigen: Clausen / Lobachevsky / ImLi₂, Hyper-ideal Geometrie, Tetraeder-Volumina.

conformallab_cgal_tests (lokal — -DWITH_CGAL=ON)

Suite Tests Was geprüft wird
ConformalMeshTopology 4 Euler-Charakteristik, Vertex/Edge/Face-Anzahl
ConformalMeshTraversal 4 Halfedge-Iteration, Valenz, Opposite
ConformalMeshProperties 5 Property-Maps (λ, θ, idx, α, Geometrietyp)
ConformalMeshValidity 1 CGAL-Validität für alle Factory-Meshes
HyperIdealFunctional 7 FD-Gradient-Checks + Hessian-Symmetrie
SphericalFunctional 12 Winkelformel + Gradient + Gauge-Fix (1 skipped)
EuclideanFunctional 11 Winkelformel + Gradient (1 skipped)
EuclideanHessian 9 Kotangenten-Laplace-Struktur, FD-Übereinstimmung, PSD, Nullraum
SphericalHessian 8 Ableitungskorrektheit, NSD am Gleichgewicht
NewtonSolver 11 Konvergenz (Eucl. ×3, Sphär. ×4, HyperIdeal ×4)
SparseQRFallback 3 Full-Rank-LDLT · singuläre Matrix → QR · geschlossenes Mesh
MeshIO 9 OFF/OBJ Round-Trips, Fehlerbehandlung
Pipeline 5 End-to-End: Build → Setup → Solve → Export → Reload
Layout 8 Kantenlängen-Erhaltung (Eucl./Sphär.), Poincaré-Disk
Serialization 2 JSON- und XML-Round-Trips (DOF + Layout)
GaussBonnet 8 χ, Genus, Summe/RHS, Defizit, Check, Enforce
CutGraph 6 Tree-Cotree, offene/geschlossene Meshes, FlagIndex-Konsistenz
HyperbolicTrilateration 4 Möbius + Kosinussatz: exakte Abstände, Disk-Inneres, off-origin
Normalisation 4 Eukl. Schwerpunkt, Längenverhältnisse, Möbius-Zentrierung
MobiusMap 8 Identity, Inverse, Compose, from_three, apply(Vector2d)
BestRootFace 2 Gültige Wurzel-Fläche, Interior-Bonus
HalfedgeUV 4 Größe = #Halfedges, Naht-Konsistenz, Randhalfedges = 0
PriorityBFS 3 Erfolg, kein Seam bei offenen Meshes, alle Vertices platziert
NormaliseEuclidean 2 UV-Schwerpunkt = 0, halfedge_uv-Schwerpunkt = 0
PeriodMatrix 7 τ ∈ , SL(2,)-Reduktion, Ausnahme außerhalb
FundamentalDomain 7 Genus-1-Parallelogramm CCW, Generatoren, g>1 leer
TilingCopy/Neighbourhood 4 Verschiebung korrekt, Anzahl Kacheln
Gesamt 158 2 skipped (Hessian-Stubs, identisch mit Java @Ignore)

Newton-Solver & SparseQR-Fallback

newton_solver.hpp stellt drei Solver mit einheitlicher Schnittstelle bereit:

NewtonResult newton_euclidean  (mesh, x0, maps [, tol, max_iter])
NewtonResult newton_spherical  (mesh, x0, maps [, tol, max_iter])
NewtonResult newton_hyper_ideal(mesh, x0, maps [, tol, max_iter, hess_eps])

Jede Iteration: Gradient G → Hessian H → löse H·Δx = G (SimplicialLDLT, Fallback SparseQR) → Backtracking-Liniensuche.

Geometrie G H-Vorzeichen
Euklidisch Θ_v Σα_v PSD → LDLT auf H
Sphärisch Θ_v Σα_v NSD → LDLT auf H
HyperIdeal Σβ_v Θ_v PSD → LDLT auf H

SparseQR-Fallback (solve_linear_system): Bei rangdefizientem H (Gauge-Moden bei geschlossenen Meshes ohne gepinnten Vertex) findet SparseQR den minimalen Newton-Schritt orthogonal zum Nullraum.


Mathematischer Umfang — C++ vs. Java-Original

Mathematische Schicht Java ConformalLab conformallab++
Euklidisches Funktional — Energie, Gradient
Sphärisches Funktional — Energie, Gradient, Gauge-Fix
HyperIdeal Funktional — Energie, Gradient
Inversive-Distance-Funktional (Luo 2004) nicht portiert
Euklidischer Hessian — Kotangenten-Laplace analytisch analytisch
Sphärischer Hessian — ∂α/∂u aus Kosinussatz analytisch analytisch
HyperIdeal Hessian — ζ → lᵢⱼ → β/α Kette analytisch ⚠️ symmetrisches FD
Newton-Solver
SparseQR-Fallback für Gauge-Moden ?
Kegelmetriken — vorgeschriebenes Θ_v ≠ 2π vollständig ⚠️ nur Datenstruktur
Layout / Einbettung — ℝ² / H² / S² Priority-BFS, alle drei
Exakte hyperbolische Trilateration Möbius Möbius + Kosinussatz
halfedge_uv — Naht-bewusstes UV (Texturatlas)
GaussBonnet Konsistenzprüfung
Tree-Cotree-Schnittgraph (2g Kanten) EricksonWhittlesey
Holonomie / Monodromie — Euklidisch (Translationen)
Holonomie — Hyperbolisch (SU(1,1) Möbius-Mappe)
Periodenmatrix τ — Genus 1 (SL(2,)-reduziert)
Fundamentalbereich-Polygon — Genus 1 CCW-Parallelogramm
4g-Polygon-Randlauf — Genus g > 1 TODO Phase 8
Periodenmatrix Siegel Ω — Genus g ≥ 2 TODO Phase 8
Globale Uniformisierung — Genus g ≥ 2 Phase 8 geplant
Clausen / Lobachevsky / ImLi₂
Poincaré-Disk / Lorentz-Boost Visualisierung
Mesh I/O + Serialisierung XML/CoHDS OFF/OBJ/PLY + JSON/XML
Interaktiver Viewer jReality libigl/GLFW

HyperIdeal Hessian — numerisch vs. analytisch

Der analytische Hessian des HyperIdeal-Funktionals erfordert Differentiation durch die Kette (bᵢ, aₑ) → lᵢⱼ → ζ₁₃/₁₄/₁₅ → αᵢⱼ / βᵢ (vier Vertex-Typ-Kombinationen pro Kante). conformallab++ verwendet stattdessen einen symmetrisierten Finite-Differenzen-Hessian:

H[i,j] = ( G(x + ε·eⱼ)[i]  G(x  ε·eⱼ)[i] ) / (2ε)

O(ε²)-genau (≈ 10⁻¹⁰ relativer Fehler bei ε = 10⁻⁵), PSD durch strikte Konvexität (Springborn 2020), kostet n zusätzliche Gradient-Auswertungen pro Newton-Schritt. Für Meshes mit < 500 DOFs ist der Unterschied in der Wandzeit vernachlässigbar. Der analytische Hessian ist für Phase 8 geplant.


Für Mathematiker — Bibliothek erweitern

Mentales Modell

ConformalMesh           — Halfedge-Mesh (CGAL::Surface_mesh)
    + Property-Maps     — per-Vertex/Edge Daten (λ, θ, α, DOF-Index, …)

Maps-Struct             — sammelt alle Property-Maps für ein Funktional
    theta_v[v]          — Zielwinkel bei Vertex v  (Eingabe)
    v_idx[v]            — DOF-Index, oder 1 wenn gepinnt
    e_idx[e]            — DOF-Index für Kanten-DOFs (nur HyperIdeal)

x ∈ ℝⁿ                 — DOF-Vektor, den der Solver optimiert

evaluate_*(mesh, x, maps)  → { Energie, Gradient, … }
newton_*(mesh, x0, maps)   → { x*, Iterationen, converged, … }

Die Mesh-Geometrie (Vertex-Positionen) dient nur zur Initialisierung der Log-Kantenlängen λ°. Danach arbeitet der Solver ausschließlich im x-Raum.

Neues Funktional hinzufügen

  1. Maps-Struct: setup_my_maps(mesh) mit Property-Maps für λ, θ_v, v_idx
  2. Energie + Gradient: Schleife über mesh.faces(), akkumuliere in grad[v_idx[v]]
  3. Gradient-Check: Finite-Differenzen-Verifikation (Vorlage in jedem test_*_functional.cpp)
  4. Newton-Solver: solve_linear_system(H, -G, &used_fallback) direkt nutzen

Halfedge-Mesh navigieren

for (auto f : mesh.faces()) {
    auto h0 = mesh.halfedge(f);
    auto h1 = mesh.next(h0);
    auto h2 = mesh.next(h1);

    Vertex_index v_opp = mesh.target(h2);  // dem Halfedge h0 gegenüberliegend
    int dof = maps.v_idx[v_opp];           // 1 = gepinnt

    bool is_boundary = mesh.is_border(mesh.opposite(h0));
}

Neue Daten am Mesh befestigen

auto [curv, created] = mesh.add_property_map<Vertex_index, double>("v:my_curv", 0.0);
curv[v] = 1.234;

Schnell-Start-Checkliste

  1. examples/example_layout.cpp lesen — zeigt die vollständige Pipeline in ~120 Zeilen
  2. cmake -S code -B build -DWITH_CGAL=ON && cmake --build build --target example_layout
  3. Gradient-Check-Test in tests/cgal/ hinzufügen (beliebigen GradientCheck_*-Block kopieren)
  4. Verschiedene Zielwinkel ausprobieren: maps.theta_v[v] = M_PI / 3 für alle Innen-Vertices. Die GaussBonnet-Bedingung Σ(2π Θ_v) = 2π·χ(M) muss erfüllt sein.
  5. Konvergenz beobachten: NewtonResult enthält iterations und grad_inf_norm

Weiterführende Literatur

Quelle Bezug
Springborn — Ideal Hyperbolic Polyhedra and Discrete Uniformization (2020) HyperIdeal-Funktional; ζ₁₃/₁₄/₁₅ in hyper_ideal_geometry.hpp
Pinkall, Polthier — Computing Discrete Minimal Surfaces (1993) Kotangenten-Laplace in euclidean_hessian.hpp
Luo — Combinatorial Yamabe Flow on Surfaces (2004) Inversive-Distance-Funktional (noch nicht portiert)
Bobenko, Springborn — Variational Principles for Circle Patterns (2004) Hintergrund für das Winkelsum-Variationsprinzip
Erickson, Whittlesey — Greedy Optimal Homotopy and Homology Generators (SODA 2005) Tree-Cotree-Algorithmus in cut_graph.hpp

Schlüssel-Designentscheidungen

CGAL als CoHDS-Ersatz. CGAL::Surface_mesh<Point3> ersetzt die Java-CoHDS-Halfedge-Datenstruktur. Vertex/Edge/Face/Halfedge-Deskriptoren sind typisierte Integer.

Property-Maps. mesh.add_property_map<Vertex_index, double>("v:lambda", 0.0) ersetzt das Java-Adapter/Decorator-Pattern.

DOF-Vektor-Konvention. Alle Funktionale verwenden x indiziert durch v_idx[v] / e_idx[e] (1 = gepinnt). Einheitlich über alle drei Geometrien.

Priority-BFS. Faces werden in aufsteigender BFS-Tiefe verarbeitet (Min-Heap über depth = max(depth[v_src], depth[v_tgt]) + 1). Dies minimiert die Akkumulation von Trilaterations-Fehlern — je weiter eine Fläche vom Ursprung entfernt ist, desto später wird sie platziert.

halfedge_uv-Semantik. halfedge_uv[h.idx()] ist das UV von source(h) aus Sicht von face(h). An Naht-Halfedges tragen die beiden gegenüberliegenden Halfedges unterschiedliche UV-Werte — so erhält jede Fläche ihre eigene Kopie eines Naht-Vertex für GPU-Texturatlas ohne Vertex-Duplizierung.

HyperIdeal Hessian via FD. Der analytische Hessian durch ζ13/14/15 → lij → β/α ist auf Phase 8 verschoben. Ein symmetrischer FD-Hessian ist O(ε²)-genau, PSD durch strikte Konvexität und für < 500 DOFs ausreichend.

Sphärischer Hessian Vorzeichen. Die sphärische Energie ist konkav (Hessian NSD). Newton löst (H)·Δx = G, das Vorzeichen wird transparent in newton_spherical behandelt.


CI

Tests laufen automatisch bei Push auf main, dev und claude/**-Branches via selbst-gehostetem Gitea-Actions-Runner (eulernest, ARM64). Nur conformallab_tests läuft in CI (kein Boost/CGAL dort).

# CI-Image neu bauen und pushen
docker buildx build \
  --platform linux/arm64 \
  -f .gitea/docker/Dockerfile.ci-cpp \
  -t git.eulernest.eu/conformallab/ci-cpp:latest \
  --push \
  .gitea/docker/

Roadmap

Phase 1   Clausen / Lobachevsky / ImLi₂                     ✅ abgeschlossen
Phase 2   Hyper-ideal Geometrie (ζ, lᵢⱼ, αᵢⱼ, σᵢ)         ✅ abgeschlossen
Phase 3   CGAL Infrastruktur + alle drei Funktionale
          + analytische Hessians (Eucl. + Sphär.)            ✅ abgeschlossen
Phase 4   Newton-Solver + SparseQR-Fallback + Mesh-I/O
          + Beispiel-Programme                               ✅ abgeschlossen
Phase 5   BFS-Layout + CLI + JSON/XML-Serialisierung         ✅ abgeschlossen
          → 95 Tests

Phase 6   Layout-Erweiterung (Java-Parität I)                ✅ abgeschlossen
          → gauss_bonnet.hpp: χ, Genus, Σ(2π-Θ_v) Check + Enforce
          → cut_graph.hpp: Tree-Cotree (EricksonWhittlesey 2005), 2g Schnitt-Kanten
          → Exakte hyperbolische Trilateration (Möbius + Kosinussatz)
          → normalise_{euclidean,hyperbolic,spherical}
          → CutGraph* + HolonomyData* in allen Layout-Funktionen
          → 121 Tests (+26 Phase-6-Tests)

Phase 7   Layout-Erweiterung (Java-Parität II)               ✅ abgeschlossen
          → layout.hpp: Priority-BFS (Min-Heap, BFS-Tiefe)
          → layout.hpp: MobiusMap — T(z)=(az+b)/(cz+d), from_three, compose
          → layout.hpp: halfedge_uv — Naht-bewusstes UV pro Halfedge
          → layout.hpp: Möbius-Holonomie (SU(1,1) pro Schnitt-Kante, hyperbolisch)
          → layout.hpp: best_root_face (größte 3D-Fläche, 1.5× Interior-Bonus)
          → layout.hpp: Flächen-gewichtete iterative Möbius-Zentrierung (Fréchet-Mittel)
          → period_matrix.hpp: τ = ω₂/ω₁ ∈ , SL(2,)-Reduktion
          → fundamental_domain.hpp: CCW-Parallelogramm, Kanten-Identifikationen,
                                    Kachelkopien; 4g-Polygon-Randlauf → TODO Phase 8
          → 158 Tests (+37 Phase-7-Tests)

Phase 8   (geplant)
          → Analytischer HyperIdeal-Hessian (direkte Ableitung durch ζ-Kette)
          → 4g-Polygon-Randlauf für Genus g > 1 (Grenzwert-Walk auf geschnittenem Mesh)
          → Siegel-Periodenmatrix Ω (g×g, g ≥ 2) via Integration holomorpher Differentiale
          → Vollständige globale Uniformisierung geschlossener Flächen beliebigen Genus
          → Inversive-Distance-Funktional (Luo 2004)

Lizenz

conformallab++ steht unter der MIT-Lizenz (siehe LICENSE).

Description
ConformalLab C++ port
Readme MIT 235 MiB
Languages
C++ 94.8%
Shell 2.7%
CMake 1.4%
Python 0.9%
C 0.2%