Coverage Report

Created: 2026-09-28 07:23

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
922
                        bool dual = false) {
37
922
    constexpr int FanSize = 2 * NumFaceVertices;
38
19.3k
    for (int i = 0; i < NumFaces; i++) {
39
18.4k
        Vec3 fan[FanSize];
40
18.4k
        Vec3 center{0.0, 0.0, 0.0};
41
73.7k
        for (int k = 0; k < NumFaceVertices; k++) {
42
55.3k
            const Vec3 va = vertices[faces[i][k]];
43
55.3k
            const Vec3 vb = vertices[faces[i][(k + 1) % NumFaceVertices]];
44
55.3k
            fan[2 * k] = va;
45
55.3k
            fan[2 * k + 1] = vec3_lerp(va, vb, 0.5);
46
55.3k
            center = vec3_add(center, va);
47
55.3k
        }
48
49
18.4k
        if constexpr (Mode == ConwayMode::Sphere) {
50
64.5k
            for (int k = 0; k < FanSize; k++)
51
55.3k
                fan[k] = vec3_normalize(fan[k]);
52
9.22k
            center = vec3_normalize(center);
53
9.22k
        } else {
54
9.22k
            center = vec3_scale(center, 1.0 / NumFaceVertices);
55
9.22k
        }
56
57
129k
        for (int k = 0; k < FanSize; k++) {
58
110k
            Vec3 *tri = out[FanSize * i + k];
59
110k
            const bool even = (k % 2) == 0;
60
110k
            const Vec3 &vertex = fan[even ? k : (k + 1) % FanSize];
61
110k
            const Vec3 &midpoint = fan[even ? (k + 1) % FanSize : k];
62
            // Dual operation just swaps vertices with face centers
63
110k
            tri[0] = dual ? vertex : center;
64
110k
            tri[1] = midpoint;
65
110k
            tri[2] = dual ? center : vertex;
66
110k
        }
67
18.4k
    }
68
922
}
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
461
                        bool dual = false) {
37
461
    constexpr int FanSize = 2 * NumFaceVertices;
38
9.68k
    for (int i = 0; i < NumFaces; i++) {
39
9.22k
        Vec3 fan[FanSize];
40
9.22k
        Vec3 center{0.0, 0.0, 0.0};
41
36.8k
        for (int k = 0; k < NumFaceVertices; k++) {
42
27.6k
            const Vec3 va = vertices[faces[i][k]];
43
27.6k
            const Vec3 vb = vertices[faces[i][(k + 1) % NumFaceVertices]];
44
27.6k
            fan[2 * k] = va;
45
27.6k
            fan[2 * k + 1] = vec3_lerp(va, vb, 0.5);
46
27.6k
            center = vec3_add(center, va);
47
27.6k
        }
48
49
9.22k
        if constexpr (Mode == ConwayMode::Sphere) {
50
64.5k
            for (int k = 0; k < FanSize; k++)
51
55.3k
                fan[k] = vec3_normalize(fan[k]);
52
9.22k
            center = vec3_normalize(center);
53
        } else {
54
            center = vec3_scale(center, 1.0 / NumFaceVertices);
55
        }
56
57
64.5k
        for (int k = 0; k < FanSize; k++) {
58
55.3k
            Vec3 *tri = out[FanSize * i + k];
59
55.3k
            const bool even = (k % 2) == 0;
60
55.3k
            const Vec3 &vertex = fan[even ? k : (k + 1) % FanSize];
61
55.3k
            const Vec3 &midpoint = fan[even ? (k + 1) % FanSize : k];
62
            // Dual operation just swaps vertices with face centers
63
55.3k
            tri[0] = dual ? vertex : center;
64
55.3k
            tri[1] = midpoint;
65
55.3k
            tri[2] = dual ? center : vertex;
66
55.3k
        }
67
9.22k
    }
68
461
}
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
461
                        bool dual = false) {
37
461
    constexpr int FanSize = 2 * NumFaceVertices;
38
9.68k
    for (int i = 0; i < NumFaces; i++) {
39
9.22k
        Vec3 fan[FanSize];
40
9.22k
        Vec3 center{0.0, 0.0, 0.0};
41
36.8k
        for (int k = 0; k < NumFaceVertices; k++) {
42
27.6k
            const Vec3 va = vertices[faces[i][k]];
43
27.6k
            const Vec3 vb = vertices[faces[i][(k + 1) % NumFaceVertices]];
44
27.6k
            fan[2 * k] = va;
45
27.6k
            fan[2 * k + 1] = vec3_lerp(va, vb, 0.5);
46
27.6k
            center = vec3_add(center, va);
47
27.6k
        }
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
9.22k
        } else {
54
9.22k
            center = vec3_scale(center, 1.0 / NumFaceVertices);
55
9.22k
        }
56
57
64.5k
        for (int k = 0; k < FanSize; k++) {
58
55.3k
            Vec3 *tri = out[FanSize * i + k];
59
55.3k
            const bool even = (k % 2) == 0;
60
55.3k
            const Vec3 &vertex = fan[even ? k : (k + 1) % FanSize];
61
55.3k
            const Vec3 &midpoint = fan[even ? (k + 1) % FanSize : k];
62
            // Dual operation just swaps vertices with face centers
63
55.3k
            tri[0] = dual ? vertex : center;
64
55.3k
            tri[1] = midpoint;
65
55.3k
            tri[2] = dual ? center : vertex;
66
55.3k
        }
67
9.22k
    }
68
461
}
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