#pragma once // Copyright (c) 2024-2026 Tarik Moussa. // SPDX-License-Identifier: MIT // conformal_mesh.hpp // // Central mesh type for the discrete conformal mapping algorithms. // Replaces the Java CoHDS (de.varylab.discreteconformal.heds.CoHDS) // and its associated vertex/edge/face types (CoVertex, CoEdge, CoFace). // // Design // ------ // Java │ C++ (this file) // ─────────────────────────────┼────────────────────────────────────────── // CoHDS │ ConformalMesh (CGAL::Surface_mesh) // CoVertex / CoEdge / CoFace │ Vertex_index / Edge_index / Face_index // HyperIdealRadiusAdapter │ property_map // HalfedgeInterface adapters │ named property maps ("v:lambda", …) // // Property-map naming convention // ─────────────────────────────── // "v:lambda" per-vertex log scale factor (conformal variable u_i) // "v:theta" per-vertex target cone angle // "v:idx" per-vertex solver DOF index (-1 = pinned / boundary) // "e:alpha" per-edge intersection angle (α_ij, hyperbolic geometry) // "f:type" per-face geometry type (0=Euclidean, 1=Hyperbolic, 2=Spherical) // // All property maps are optional; add only what a given algorithm needs. // // Note on descriptor types (CGAL 6.x) // ──────────────────────────────────── // CGAL::Surface_mesh exposes its index types as nested types: // Surface_mesh::Vertex_index, ::Halfedge_index, ::Edge_index, ::Face_index // The BGL graph_traits aliases expose the same types as vertex_descriptor etc., // but those live in boost::graph_traits, not in Surface_mesh itself. // We use the Surface_mesh member names throughout for clarity. #include #include #include #include namespace conformallab { // ── Kernel ────────────────────────────────────────────────────────────────── // Simple double-precision Cartesian. Conformal mapping algorithms never // need exact arithmetic — they operate on floating-point lengths and angles. /// CGAL kernel used by all conformallab algorithms (double precision). using Kernel = CGAL::Simple_cartesian; /// 3-D point type (vertex coordinates). using Point3 = Kernel::Point_3; /// 2-D point type (UV-domain layout coordinates). using Point2 = Kernel::Point_2; // ── Mesh type ──────────────────────────────────────────────────────────────── /// Triangle mesh carrying all conformal-map data as property maps. using ConformalMesh = CGAL::Surface_mesh; // ── Index/descriptor aliases (CGAL 6.x naming) ─────────────────────────────── /// Vertex descriptor of `ConformalMesh`. using Vertex_index = ConformalMesh::Vertex_index; /// Half-edge descriptor of `ConformalMesh`. using Halfedge_index = ConformalMesh::Halfedge_index; /// Edge descriptor of `ConformalMesh`. using Edge_index = ConformalMesh::Edge_index; /// Face descriptor of `ConformalMesh`. using Face_index = ConformalMesh::Face_index; // ── Geometry type constant (replaces Java CoFace.type enum) ───────────────── /// Discrete geometry type that a face/mesh is interpreted in. /// Replaces the original Java `CoFace.type` enum. enum class GeometryType : int { Euclidean = 0, ///< Flat metric (ℝ²). Hyperbolic = 1, ///< Hyperbolic metric (ℍ²). Spherical = 2 ///< Spherical metric (S²). }; // ── Standard property-map bundles ──────────────────────────────────────────── /// Register and return the vertex-side property maps used by all five /// DCE functionals: `v:lambda` (log conformal factor), `v:theta` (target /// cone angle), `v:idx` (contiguous integer index). inline auto add_vertex_properties(ConformalMesh& mesh) { auto [lambda, ok1] = mesh.add_property_map("v:lambda", 0.0); auto [theta, ok2] = mesh.add_property_map("v:theta", 0.0); auto [idx, ok3] = mesh.add_property_map ("v:idx", -1); (void)ok1; (void)ok2; (void)ok3; return std::make_tuple(lambda, theta, idx); } /// Register and return the edge intersection-angle property `e:alpha` /// (used by the hyper-ideal functional). inline auto add_edge_properties(ConformalMesh& mesh) { auto [alpha, ok] = mesh.add_property_map("e:alpha", 0.0); (void)ok; return alpha; } /// Register and return the per-face geometry-type property `f:type`. inline auto add_face_properties(ConformalMesh& mesh) { auto [ftype, ok] = mesh.add_property_map( "f:type", static_cast(GeometryType::Euclidean)); (void)ok; return ftype; } // ── Half-edge index helper ──────────────────────────────────────────────────── // // Convert a Halfedge_index to std::size_t for use as a vector subscript. // Each functional previously duplicated this one-liner under a name like // eucl_hidx / spher_hidx / hidx. Centralised here (MINOR-4 fix). // // Implementation: the double-cast uint32_t → size_t is intentional. CGAL 6.x // Surface_mesh stores half-edge indices internally as 32-bit unsigned integers. // Casting directly to size_t on a 64-bit system would produce the same result // because CGAL index types use non-negative values, but the explicit intermediate // cast documents the assumption and silences spurious sign-conversion warnings. /// Convert a `Halfedge_index` to `std::size_t` for vector subscript use. /// Replaces the duplicated `eucl_hidx`, `spher_hidx`, `hidx` helpers. inline std::size_t halfedge_to_index(Halfedge_index h) noexcept { return static_cast(static_cast(h)); } } // namespace conformallab