#pragma once // mesh_builder.hpp // // Factory functions that build simple reference meshes for testing and examples. // All functions return a ConformalMesh (CGAL::Surface_mesh). // // Replaces Java mesh generators: // CoHDS generators (convex hull, hyper-ideal generator) come later (Phase 3c/4). // These builders cover the minimal meshes needed for functional unit tests. #include "conformal_mesh.hpp" #include "constants.hpp" #include #include namespace conformallab { // ── Single triangle ────────────────────────────────────────────────────────── // // v2 // | \ // | \ // v0 ─ v1 // // Returns a mesh with 1 face, 3 vertices, 3 edges. // The triangle lies in the xy-plane with a right angle at v0. inline ConformalMesh make_triangle( double x0=0, double y0=0, double x1=1, double y1=0, double x2=0, double y2=1) { ConformalMesh mesh; auto v0 = mesh.add_vertex(Point3(x0, y0, 0)); auto v1 = mesh.add_vertex(Point3(x1, y1, 0)); auto v2 = mesh.add_vertex(Point3(x2, y2, 0)); mesh.add_face(v0, v1, v2); return mesh; } // ── Regular tetrahedron ────────────────────────────────────────────────────── // // 4 vertices, 4 faces, 6 edges. // Euler characteristic: V - E + F = 4 - 6 + 4 = 2 (sphere topology). // Used to test closed-surface traversal. inline ConformalMesh make_tetrahedron() { ConformalMesh mesh; // Vertices of a regular tetrahedron centred at origin, edge length √2·2 auto v0 = mesh.add_vertex(Point3( 1, 1, 1)); auto v1 = mesh.add_vertex(Point3( 1, -1, -1)); auto v2 = mesh.add_vertex(Point3(-1, 1, -1)); auto v3 = mesh.add_vertex(Point3(-1, -1, 1)); // 4 outward-facing triangles (consistent winding) mesh.add_face(v0, v2, v1); // bottom (z=-1 side) mesh.add_face(v0, v1, v3); // front (y=-1 side) mesh.add_face(v0, v3, v2); // left (x=-1 side) mesh.add_face(v1, v2, v3); // back return mesh; } // ── Two-triangle strip ─────────────────────────────────────────────────────── // // v2 ─ v3 // | \ | // v0 ─ v1 // // 4 vertices, 2 faces, 5 edges (1 interior edge v1–v2 shared by both faces). // Useful for testing edge-interior vs edge-boundary distinction. inline ConformalMesh make_quad_strip() { ConformalMesh mesh; auto v0 = mesh.add_vertex(Point3(0, 0, 0)); auto v1 = mesh.add_vertex(Point3(1, 0, 0)); auto v2 = mesh.add_vertex(Point3(0, 1, 0)); auto v3 = mesh.add_vertex(Point3(1, 1, 0)); mesh.add_face(v0, v1, v2); // lower-left triangle mesh.add_face(v1, v3, v2); // upper-right triangle (shares edge v1–v2) return mesh; } // ── Regular flat polygon fan ───────────────────────────────────────────────── // // n triangles sharing a central vertex; forms a disk topology (boundary). // Used to verify valence-n vertex traversal. inline ConformalMesh make_fan(int n) { CGAL_precondition(n >= 3); ConformalMesh mesh; auto center = mesh.add_vertex(Point3(0, 0, 0)); const double dtheta = TWO_PI / n; std::vector rim(n); for (int i = 0; i < n; ++i) { double a = i * dtheta; rim[i] = mesh.add_vertex(Point3(std::cos(a), std::sin(a), 0)); } for (int i = 0; i < n; ++i) mesh.add_face(center, rim[i], rim[(i+1) % n]); return mesh; } // ── Spherical tetrahedron (vertices on the unit sphere) ─────────────────────── // // The four vertices of a regular tetrahedron projected onto the unit sphere. // Starting from (±1,±1,±1), dividing by √3 gives unit-length positions. // All edge lengths equal arccos(−1/3) ≈ 1.9106 radians. // Used for SphericalFunctional tests (all four faces are valid spherical triangles). inline ConformalMesh make_spherical_tetrahedron() { ConformalMesh mesh; const double s = 1.0 / std::sqrt(3.0); auto v0 = mesh.add_vertex(Point3( s, s, s)); auto v1 = mesh.add_vertex(Point3( s, -s, -s)); auto v2 = mesh.add_vertex(Point3(-s, s, -s)); auto v3 = mesh.add_vertex(Point3(-s, -s, s)); mesh.add_face(v0, v2, v1); mesh.add_face(v0, v1, v3); mesh.add_face(v0, v3, v2); mesh.add_face(v1, v2, v3); return mesh; } // ── Octahedron face triangle (vertices on the unit sphere) ──────────────────── // // One face of a regular octahedron: the triangle (1,0,0)→(0,1,0)→(0,0,1). // All edge lengths equal arccos(0) = π/2. // The corner angles are all π/2 (right-angled spherical triangle). // base log-length: λ° = 2·log(sin(π/4)) = 2·log(1/√2) = −log(2) ≈ −0.6931. inline ConformalMesh make_octahedron_face() { ConformalMesh mesh; auto v0 = mesh.add_vertex(Point3(1, 0, 0)); auto v1 = mesh.add_vertex(Point3(0, 1, 0)); auto v2 = mesh.add_vertex(Point3(0, 0, 1)); mesh.add_face(v0, v1, v2); return mesh; } } // namespace conformallab