Coverage Report

Created: 2026-09-03 06:43

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
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