Phase 7.5: Doxygen infrastructure + Phase 8 design freeze
Some checks failed
C++ Tests / test-fast (push) Successful in 1m57s
C++ Tests / test-fast (pull_request) Successful in 2m19s
C++ Tests / test-cgal (push) Has been skipped
C++ Tests / test-cgal (pull_request) Failing after 2m26s

Adds the Doxygen documentation pipeline as the bridge from Phase 7
(porting complete) to Phase 8 (CGAL package). Also captures the
strategic Phase 8 decisions taken on 2026-05-19.

Infrastructure
──────────────
* Doxyfile         — CGAL-style minimal configuration, HTML-only,
                     INPUT=code/include + doc/, excludes deps/ and
                     macOS Finder duplicates
* code/CMakeLists  — `doc` target via find_package(Doxygen QUIET);
                     silently disabled if Doxygen is not installed
* README           — `cmake --build build --target doc` instructions
* .gitignore       — exclude doc/doxygen/ output

Phase 8 strategic decisions (recorded in doc/api/cgal-package.md)
────────────────────────────────────────────────────────────────
* Submission to CGAL: pre-submission-ready, 12+ months horizon, MIT preserved
* Mesh-type flexibility: generic FaceGraph + HalfedgeGraph
* Parameter style: CGAL Named Parameters
* Default kernel: Simple_cartesian<double> (status quo)
* Architecture: 3-layer wrapper, no algorithm duplication
* Acceptance test: Phase 9a (Inversive-Distance) as first new client

CLAUDE.md updated with a compact Phase 8 decision table.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Tarik Moussa
2026-05-19 19:55:50 +02:00
parent e958afbd19
commit 02fb80ee3e
6 changed files with 434 additions and 103 deletions

View File

@@ -1,77 +1,211 @@
# Phase 8 — CGAL Package Design
> **Status: planned.** This document describes the target architecture for Phase 8.
> No code has been written yet. The design is informed by the CGAL package submission
> guidelines at https://www.cgal.org/developers.html
> **Status: design frozen, implementation planned.**
> This document captures the strategic decisions taken before the first
> line of Phase 8 code is written. The decisions were taken on 2026-05-19
> after the docstring/architecture audit at the end of Phase 7.
>
> The design is informed by the CGAL package submission guidelines at
> https://www.cgal.org/developers.html and by reading the existing
> `Polygon_mesh_processing` and `Surface_mesh_parameterization` packages.
---
## Goal
## Strategic position
Integrate conformallab++ into the CGAL library as a proper CGAL package:
`Discrete_conformal_map`. The package must satisfy all CGAL submission requirements:
traits-class design, Doxygen documentation, CGAL-format test suite, and coverage of
the CGAL coding conventions.
| Question | Decision | Rationale |
|---|---|---|
| Submission to CGAL? | **Pre-submission-ready, not submission-bound.** 12+ months horizon, optional. | Keep design freedom, no editor-review pressure. Structure is valuable on its own. |
| License | **MIT preserved.** | CGAL submission would require LGPL — deferred. Current users (academic + industrial) profit from MIT. |
| Mesh-type flexibility | **Generic `FaceGraph + HalfedgeGraph`.** | Maximum CGAL value: works with `Surface_mesh`, `Polyhedron_3`, OpenMesh-adapter, pmp. |
| Parameter style | **Named Parameters** (`CGAL::parameters::vertex_curvature_map(...).max_iterations(50)`). | CGAL standard; identical UX to `PMP::triangulate_*`. |
| Default kernel | **`CGAL::Simple_cartesian<double>`.** | Status quo. Conformal geometry does not require exact predicates. |
| Backward compatibility | **Dual-layer wrapper.** `code/include/*.hpp` stays as implementation; `include/CGAL/*.h` is thin wrapper. | Existing 176 + 36 tests unchanged. New API gets new tests. |
| Algorithm code | **No duplication.** New CGAL headers delegate to existing code via property-map adapters. | Single source of truth; no parallel maintenance. |
---
## Architecture
### Three-layer model
```
┌──────────────────────────────────────────────────────────────────┐
│ Layer 3: Public CGAL API include/CGAL/*.h │
│ ───────────────────────── │
│ • Conformal_map_traits.h ← concept + default model │
│ • Discrete_conformal_map.h ← user-facing entry │
│ • Conformal_layout.h, ... │
│ Named parameters, generic over FaceGraph, Doxygen-documented. │
└──────────────────────────────────────────────────────────────────┘
│ thin wrapper, no algorithm code
┌──────────────────────────────────────────────────────────────────┐
│ Layer 2: Adapter / Traits include/CGAL/Conformal_map/ │
│ ───────────────────────── │
│ • Default_traits.h ← maps generic FaceGraph to │
│ Surface_mesh property maps │
│ • Property_map_adapter.h ← read/write u, θ, α via │
│ boost::property_map traits │
└──────────────────────────────────────────────────────────────────┘
│ uses existing algorithms as-is
┌──────────────────────────────────────────────────────────────────┐
│ Layer 1: Implementation code/include/*.hpp │
│ ───────────────────────── │
│ euclidean_functional.hpp, layout.hpp, newton_solver.hpp, ... │
│ Hardcoded to Surface_mesh + Simple_cartesian — unchanged. │
└──────────────────────────────────────────────────────────────────┘
```
---
## 8a — Traits class & concepts
The current code is tightly coupled to `CGAL::Surface_mesh<Point3>`. Phase 8a introduces
a traits class that separates the mesh type from the algorithm:
### `ConformalMapTraits` concept
The concept lists the types and operations every Traits model must provide.
```cpp
// TODO(Phase 8a): implement this header
// include/CGAL/Conformal_map_traits.h
namespace CGAL {
template<
typename MeshType, // any CGAL halfedge mesh
typename KernelType, // CGAL kernel
typename ScalarType = double
>
struct Conformal_map_traits {
using Mesh = MeshType;
using Kernel = KernelType;
using FT = ScalarType;
// ... vertex/edge/face descriptor types
// ... property map access
// Concept (documentation only; no code):
struct ConformalMapTraits {
// Types
using Triangle_mesh = ...; // model of FaceGraph + HalfedgeGraph
using FT = ...; // typically double
using Vertex_descriptor = boost::graph_traits<Triangle_mesh>::vertex_descriptor;
using Halfedge_descriptor = ...;
using Face_descriptor = ...;
// Read access (input geometry)
using Vertex_point_map = ...; // model of ReadablePropertyMap
// key: Vertex_descriptor
// value: K::Point_3
// Read/write access (conformal data)
using Lambda_pmap = ...; // u_v (scale factor) RW
using Theta_pmap = ...; // Θ_v (target curvature) R
using Vertex_index_pmap = ...; // DOF index (1 = pinned) RW
using Edge_alpha_pmap = ...; // α_e (hyperbolic only) RW
using Face_type_pmap = ...; // geometry tag per face R
// Optional output
using UV_pmap = ...; // halfedge → (u, v) ∈ ℝ² W
using Holonomy_pmap = ...; // seam edge → ω ∈ W
};
}
```
### `Default_conformal_map_traits<TM>`
The default model wraps `Surface_mesh` property maps so existing code keeps
working through the new public API.
```cpp
template <class TriangleMesh,
class K = CGAL::Simple_cartesian<double>>
struct Default_conformal_map_traits;
// Specialisation for Surface_mesh:
template <class K>
struct Default_conformal_map_traits<CGAL::Surface_mesh<typename K::Point_3>, K> {
using Triangle_mesh = CGAL::Surface_mesh<typename K::Point_3>;
using FT = typename K::FT;
using Vertex_point_map = typename Triangle_mesh::Point_property_map;
using Lambda_pmap = typename Triangle_mesh::template Property_map<vertex_descriptor, FT>;
// ... etc, using "conformal:lambda" property names
};
// Generic specialisation for other FaceGraph models will be added in 8a.2.
```
### Concept-checks
```cpp
// include/CGAL/Conformal_map_concept_checks.h
template <class Traits>
struct Conformal_map_traits_check {
static_assert(boost::is_same<...>::value, "Traits::FT must be a floating-point type");
static_assert(is_face_graph<Traits::Triangle_mesh>::value);
// ...
};
```
Concept checks will ensure any user-provided mesh satisfies the halfedge mesh concept.
---
## 8b — Public header hierarchy
## 8b — Public CGAL header hierarchy
A clean public API separate from the internal implementation:
### User-facing entry
```cpp
// include/CGAL/Discrete_conformal_map.h
namespace CGAL {
template <class TriangleMesh, class NamedParameters = parameters::Default_named_parameters>
bool discrete_conformal_map_euclidean(TriangleMesh& mesh,
const NamedParameters& np = parameters::default_values());
template <class TriangleMesh, class NamedParameters = ...>
bool discrete_conformal_map_spherical(TriangleMesh& mesh,
const NamedParameters& np = ...);
template <class TriangleMesh, class NamedParameters = ...>
bool discrete_conformal_map_hyperbolic(TriangleMesh& mesh,
const NamedParameters& np = ...);
} // namespace CGAL
```
### Named parameter vocabulary
| Parameter | Type | Default | Meaning |
|---|---|---|---|
| `vertex_curvature_map(pmap)` | ReadablePropertyMap | `2π` at interior, `π` at boundary | Θᵥ values |
| `fixed_vertex_pmap(pmap)` | ReadablePropertyMap<bool> | First vertex pinned | Which vertices are pinned (gauge) |
| `max_iterations(n)` | int | 200 | Newton iteration limit |
| `gradient_tolerance(eps)` | FT | 1e-10 | `‖G‖∞` threshold |
| `vertex_index_map(pmap)` | LvaluePropertyMap | DOF auto-assigned | Allows user to override DOF assignment |
| `output_uv_map(pmap)` | WritablePropertyMap | none | If set, writes UV layout into pmap |
| `cut_graph(cg)` | `Conformal_cut_graph` | auto-computed | Pre-computed seam edges (mandatory for closed surfaces) |
| `geom_traits(t)` | model of ConformalMapTraits | `Default_*` | Custom traits |
### Modular headers
```
include/CGAL/
Discrete_conformal_map.h ← single user-facing include
Conformal_map_traits.h
Conformal_newton_solver.h
Conformal_layout.h
Conformal_cut_graph.h
conformal_map_package.h ← PackageDescription
├── Discrete_conformal_map.h ← user-facing entry (1 include for casual use)
├── Conformal_map_traits.h ← concept + Default_conformal_map_traits
├── Conformal_map_concept_checks.h
├── Conformal_newton_solver.h ← standalone Newton (advanced users)
├── Conformal_layout.h ← layout + holonomy
├── Conformal_cut_graph.h ← orthogonal algorithm
├── Conformal_period_matrix.h ← genus-1 τ (conformallab++ unique)
├── Conformal_holonomy.h ← Möbius holonomy (conformallab++ unique)
└── Conformal_map/ ← CGAL convention: implementation details
├── Default_traits.h
├── Property_map_adapter.h
├── Newton_iteration.h
└── Internal_helpers.h
```
All existing `include/*.hpp` headers remain as internal implementation details,
not part of the public CGAL API.
---
## 8c — CGAL-style documentation
```
doc/Conformal_map/
PackageDescription.txt
User_manual.md
Reference_manual.md
fig/ pipeline diagrams, mathematical figures
├── PackageDescription.txt ← CGAL Doxygen package file
├── Conformal_map.txt ← Doxygen User_manual
├── examples.txt ← linkable example code
├── dependenciestextual list
└── fig/ ← pipeline diagrams, math figures
```
All public functions and concepts require Doxygen comments following the CGAL style.
All public functions, concepts, and types require Doxygen. See **Phase 7.5** (below).
---
@@ -79,88 +213,113 @@ All public functions and concepts require Doxygen comments following the CGAL st
```
test/Conformal_map/
CMakeLists.txt ← CGAL-format, uses find_package(CGAL)
test_euclidean_functional.cpp
test_newton_solver.cpp
...
├── CMakeLists.txt ← CGAL-format, uses find_package(CGAL)
├── test_euclidean_traits.cpp ← traits concept checks
├── test_polyhedron_3_backend.cpp ← tests with Polyhedron_3 as mesh
├── test_named_parameters.cpp
└── data/ ← test meshes
```
The existing GTest suite remains. CGAL-format tests are added alongside as a separate
target, following the CGAL test infrastructure conventions.
The existing GTest suite at `code/tests/cgal/` remains; CGAL-format tests are
added alongside as a separate target. CI runs both.
---
## 8e — Declarative YAML pipeline
A lightweight YAML format for reproducible experiments. The CLI accepts
A lightweight YAML format for reproducible experiments. CLI accepts
`--pipeline experiment.yml`; the validator checks `require`/`provide` tokens
before execution.
**Full concept & design specification:** [doc/concepts/declarative-pipeline.md](../concepts/declarative-pipeline.md)
— token vocabulary, validation algorithm, 5 complete examples, implementation plan.
Abbreviated example:
**Full spec:** [doc/concepts/declarative-pipeline.md](../concepts/declarative-pipeline.md)
— token vocabulary, validation algorithm, 5 complete examples.
```yaml
pipeline:
name: flat_torus_period
geometry: euclidean
input:
source: data/torus.off
input: { source: data/torus.off }
steps:
- id: setup
unit: setup_euclidean_maps
provide: [maps_initialised]
- id: gauss_bonnet
unit: enforce_gauss_bonnet
require: [maps_initialised]
provide: [gauss_bonnet_satisfied]
- id: solve
unit: newton_euclidean
require: [gauss_bonnet_satisfied]
params:
tol: 1.0e-10
max_iter: 200
provide: [x_converged]
- id: cut
unit: compute_cut_graph
require: [mesh_closed]
provide: [cut_graph]
- id: layout
unit: euclidean_layout
require: [x_converged, cut_graph]
params:
normalise: true
provide: [layout_uv, holonomy]
- id: period
unit: compute_period_matrix
require: [holonomy]
provide: [tau]
- { id: setup, unit: setup_euclidean_maps, provide: [maps_initialised] }
- { id: gb, unit: enforce_gauss_bonnet, require: [maps_initialised], provide: [gauss_bonnet_satisfied] }
- { id: solve, unit: newton_euclidean, require: [gauss_bonnet_satisfied], provide: [x_converged] }
- { id: cut, unit: compute_cut_graph, require: [mesh_closed], provide: [cut_graph] }
- { id: layout, unit: euclidean_layout, require: [x_converged, cut_graph], provide: [layout_uv, holonomy] }
- { id: period, unit: compute_period_matrix, require: [holonomy], provide: [tau] }
output:
layout: out/torus_layout.off
json: out/torus_result.json
tau: out/torus_tau.txt
```
The contract table in [contracts.md](contracts.md) defines the valid `require`/`provide`
token vocabulary.
---
## TODO
## Phase 7.5 — Doxygen infrastructure (prerequisite)
- [ ] Design `Conformal_map_traits.h` interface (8a)
- [ ] Define concept requirements for `MeshType` (8a)
- [ ] Create `include/CGAL/` header skeleton (8b)
- [ ] Write `PackageDescription.txt` (8c)
- [ ] Port GTest tests to CGAL format (8d)
- [ ] Implement YAML validator (8e)
- [ ] CLI: `--pipeline` flag (8e)
Before any Phase 8 code, the existing API surface must be extractable.
This is the prerequisite that bridges Phase 7 → Phase 8.
```
Phase 7.5 — Doxygen infrastructure
──────────────────────────────────
• Doxyfile (CGAL-conform: INPUT=code/include + include/CGAL,
EXCLUDE_PATTERNS="* 2.hpp")
• doxygen-awesome-css as theme (matches CGAL house style)
• CMake target: cmake --build build --target doc
• CI job: doc-build → publishes to Codeberg Pages or gitea-pages
• Extract baseline once → snapshot what is actually exported today
• Top-5 central headers (3 functional + conformal_mesh + layout)
upgraded to Doxygen comments; the rest follows during Phase 8 implementation
```
The baseline snapshot doubles as the API-design review tool: before designing
the public CGAL wrapper, we see exactly which functions, classes and free
operators exist and need to be wrapped or hidden.
---
## Validation criteria
Phase 8a is "done" when:
1. `cgal.ConformalTraits.Polyhedron_3_works` passes.
2. `cgal.ConformalTraits.Surface_mesh_default_works` passes — identical results to the legacy API.
3. The Inversive-Distance functional (Phase 9a) is implementable as the *first* new client of the traits API without architectural changes — no breaking changes to the trait concept.
4. A user can write `#include <CGAL/Discrete_conformal_map.h>` and call `discrete_conformal_map_euclidean(mesh, parameters::vertex_curvature_map(theta))` against a `Polyhedron_3` and get a valid layout.
If any of these fail, the design is iterated before continuing.
---
## Implementation order
```
1. Phase 7.5 Doxygen infrastructure + duplicate cleanup (½1 day)
2. Phase 8a.1 ConformalMapTraits concept + Default_traits (23 days)
3. Phase 8a.2 Generic FaceGraph specialisation (2 days)
4. Phase 8b.1 Discrete_conformal_map.h entry point (2 days)
5. Phase 8b.2 Layout + cut graph wrappers (2 days)
6. Phase 9a Inversive-Distance against new traits = API test (35 days)
7. Phase 8c PackageDescription.txt + User_manual.md (2 days)
8. Phase 8d CGAL-format test directory (12 days)
9. Phase 8e YAML pipeline + CLI flag (3 days)
```
**Total budget: 34 weeks net work, 68 weeks calendar.**
---
## TODO checklist
- [ ] Phase 7.5: Doxyfile + CMake doc target + duplicate cleanup
- [ ] 8a.1: `ConformalMapTraits` concept header
- [ ] 8a.1: `Default_conformal_map_traits<Surface_mesh, K>`
- [ ] 8a.2: Generic `FaceGraph` specialisation
- [ ] 8a.2: `Conformal_map_concept_checks.h`
- [ ] 8b.1: `Discrete_conformal_map.h` (3 entry functions)
- [ ] 8b.1: Named-parameter vocabulary header
- [ ] 8b.2: `Conformal_layout.h`, `Conformal_cut_graph.h` wrappers
- [ ] 9a: `inversive_distance_functional.hpp` written against new traits
- [ ] 8c: `doc/Conformal_map/PackageDescription.txt`
- [ ] 8c: User_manual + Reference_manual
- [ ] 8d: `test/Conformal_map/` CGAL-style tests
- [ ] 8e: YAML validator + CLI `--pipeline` flag