/src/PROJ/src/projections/polyhedral/polyhedra/validation.h
Line | Count | Source |
1 | | /****************************************************************************** |
2 | | * |
3 | | * Project: PROJ |
4 | | * Purpose: Compile-time validation helper for polyhedron seed meshes. |
5 | | * Author: Felix Palmer |
6 | | * |
7 | | ****************************************************************************/ |
8 | | |
9 | | #ifndef POLYHEDRA_VALIDATION_H |
10 | | #define POLYHEDRA_VALIDATION_H |
11 | | |
12 | | #include "../conway.h" |
13 | | |
14 | | namespace polyhedra { |
15 | | |
16 | | template <int NV, int NF, int NFV> |
17 | | constexpr bool |
18 | 0 | all_vertices_on_unit_sphere(const polyhedral::Mesh<NV, NF, NFV> &m) { |
19 | 0 | constexpr double tol = 1e-12; |
20 | 0 | for (int i = 0; i < NV; i++) { |
21 | 0 | const auto &v = m.vertices[i]; |
22 | 0 | const double err = v.x * v.x + v.y * v.y + v.z * v.z - 1.0; |
23 | 0 | if (err < -tol || err > tol) |
24 | 0 | return false; |
25 | 0 | } |
26 | 0 | return true; |
27 | 0 | } Unexecuted instantiation: bool polyhedra::all_vertices_on_unit_sphere<20, 12, 5>(polyhedral::Mesh<20, 12, 5> const&) Unexecuted instantiation: bool polyhedra::all_vertices_on_unit_sphere<12, 20, 3>(polyhedral::Mesh<12, 20, 3> const&) Unexecuted instantiation: bool polyhedra::all_vertices_on_unit_sphere<4, 4, 3>(polyhedral::Mesh<4, 4, 3> const&) |
28 | | |
29 | | template <int NV, int NF, int NFV> |
30 | | constexpr bool |
31 | 0 | face_indices_well_formed(const polyhedral::Mesh<NV, NF, NFV> &m) { |
32 | 0 | for (int f = 0; f < NF; f++) { |
33 | 0 | for (int k = 0; k < NFV; k++) { |
34 | 0 | if (m.faces[f][k] < 0 || m.faces[f][k] >= NV) |
35 | 0 | return false; |
36 | 0 | for (int j = k + 1; j < NFV; j++) { |
37 | 0 | if (m.faces[f][k] == m.faces[f][j]) |
38 | 0 | return false; |
39 | 0 | } |
40 | 0 | } |
41 | 0 | } |
42 | 0 | return true; |
43 | 0 | } Unexecuted instantiation: bool polyhedra::face_indices_well_formed<20, 12, 5>(polyhedral::Mesh<20, 12, 5> const&) Unexecuted instantiation: bool polyhedra::face_indices_well_formed<12, 20, 3>(polyhedral::Mesh<12, 20, 3> const&) Unexecuted instantiation: bool polyhedra::face_indices_well_formed<4, 4, 3>(polyhedral::Mesh<4, 4, 3> const&) |
44 | | |
45 | | // Two topological conditions: |
46 | | // V - E + F = 2 for any closed convex polyhedron, |
47 | | // E = NF * NFV / 2 (each edge shared by exactly two NFV-gon faces). |
48 | | template <int NV, int NF, int NFV> |
49 | 0 | constexpr bool euler_holds(const polyhedral::Mesh<NV, NF, NFV> &) { |
50 | 0 | return (NF * NFV) % 2 == 0 && NV - (NF * NFV) / 2 + NF == 2; |
51 | 0 | } Unexecuted instantiation: bool polyhedra::euler_holds<20, 12, 5>(polyhedral::Mesh<20, 12, 5> const&) Unexecuted instantiation: bool polyhedra::euler_holds<12, 20, 3>(polyhedral::Mesh<12, 20, 3> const&) Unexecuted instantiation: bool polyhedra::euler_holds<4, 4, 3>(polyhedral::Mesh<4, 4, 3> const&) |
52 | | |
53 | | template <auto &M> struct validate_polyhedron { |
54 | | static_assert(M.vertices[0].x == 0.0 && M.vertices[0].y == 0.0 && |
55 | | M.vertices[0].z == 1.0, |
56 | | "V0 must be at (0, 0, 1)"); |
57 | | static_assert(all_vertices_on_unit_sphere(M), |
58 | | "all vertices must lie on the unit sphere"); |
59 | | static_assert(face_indices_well_formed(M), |
60 | | "face vertex indices must be in [0, NV) " |
61 | | "and unique within each face"); |
62 | | static_assert(euler_holds(M), |
63 | | "polyhedron must satisfy Euler's formula V - E + F = 2"); |
64 | | }; |
65 | | |
66 | | } // namespace polyhedra |
67 | | |
68 | | #endif // POLYHEDRA_VALIDATION_H |