Files
ConformalLabpp/code/tests/cgal/CMakeLists.txt
Tarik Moussa 1375878d9d
All checks were successful
C++ Tests / test-fast (pull_request) Successful in 2m31s
C++ Tests / quality-gates (pull_request) Has been skipped
C++ Tests / test-cgal (pull_request) Has been skipped
feat(p1): CLI extensions + quality measures + stereographic layout
Implement Phase-Session P1 quick wins (4 independent additions):

9h.1: Add --tol and --max-iter CLI options to conformallab_core
  - Newton solver tolerance [default 1e-8]
  - Newton iteration limit [default 200]
  - Thread both through run_euclidean / run_spherical / run_hyper_ideal
  - Update CLI parameter table in documentation

9h.2: Add -g cp_euclidean and -g inversive_distance geometry routes
  - run_cp_euclidean() & run_inversive_distance() pipelines (~60 lines each)
  - Face-based DOF assignment for CP-Euclidean
  - Vertex-based DOF assignment for Inversive-Distance
  - Both integrated into CLI geometry validator (IsMember)

9g.1: Create conformal_quality.hpp with validation measures
  - IsothermicityMeasure: metric anisotropy (conformality deviation)
  - DiscreteConformalEquivalenceMeasure: length-cross-ratio residuals
  - FlippedTriangles: detects inverted/degenerate triangles
  - LengthCrossRatio: discrete conformal invariant computation
  - ConvergenceUtility: aggregated convergence statistics (max/mean/sum)
  - Ported from Java: plugin/visualizer + convergence utilities
  - Includes sanity tests validating finite outputs on valid layouts

9d.3: Create stereographic_layout.hpp for S² → ℂ projection
  - Stereographic projection from north pole: S² → ℂ ∪ {∞}
  - Inverse projection: ℂ → S² for round-trip validation
  - Möbius centring: centres the 2-D point cloud at origin
  - stereographic_layout(Layout3D) -> Layout2D conversion
  - Round-trip tests: south pole, equator, random sphere points
  - Tests: projection/inverse consistency, north pole handling

Test results: 336/336 CGAL tests pass (272 pre-existing + 64 new from all phases)
- conformal_quality.cpp: 13 new tests (measures, isothermic, dce, convergence)
- stereographic_layout.cpp: 10 new tests (projection, inverse, round-trip, layout)

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-06-01 01:25:43 +02:00

273 lines
12 KiB
CMake
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.

# tests/cgal/CMakeLists.txt
#
# CGAL-dependent test target. Only built when -DWITH_CGAL=ON.
# Requires Boost (find_package(Boost REQUIRED) is called in the root CMakeLists).
#
# Run with:
# cmake -S code -B build -DWITH_CGAL=ON
# cmake --build build --target conformallab_cgal_tests
# ctest --test-dir build -R cgal
add_executable(conformallab_cgal_tests
# ── Phase 3a: mesh infrastructure ──────────────────────────────────────
test_conformal_mesh.cpp
# ── Phase 3b: HyperIdealFunctional ─────────────────────────────────────
test_hyper_ideal_functional.cpp
# ── Phase 3c + 3e: SphericalFunctional + gauge-fix ────────────────────
test_spherical_functional.cpp
# ── Phase 3d: EuclideanCyclicFunctional ───────────────────────────────
test_euclidean_functional.cpp
# ── Phase 3f: Hessians (cotangent Laplacian, spherical + Euclidean) ───
test_euclidean_hessian.cpp
test_spherical_hessian.cpp
# ── Phase 9b: Hyper-ideal Hessian — block-FD vs full-FD validation ───
# Verifies the O(F·36) block-local Hessian agrees with the
# O(F·n) full-FD baseline. Java upstream has no Hessian at all
# (HyperIdealFunctional.hasHessian() returns false) — both
# variants are conformallab++ extensions beyond the port.
test_hyper_ideal_hessian.cpp
# ── Phase 4a: Newton solver ────────────────────────────────────────────
test_newton_solver.cpp
# ── Phase 4b: Mesh I/O (CGAL::IO) ─────────────────────────────────────
test_mesh_io.cpp
# ── Phase 4c: End-to-end pipeline + user examples ─────────────────────
test_pipeline.cpp
# ── Phase 5: Layout / embedding + serialization ────────────────────────
test_layout.cpp
# ── Phase 6: GaussBonnet, cut graph, exact trilateration, normalisation
test_phase6.cpp
# ── Phase 7: Java-parity layout — MobiusMap, priority BFS, halfedge_uv,
# period matrix, fundamental domain, tiling
test_phase7.cpp
# ── Java parity: geometry utility tests ──────────────────────────────────
# Ported from CuttinUtilityTest, UnwrapUtilityTest,
# ConvergenceUtilityTests, HomologyTest. All tests active —
# the v0.7.0 genus-2 homology stub was implemented in Phase 7
# (HomologyGenerators.Genus2_FourCutEdges, brezel2.obj).
test_geometry_utils.cpp
# ── Scalability smoke tests ────────────────────────────────────────────────
# Newton convergence on large real-world meshes (cathead, brezel, brezel2).
# Assert correctness only (< 30 iterations, ||G|| < 1e-8).
# Wall-clock time is printed for documentation but NOT asserted,
# so the tests remain stable on slow CI hardware (Raspberry Pi ARM64).
test_scalability_smoke.cpp
# ── Phase 8 MVP: new CGAL-style public API ────────────────────────────────
# First client of Conformal_map_traits.h + Discrete_conformal_map.h.
# Acceptance probe before Phase 9a (Inversive-Distance) lands.
test_cgal_traits_mvp.cpp
# ── Phase 9a.1: CPEuclideanFunctional (BPS 2010 circle packing) ──────────
# Face-based circle-packing functional ported from
# CPEuclideanFunctional.java. Reference: Bobenko-Pinkall-Springborn 2010.
test_cp_euclidean_functional.cpp
# ── Phase 9a.2: InversiveDistance (Luo 2004 + Glickenstein 2011) ─────────
# Vertex-based inversive-distance circle-packing functional. No Java
# reference; implemented from the literature. Cross-validated against
# EuclideanCyclicFunctional at the natural initial geometry (u = 0).
test_inversive_distance_functional.cpp
# ── Phase 9a: Newton solvers for the two new circle-packing functionals ──
# Convergence tests for newton_cp_euclidean (analytic Hessian) and
# newton_inversive_distance (FD Hessian).
test_newton_phase9a.cpp
# ── Tier-3 Java cross-validation: Lawson square-tiled HyperIdeal ─────────
# Low-level half-edge genus-2 generator + golden-vector convergence.
test_lawson_hyperideal.cpp
# ── Pn projective-metric substrate (de.jreality.math.Pn port) ───────────
# Inner product / norm / distance / geodesic interpolation in
# Euclidean, Elliptic, Hyperbolic signatures.
test_pn_geometry.cpp
# ── Phase 8b-Lite: CGAL entry wrappers for the 4 non-Euclidean modes ─────
# Spherical, HyperIdeal, CircleP-Euclidean, Inversive-Distance via
# <CGAL/Discrete_*.h> public API + Conformal_layout.h wrapper.
test_cgal_phase8b_lite.cpp
# ── Phase 9g.1: Conformal quality measures ─────────────────────────────────
# IsothermicityMeasure, DiscreteConformalEquivalenceMeasure, FlippedTriangles,
# LengthCrossRatio, ConvergenceUtility. Validates layout correctness and
# convergence metrics (ported from Java visualizer + convergence utilities).
test_conformal_quality.cpp
# ── Phase 9d.3: Stereographic projection for spherical layouts ──────────────
# Converts spherical layout (S²) to 2-D conformal map via stereographic
# projection + Möbius centring. Tests round-trip consistency.
test_stereographic_layout.cpp
)
target_include_directories(conformallab_cgal_tests SYSTEM PRIVATE
${CMAKE_SOURCE_DIR}/deps/eigen-3.4.0
${CMAKE_SOURCE_DIR}/deps/CGAL-6.1.1/include
${CMAKE_SOURCE_DIR}/deps/single_includes
${Boost_INCLUDE_DIRS}
)
target_include_directories(conformallab_cgal_tests PRIVATE
${CMAKE_SOURCE_DIR}/include
)
target_compile_definitions(conformallab_cgal_tests PRIVATE
CGAL_DISABLE_GMP
CGAL_DISABLE_MPFR
# Data directory — absolute path to code/data/ at build time.
# Used by tests that load real mesh files (cathead.obj, brezel2.obj, …).
CONFORMALLAB_DATA_DIR="${CMAKE_SOURCE_DIR}/data"
)
# Suppress warnings from CGAL/Boost headers
target_compile_options(conformallab_cgal_tests PRIVATE
$<$<CXX_COMPILER_ID:GNU,Clang,AppleClang>:-Wno-unused-parameter>
)
# Fast test-build mode (lever #10): -O0 -g overrides the inherited
# Release-mode -O3 + -DNDEBUG. Applies only to this test target.
if(CONFORMALLAB_FAST_TEST_BUILD)
target_compile_options(conformallab_cgal_tests PRIVATE
$<$<CXX_COMPILER_ID:GNU,Clang,AppleClang>:-O0 -g -UNDEBUG>
)
endif()
# ── Low-memory build mode (for RAM-constrained CI runners, e.g. Raspberry Pi) ──
#
# Problem: CGAL + Eigen at -O3 drives cc1plus peak RAM to ~600-800 MB per
# Unity compilation unit on ARM64 Linux. A 1600 MB container limit with a
# batch of 4 files per unit causes OOM-kill during the build.
#
# This flag enables three orthogonal memory-saving measures:
#
# 1. -O0 (no debug info): drops cc1plus backend RAM by ~60-70 %.
# Optimizer passes (inlining, register allocation, constant propagation)
# dominate the backend. At -O0 they are entirely skipped → peak per
# TU falls from ~700 MB to ~150-200 MB on ARM64.
# We omit -g deliberately: debug info adds ~30-40 % object-file size
# and increases linker RSS. CI needs "does it compile + do tests pass",
# not debuggability.
#
# 2. PCH OFF: the precompiled header itself consumes ~200 MB to compile
# and is re-read by every TU. Disabling it saves the one-time PCH
# compilation cost; each TU re-parses CGAL headers, but at -O0 this
# is fast.
#
# 3. UNITY_BUILD_BATCH_SIZE=1: one source file per unity unit. Removes
# the "4 files × CGAL parse cost" multiplier; each cc1plus process
# only sees one file worth of templates.
#
# 4. Linker memory flag (GCC/Clang only): --no-keep-memory tells GNU ld
# to release symbol table memory after each input file instead of
# keeping it for cross-reference. Reduces linker RSS by 15-25 % at
# the cost of slightly longer link time.
#
# Activate with:
# cmake -S code -B build -DWITH_CGAL_TESTS=ON \
# -DCONFORMALLAB_LOW_MEMORY_BUILD=ON
# Expected peak per cc1plus: ~150-200 MB → fits in 1800-2000 MB container.
# Test runtime is 2-4× slower than Release (CGAL traversals unoptimized),
# but correctness is unaffected.
option(CONFORMALLAB_LOW_MEMORY_BUILD
"Build CGAL tests with -O0, no PCH, UNITY_BATCH_SIZE=1 for RAM-constrained CI." OFF)
if(CONFORMALLAB_LOW_MEMORY_BUILD)
message(STATUS "CONFORMALLAB_LOW_MEMORY_BUILD active: -O0, no PCH, unity batch 1.")
# 1. -O0, no debug info
target_compile_options(conformallab_cgal_tests PRIVATE
$<$<CXX_COMPILER_ID:GNU,Clang,AppleClang>:-O0 -UNDEBUG>
)
# 2. PCH off — force-override the option so the block below is skipped
set(CONFORMALLAB_USE_PCH OFF CACHE BOOL "" FORCE)
# 3. Unity batch size = 1 (one source file per compilation unit)
set_target_properties(conformallab_cgal_tests PROPERTIES
UNITY_BUILD ON
UNITY_BUILD_MODE BATCH
UNITY_BUILD_BATCH_SIZE 1)
# 4. Linker memory hint (GNU ld / lld)
target_link_options(conformallab_cgal_tests PRIVATE
$<$<CXX_COMPILER_ID:GNU>:-Wl,--no-keep-memory>)
endif()
target_link_libraries(conformallab_cgal_tests PRIVATE GTest::gtest_main)
# ── Compile-time speed-up: precompiled headers ───────────────────────────────
#
# The CGAL+Eigen template soup dominates every TU in this target:
# measured at 5.9 s per minimal "include <CGAL/Discrete_conformal_map.h>"
# TU on Apple M1. A shared PCH absorbs that cost once, slashing the
# total wall-clock from ~78 s (j8) to ~25 s (3×).
#
# Opt-out with -DCONFORMALLAB_USE_PCH=OFF if the PCH itself misbehaves
# (e.g. older toolchains that don't share PCH across translation units
# reliably) — falls back to the historical "every TU re-parses CGAL"
# build mode.
option(CONFORMALLAB_USE_PCH
"Enable precompiled headers for the CGAL test target." ON)
if(CONFORMALLAB_USE_PCH)
# Per-target Unity Build property takes precedence over the global
# CMAKE_UNITY_BUILD; honour CONFORMALLAB_DEV_BUILD's preference here
# so `-DCONFORMALLAB_DEV_BUILD=ON` truly turns Unity Build off for
# incremental-rebuild workflows.
if(NOT CONFORMALLAB_DEV_BUILD)
set_target_properties(conformallab_cgal_tests PROPERTIES
# Unity-builds amortise the per-TU CGAL+Eigen header cost
# across several tests in the same compile. Batch size 4
# keeps gtest's TEST(...) macros + per-file `using
# namespace …` from colliding while still cutting parser
# cost ~4×.
UNITY_BUILD ON
UNITY_BUILD_MODE BATCH
UNITY_BUILD_BATCH_SIZE 4)
endif()
target_precompile_headers(conformallab_cgal_tests PRIVATE
# CGAL headers that every test transitively includes.
<CGAL/Surface_mesh.h>
<CGAL/Simple_cartesian.h>
<CGAL/Kernel_traits.h>
<CGAL/boost/graph/iterator.h>
<CGAL/Polygon_mesh_processing/triangulate_faces.h>
# Eigen blocks that drive the slowest template instantiations
# (SelfAdjointEigenSolver<Matrix<2,2>>, ColPivHouseholderQR<
# Matrix<complex,3,3>>, sparse Cholesky + QR fallback).
<Eigen/Dense>
<Eigen/Sparse>
<Eigen/SparseCholesky>
<Eigen/SparseQR>
# GoogleTest itself; every test includes it.
<gtest/gtest.h>
# std headers that appear in every test.
<vector>
<string>
<cmath>
<complex>
)
endif()
include(GoogleTest)
gtest_discover_tests(conformallab_cgal_tests
TEST_PREFIX "cgal."
DISCOVERY_TIMEOUT 60
)