// Copyright (c) 2024-2026 Tarik Moussa. // SPDX-License-Identifier: MIT // // Package: conformallab++ / Discrete_conformal_map (Phase 8 MVP, 2026-05-19) /*! \file CGAL/Conformal_map_traits.h \ingroup PkgConformalMapRef Defines the `ConformalMapTraits` concept and the default model `Default_conformal_map_traits` for the package. The concept lists the types and property maps that the discrete-conformal algorithms require from any backing data structure. By templatising the algorithms on this concept, the package can run on any CGAL halfedge mesh — `Surface_mesh`, `Polyhedron_3`, OpenMesh-adapter, pmp — without changes to the algorithm code. For Phase 8 MVP only the `Surface_mesh` specialisation is provided (specialisation 8a.1). A generic `FaceGraph` specialisation is on the roadmap as 8a.2. \sa `CGAL::Discrete_conformal_map` \sa `CGAL::parameters::vertex_curvature_map` */ #ifndef CGAL_CONFORMAL_MAP_TRAITS_H #define CGAL_CONFORMAL_MAP_TRAITS_H #include #include #include namespace CGAL { // ════════════════════════════════════════════════════════════════════════════ // \cgalConcept // // \concept ConformalMapTraits // \ingroup PkgConformalMapConcepts // // The concept `ConformalMapTraits` describes the requirements that any // Traits model must fulfil for the Discrete_conformal_map package. // // \cgalHasModelsBegin // \cgalHasModels{CGAL::Default_conformal_map_traits} // \cgalHasModelsEnd // // \section RequiredTypes Required types // // | Type | Description | // |------|-------------| // | `Triangle_mesh` | A model of CGAL `FaceGraph` + `HalfedgeGraph`. | // | `Kernel` | A CGAL kernel; defaults to `Simple_cartesian`. | // | `FT` | Field type used internally (typically `double`). | // | `Vertex_descriptor` | `boost::graph_traits::vertex_descriptor`. | // | `Halfedge_descriptor` | analogously. | // | `Edge_descriptor` | analogously. | // | `Face_descriptor` | analogously. | // // \section RequiredProperties Required property-map accessors // // The Traits class is responsible for *locating* the property maps that // the algorithm reads from and writes to. The semantics follow the // project conventions (see `doc/api/contracts.md` for the full table): // // | Property | Key | Value | Access | Used by | // |----------------------|-------------------------|-------|---------|---------| // | `vertex_points(m)` | `Vertex_descriptor` | `Point_3` | Read | input geometry | // | `theta_map(m)` | `Vertex_descriptor` | `FT` | RW | target cone angle Θᵥ | // | `vertex_index_map(m)`| `Vertex_descriptor` | `int` | RW | DOF index (−1 = pinned) | // | `lambda0_map(m)` | `Edge_descriptor` | `FT` | RW | base log-length λ°ᵢⱼ | // // Each accessor is a `static` member that returns the map; it must be // idempotent (calling twice yields the same map by name lookup). // ════════════════════════════════════════════════════════════════════════════ // ════════════════════════════════════════════════════════════════════════════ // Default_conformal_map_traits — primary template (undefined) // ════════════════════════════════════════════════════════════════════════════ // // The undefined primary template forces specialisation per mesh type. // MVP provides only the `Surface_mesh` specialisation below; further // mesh types (Polyhedron_3, OpenMesh, pmp) are deferred to Phase 8a.2. template > struct Default_conformal_map_traits; // ════════════════════════════════════════════════════════════════════════════ // Specialisation: CGAL::Surface_mesh // ════════════════════════════════════════════════════════════════════════════ /*! \ingroup PkgConformalMapRef Default traits for `CGAL::Surface_mesh`. Wraps the property maps that the existing implementation (`code/include/euclidean_functional.hpp`) attaches to a Surface_mesh under the `"ev:idx"`, `"ev:theta"`, `"ee:lam0"` etc. names. This specialisation is the only one available in Phase 8 MVP. It is selected automatically when `TriangleMesh = CGAL::Surface_mesh<...>`. \tparam K Any CGAL kernel. Defaults to `Simple_cartesian`, which is what `conformal_mesh.hpp` uses today. */ template struct Default_conformal_map_traits, K> { /// The CGAL kernel parameter; defaults to `Simple_cartesian`. using Kernel = K; /// Field type used for all scalar conformal-map data (lengths, λ, Θ, …). using FT = typename K::FT; /// 3-D point type used for vertex coordinates. using Point_3 = typename K::Point_3; /// The triangle-mesh type this specialisation targets. using Triangle_mesh = CGAL::Surface_mesh; /// Boost-graph vertex descriptor for `Triangle_mesh`. using Vertex_descriptor = typename boost::graph_traits::vertex_descriptor; /// Boost-graph half-edge descriptor for `Triangle_mesh`. using Halfedge_descriptor = typename boost::graph_traits::halfedge_descriptor; /// Boost-graph edge descriptor for `Triangle_mesh`. using Edge_descriptor = typename boost::graph_traits::edge_descriptor; /// Boost-graph face descriptor for `Triangle_mesh`. using Face_descriptor = typename boost::graph_traits::face_descriptor; // Property-map types — match the names used by setup_euclidean_maps(). /// Property map vertex → `Point_3` (the mesh's geometric embedding). using Vertex_point_map = typename Triangle_mesh::template Property_map; /// Property map vertex → target cone angle Θᵥ in radians (legacy name `ev:theta`). using Theta_pmap = typename Triangle_mesh::template Property_map; /// Property map vertex → contiguous integer index (legacy name `ev:idx`). using Vertex_index_pmap = typename Triangle_mesh::template Property_map; /// Property map edge → log of original edge length λ⁰ (legacy name `ee:lam0`). using Lambda0_pmap = typename Triangle_mesh::template Property_map; // ─── Property-map accessors ─────────────────────────────────────────── // // Each accessor returns a property map under its canonical legacy name. // If no such map exists yet it is created with sensible defaults — so // calling either `setup_euclidean_maps(m)` first or the accessor first // is equivalent. /// Return the built-in vertex-point map of `m` (the geometric embedding). static Vertex_point_map vertex_points(Triangle_mesh& m) { return m.points(); } /// Return (or create with default 2π) the target-angle property map. static Theta_pmap theta_map(Triangle_mesh& m) { auto [pm, created] = m.template add_property_map( "ev:theta", FT(2.0 * 3.141592653589793238)); (void)created; return pm; } /// Return (or create with default −1) the vertex-index property map. static Vertex_index_pmap vertex_index_map(Triangle_mesh& m) { auto [pm, created] = m.template add_property_map( "ev:idx", -1); (void)created; return pm; } /// Return (or create with default 0) the λ⁰ (initial log-length) property map. static Lambda0_pmap lambda0_map(Triangle_mesh& m) { auto [pm, created] = m.template add_property_map( "ee:lam0", FT(0)); (void)created; return pm; } }; } // namespace CGAL #endif // CGAL_CONFORMAL_MAP_TRAITS_H