/src/PROJ/src/projections/polyhedral/conway.h
Line | Count | Source |
1 | | /****************************************************************************** |
2 | | * |
3 | | * Project: PROJ |
4 | | * Purpose: Conway meta polyhedron operation |
5 | | * Author: Felix Palmer |
6 | | * |
7 | | ****************************************************************************/ |
8 | | |
9 | | #ifndef POLYHEDRAL_CONWAY_H |
10 | | #define POLYHEDRAL_CONWAY_H |
11 | | |
12 | | #include "vec3.h" |
13 | | |
14 | | namespace polyhedral { |
15 | | |
16 | | // Mesh struct, both for representing polyhedra & flat nets |
17 | | template <int NumVertices, int NumFaces, int NumFaceVertices> struct Mesh { |
18 | | // List of vertices as 3D vectors |
19 | | Vec3 vertices[NumVertices]; |
20 | | // Faces, indexing above vertices |
21 | | int faces[NumFaces][NumFaceVertices] = {}; |
22 | | }; |
23 | | |
24 | | // ConwayMode: |
25 | | // - Sphere: project centroid + fan vertices onto unit sphere (for polyhedra) |
26 | | // - Plane: scale centroid to the arithmetic mean (for nets) |
27 | | enum class ConwayMode { Sphere, Plane }; |
28 | | |
29 | | // Conway meta operation (m = kda). Optional dual operation applied first (md = |
30 | | // kdad) Geometrically this subdivides each face with n vertices into 2n |
31 | | // triangles in a fan Emitted vertex order: [center, midpoint, vertex] |
32 | | template <ConwayMode Mode, int NumVertices, int NumFaces, int NumFaceVertices> |
33 | | inline void conway_meta(const Vec3 (&vertices)[NumVertices], |
34 | | const int (&faces)[NumFaces][NumFaceVertices], |
35 | | Vec3 (&out)[2 * NumFaceVertices * NumFaces][3], |
36 | 766 | bool dual = false) { |
37 | 766 | constexpr int FanSize = 2 * NumFaceVertices; |
38 | 16.0k | for (int i = 0; i < NumFaces; i++) { |
39 | 15.3k | Vec3 fan[FanSize]; |
40 | 15.3k | Vec3 center{0.0, 0.0, 0.0}; |
41 | 61.2k | for (int k = 0; k < NumFaceVertices; k++) { |
42 | 45.9k | const Vec3 va = vertices[faces[i][k]]; |
43 | 45.9k | const Vec3 vb = vertices[faces[i][(k + 1) % NumFaceVertices]]; |
44 | 45.9k | fan[2 * k] = va; |
45 | 45.9k | fan[2 * k + 1] = vec3_lerp(va, vb, 0.5); |
46 | 45.9k | center = vec3_add(center, va); |
47 | 45.9k | } |
48 | | |
49 | 15.3k | if constexpr (Mode == ConwayMode::Sphere) { |
50 | 53.6k | for (int k = 0; k < FanSize; k++) |
51 | 45.9k | fan[k] = vec3_normalize(fan[k]); |
52 | 7.66k | center = vec3_normalize(center); |
53 | 7.66k | } else { |
54 | 7.66k | center = vec3_scale(center, 1.0 / NumFaceVertices); |
55 | 7.66k | } |
56 | | |
57 | 107k | for (int k = 0; k < FanSize; k++) { |
58 | 91.9k | Vec3 *tri = out[FanSize * i + k]; |
59 | 91.9k | const bool even = (k % 2) == 0; |
60 | 91.9k | const Vec3 &vertex = fan[even ? k : (k + 1) % FanSize]; |
61 | 91.9k | const Vec3 &midpoint = fan[even ? (k + 1) % FanSize : k]; |
62 | | // Dual operation just swaps vertices with face centers |
63 | 91.9k | tri[0] = dual ? vertex : center; |
64 | 91.9k | tri[1] = midpoint; |
65 | 91.9k | tri[2] = dual ? center : vertex; |
66 | 91.9k | } |
67 | 15.3k | } |
68 | 766 | } Unexecuted instantiation: void polyhedral::conway_meta<(polyhedral::ConwayMode)0, 20, 12, 5>(Vec3 const (&) [20], int const (&) [12][5], Vec3 (&) [((2)*(5))*(12)][3], bool) Unexecuted instantiation: void polyhedral::conway_meta<(polyhedral::ConwayMode)1, 38, 12, 5>(Vec3 const (&) [38], int const (&) [12][5], Vec3 (&) [((2)*(5))*(12)][3], bool) void polyhedral::conway_meta<(polyhedral::ConwayMode)0, 12, 20, 3>(Vec3 const (&) [12], int const (&) [20][3], Vec3 (&) [((2)*(3))*(20)][3], bool) Line | Count | Source | 36 | 383 | bool dual = false) { | 37 | 383 | constexpr int FanSize = 2 * NumFaceVertices; | 38 | 8.04k | for (int i = 0; i < NumFaces; i++) { | 39 | 7.66k | Vec3 fan[FanSize]; | 40 | 7.66k | Vec3 center{0.0, 0.0, 0.0}; | 41 | 30.6k | for (int k = 0; k < NumFaceVertices; k++) { | 42 | 22.9k | const Vec3 va = vertices[faces[i][k]]; | 43 | 22.9k | const Vec3 vb = vertices[faces[i][(k + 1) % NumFaceVertices]]; | 44 | 22.9k | fan[2 * k] = va; | 45 | 22.9k | fan[2 * k + 1] = vec3_lerp(va, vb, 0.5); | 46 | 22.9k | center = vec3_add(center, va); | 47 | 22.9k | } | 48 | | | 49 | 7.66k | if constexpr (Mode == ConwayMode::Sphere) { | 50 | 53.6k | for (int k = 0; k < FanSize; k++) | 51 | 45.9k | fan[k] = vec3_normalize(fan[k]); | 52 | 7.66k | center = vec3_normalize(center); | 53 | | } else { | 54 | | center = vec3_scale(center, 1.0 / NumFaceVertices); | 55 | | } | 56 | | | 57 | 53.6k | for (int k = 0; k < FanSize; k++) { | 58 | 45.9k | Vec3 *tri = out[FanSize * i + k]; | 59 | 45.9k | const bool even = (k % 2) == 0; | 60 | 45.9k | const Vec3 &vertex = fan[even ? k : (k + 1) % FanSize]; | 61 | 45.9k | const Vec3 &midpoint = fan[even ? (k + 1) % FanSize : k]; | 62 | | // Dual operation just swaps vertices with face centers | 63 | 45.9k | tri[0] = dual ? vertex : center; | 64 | 45.9k | tri[1] = midpoint; | 65 | 45.9k | tri[2] = dual ? center : vertex; | 66 | 45.9k | } | 67 | 7.66k | } | 68 | 383 | } |
void polyhedral::conway_meta<(polyhedral::ConwayMode)1, 22, 20, 3>(Vec3 const (&) [22], int const (&) [20][3], Vec3 (&) [((2)*(3))*(20)][3], bool) Line | Count | Source | 36 | 383 | bool dual = false) { | 37 | 383 | constexpr int FanSize = 2 * NumFaceVertices; | 38 | 8.04k | for (int i = 0; i < NumFaces; i++) { | 39 | 7.66k | Vec3 fan[FanSize]; | 40 | 7.66k | Vec3 center{0.0, 0.0, 0.0}; | 41 | 30.6k | for (int k = 0; k < NumFaceVertices; k++) { | 42 | 22.9k | const Vec3 va = vertices[faces[i][k]]; | 43 | 22.9k | const Vec3 vb = vertices[faces[i][(k + 1) % NumFaceVertices]]; | 44 | 22.9k | fan[2 * k] = va; | 45 | 22.9k | fan[2 * k + 1] = vec3_lerp(va, vb, 0.5); | 46 | 22.9k | center = vec3_add(center, va); | 47 | 22.9k | } | 48 | | | 49 | | if constexpr (Mode == ConwayMode::Sphere) { | 50 | | for (int k = 0; k < FanSize; k++) | 51 | | fan[k] = vec3_normalize(fan[k]); | 52 | | center = vec3_normalize(center); | 53 | 7.66k | } else { | 54 | 7.66k | center = vec3_scale(center, 1.0 / NumFaceVertices); | 55 | 7.66k | } | 56 | | | 57 | 53.6k | for (int k = 0; k < FanSize; k++) { | 58 | 45.9k | Vec3 *tri = out[FanSize * i + k]; | 59 | 45.9k | const bool even = (k % 2) == 0; | 60 | 45.9k | const Vec3 &vertex = fan[even ? k : (k + 1) % FanSize]; | 61 | 45.9k | const Vec3 &midpoint = fan[even ? (k + 1) % FanSize : k]; | 62 | | // Dual operation just swaps vertices with face centers | 63 | 45.9k | tri[0] = dual ? vertex : center; | 64 | 45.9k | tri[1] = midpoint; | 65 | 45.9k | tri[2] = dual ? center : vertex; | 66 | 45.9k | } | 67 | 7.66k | } | 68 | 383 | } |
Unexecuted instantiation: void polyhedral::conway_meta<(polyhedral::ConwayMode)0, 4, 4, 3>(Vec3 const (&) [4], int const (&) [4][3], Vec3 (&) [((2)*(3))*(4)][3], bool) Unexecuted instantiation: void polyhedral::conway_meta<(polyhedral::ConwayMode)1, 6, 4, 3>(Vec3 const (&) [6], int const (&) [4][3], Vec3 (&) [((2)*(3))*(4)][3], bool) |
69 | | |
70 | | } // namespace polyhedral |
71 | | |
72 | | #endif // POLYHEDRAL_CONWAY_H |