Coverage Report

Created: 2026-11-12 07:32

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
934
                        bool dual = false) {
37
934
    constexpr int FanSize = 2 * NumFaceVertices;
38
18.4k
    for (int i = 0; i < NumFaces; i++) {
39
17.4k
        Vec3 fan[FanSize];
40
17.4k
        Vec3 center{0.0, 0.0, 0.0};
41
69.9k
        for (int k = 0; k < NumFaceVertices; k++) {
42
52.4k
            const Vec3 va = vertices[faces[i][k]];
43
52.4k
            const Vec3 vb = vertices[faces[i][(k + 1) % NumFaceVertices]];
44
52.4k
            fan[2 * k] = va;
45
52.4k
            fan[2 * k + 1] = vec3_lerp(va, vb, 0.5);
46
52.4k
            center = vec3_add(center, va);
47
52.4k
        }
48
49
17.4k
        if constexpr (Mode == ConwayMode::Sphere) {
50
61.2k
            for (int k = 0; k < FanSize; k++)
51
52.4k
                fan[k] = vec3_normalize(fan[k]);
52
8.74k
            center = vec3_normalize(center);
53
8.74k
        } else {
54
8.74k
            center = vec3_scale(center, 1.0 / NumFaceVertices);
55
8.74k
        }
56
57
122k
        for (int k = 0; k < FanSize; k++) {
58
104k
            Vec3 *tri = out[FanSize * i + k];
59
104k
            const bool even = (k % 2) == 0;
60
104k
            const Vec3 &vertex = fan[even ? k : (k + 1) % FanSize];
61
104k
            const Vec3 &midpoint = fan[even ? (k + 1) % FanSize : k];
62
            // Dual operation just swaps vertices with face centers
63
104k
            tri[0] = dual ? vertex : center;
64
104k
            tri[1] = midpoint;
65
104k
            tri[2] = dual ? center : vertex;
66
104k
        }
67
17.4k
    }
68
934
}
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
430
                        bool dual = false) {
37
430
    constexpr int FanSize = 2 * NumFaceVertices;
38
9.03k
    for (int i = 0; i < NumFaces; i++) {
39
8.60k
        Vec3 fan[FanSize];
40
8.60k
        Vec3 center{0.0, 0.0, 0.0};
41
34.4k
        for (int k = 0; k < NumFaceVertices; k++) {
42
25.8k
            const Vec3 va = vertices[faces[i][k]];
43
25.8k
            const Vec3 vb = vertices[faces[i][(k + 1) % NumFaceVertices]];
44
25.8k
            fan[2 * k] = va;
45
25.8k
            fan[2 * k + 1] = vec3_lerp(va, vb, 0.5);
46
25.8k
            center = vec3_add(center, va);
47
25.8k
        }
48
49
8.60k
        if constexpr (Mode == ConwayMode::Sphere) {
50
60.2k
            for (int k = 0; k < FanSize; k++)
51
51.6k
                fan[k] = vec3_normalize(fan[k]);
52
8.60k
            center = vec3_normalize(center);
53
        } else {
54
            center = vec3_scale(center, 1.0 / NumFaceVertices);
55
        }
56
57
60.2k
        for (int k = 0; k < FanSize; k++) {
58
51.6k
            Vec3 *tri = out[FanSize * i + k];
59
51.6k
            const bool even = (k % 2) == 0;
60
51.6k
            const Vec3 &vertex = fan[even ? k : (k + 1) % FanSize];
61
51.6k
            const Vec3 &midpoint = fan[even ? (k + 1) % FanSize : k];
62
            // Dual operation just swaps vertices with face centers
63
51.6k
            tri[0] = dual ? vertex : center;
64
51.6k
            tri[1] = midpoint;
65
51.6k
            tri[2] = dual ? center : vertex;
66
51.6k
        }
67
8.60k
    }
68
430
}
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
430
                        bool dual = false) {
37
430
    constexpr int FanSize = 2 * NumFaceVertices;
38
9.03k
    for (int i = 0; i < NumFaces; i++) {
39
8.60k
        Vec3 fan[FanSize];
40
8.60k
        Vec3 center{0.0, 0.0, 0.0};
41
34.4k
        for (int k = 0; k < NumFaceVertices; k++) {
42
25.8k
            const Vec3 va = vertices[faces[i][k]];
43
25.8k
            const Vec3 vb = vertices[faces[i][(k + 1) % NumFaceVertices]];
44
25.8k
            fan[2 * k] = va;
45
25.8k
            fan[2 * k + 1] = vec3_lerp(va, vb, 0.5);
46
25.8k
            center = vec3_add(center, va);
47
25.8k
        }
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
8.60k
        } else {
54
8.60k
            center = vec3_scale(center, 1.0 / NumFaceVertices);
55
8.60k
        }
56
57
60.2k
        for (int k = 0; k < FanSize; k++) {
58
51.6k
            Vec3 *tri = out[FanSize * i + k];
59
51.6k
            const bool even = (k % 2) == 0;
60
51.6k
            const Vec3 &vertex = fan[even ? k : (k + 1) % FanSize];
61
51.6k
            const Vec3 &midpoint = fan[even ? (k + 1) % FanSize : k];
62
            // Dual operation just swaps vertices with face centers
63
51.6k
            tri[0] = dual ? vertex : center;
64
51.6k
            tri[1] = midpoint;
65
51.6k
            tri[2] = dual ? center : vertex;
66
51.6k
        }
67
8.60k
    }
68
430
}
void polyhedral::conway_meta<(polyhedral::ConwayMode)0, 4, 4, 3>(Vec3 const (&) [4], int const (&) [4][3], Vec3 (&) [((2)*(3))*(4)][3], bool)
Line
Count
Source
36
37
                        bool dual = false) {
37
37
    constexpr int FanSize = 2 * NumFaceVertices;
38
185
    for (int i = 0; i < NumFaces; i++) {
39
148
        Vec3 fan[FanSize];
40
148
        Vec3 center{0.0, 0.0, 0.0};
41
592
        for (int k = 0; k < NumFaceVertices; k++) {
42
444
            const Vec3 va = vertices[faces[i][k]];
43
444
            const Vec3 vb = vertices[faces[i][(k + 1) % NumFaceVertices]];
44
444
            fan[2 * k] = va;
45
444
            fan[2 * k + 1] = vec3_lerp(va, vb, 0.5);
46
444
            center = vec3_add(center, va);
47
444
        }
48
49
148
        if constexpr (Mode == ConwayMode::Sphere) {
50
1.03k
            for (int k = 0; k < FanSize; k++)
51
888
                fan[k] = vec3_normalize(fan[k]);
52
148
            center = vec3_normalize(center);
53
        } else {
54
            center = vec3_scale(center, 1.0 / NumFaceVertices);
55
        }
56
57
1.03k
        for (int k = 0; k < FanSize; k++) {
58
888
            Vec3 *tri = out[FanSize * i + k];
59
888
            const bool even = (k % 2) == 0;
60
888
            const Vec3 &vertex = fan[even ? k : (k + 1) % FanSize];
61
888
            const Vec3 &midpoint = fan[even ? (k + 1) % FanSize : k];
62
            // Dual operation just swaps vertices with face centers
63
888
            tri[0] = dual ? vertex : center;
64
888
            tri[1] = midpoint;
65
888
            tri[2] = dual ? center : vertex;
66
888
        }
67
148
    }
68
37
}
void polyhedral::conway_meta<(polyhedral::ConwayMode)1, 6, 4, 3>(Vec3 const (&) [6], int const (&) [4][3], Vec3 (&) [((2)*(3))*(4)][3], bool)
Line
Count
Source
36
37
                        bool dual = false) {
37
37
    constexpr int FanSize = 2 * NumFaceVertices;
38
185
    for (int i = 0; i < NumFaces; i++) {
39
148
        Vec3 fan[FanSize];
40
148
        Vec3 center{0.0, 0.0, 0.0};
41
592
        for (int k = 0; k < NumFaceVertices; k++) {
42
444
            const Vec3 va = vertices[faces[i][k]];
43
444
            const Vec3 vb = vertices[faces[i][(k + 1) % NumFaceVertices]];
44
444
            fan[2 * k] = va;
45
444
            fan[2 * k + 1] = vec3_lerp(va, vb, 0.5);
46
444
            center = vec3_add(center, va);
47
444
        }
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
148
        } else {
54
148
            center = vec3_scale(center, 1.0 / NumFaceVertices);
55
148
        }
56
57
1.03k
        for (int k = 0; k < FanSize; k++) {
58
888
            Vec3 *tri = out[FanSize * i + k];
59
888
            const bool even = (k % 2) == 0;
60
888
            const Vec3 &vertex = fan[even ? k : (k + 1) % FanSize];
61
888
            const Vec3 &midpoint = fan[even ? (k + 1) % FanSize : k];
62
            // Dual operation just swaps vertices with face centers
63
888
            tri[0] = dual ? vertex : center;
64
888
            tri[1] = midpoint;
65
888
            tri[2] = dual ? center : vertex;
66
888
        }
67
148
    }
68
37
}
69
70
} // namespace polyhedral
71
72
#endif // POLYHEDRAL_CONWAY_H