• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

NREL / SolTrace / 21046664913

15 Jan 2026 09:17PM UTC coverage: 87.999% (+0.2%) from 87.815%
21046664913

Pull #96

github

web-flow
Merge a5971e7da into e78d2bfb0
Pull Request #96: 95 implement embree runner

605 of 797 new or added lines in 17 files covered. (75.91%)

14 existing lines in 7 files now uncovered.

6255 of 7108 relevant lines covered (88.0%)

7221404.67 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.7
/coretrace/simulation_data/surface.cpp
1

2
#include "surface.hpp"
3
#include "simdata_io.hpp"
4

5
#include <vector>
6

7
#include <utilities.hpp>
8

9
namespace SolTrace::Data
10
{
11

12
    surface_ptr make_surface_from_type(SurfaceType type, const std::vector<double> &args)
21,321✔
13
    {
14
        surface_ptr retval = nullptr;
21,321✔
15
        unsigned nargs = args.size();
21,321✔
16

17
        switch (type)
21,321✔
18
        {
19
        case SurfaceType::CONE:
3✔
20
            retval = nargs < 1 ? nullptr : make_surface<Cone>(args[0]);
3✔
21
            break;
3✔
22
        case SurfaceType::CYLINDER:
7✔
23
            retval = nargs < 1 ? nullptr : make_surface<Cylinder>(1.0 / args[0]);
7✔
24
            break;
7✔
25
        case SurfaceType::FLAT:
7✔
26
            retval = make_surface<Flat>();
7✔
27
            break;
7✔
28
        case SurfaceType::PARABOLA:
21,221✔
29
        {
30
            if (nargs < 2)
21,221✔
31
                retval = nullptr;
2✔
32
            else
33
            {
34
                double cx = args[0];
21,219✔
35
                double cy = args[1];
21,219✔
36
                double fx = 1.0 / (2.0 * cx);
21,219✔
37
                double fy = 1.0 / (2.0 * cy);
21,219✔
38
                retval = make_surface<Parabola>(fx, fy);
21,219✔
39
            }
40
            break;
21,221✔
41
        }
42
        case SurfaceType::SPHERE:
79✔
43
            retval = nargs < 1 ? nullptr : make_surface<Sphere>(args[0]);
79✔
44
            break;
79✔
45
        case SurfaceType::HYPER:
4✔
46
        case SurfaceType::GENERAL_SPENCER_MURTY:
47
        case SurfaceType::TORUS:
48
        default:
49
            retval = nullptr; // Not implemented yet
4✔
50
            break;
4✔
51
        }
52

53
        return retval;
21,321✔
NEW
54
    }
×
55

56
    surface_ptr make_surface_from_json(const nlohmann::ordered_json &jnode)
2,437✔
57
    {
58
        if (!jnode.contains("surface_type"))
2,437✔
59
            throw std::invalid_argument("Missing surface_type");
1✔
60
        std::string type_str = jnode.at("surface_type");
2,436✔
61
        SurfaceType surface_type = get_enum_from_string(type_str, SurfaceTypeMap, SurfaceType::SURFACE_UNKNOWN);
2,436✔
62
        if (surface_type == SurfaceType::SURFACE_UNKNOWN)
2,436✔
63
            throw std::invalid_argument("Unknown surface");
1✔
64
        switch (surface_type)
2,435✔
65
        {
66
        case SurfaceType::CONE:
2✔
67
            return make_surface<Cone>(jnode);
2✔
68
        case SurfaceType::CYLINDER:
3✔
69
            return make_surface<Cylinder>(jnode);
3✔
70
        case SurfaceType::FLAT:
6✔
71
            return make_surface<Flat>(jnode);
6✔
72
        case SurfaceType::PARABOLA:
2,372✔
73
            return make_surface<Parabola>(jnode);
2,372✔
74
        case SurfaceType::SPHERE:
52✔
75
            return make_surface<Sphere>(jnode);
52✔
76
        default:
×
77
            throw std::invalid_argument("Unsupported surface_type: " + type_str);
×
78
        }
79
    }
2,436✔
80

81
    Cone::Cone(const nlohmann::ordered_json &jnode)
2✔
82
        : Surface(SurfaceType::CONE)
2✔
83
    {
84
        this->half_angle = jnode.at("half_angle");
2✔
85
    }
2✔
86

87
    void Cone::bounding_box(const double x_minmax[2],
3✔
88
                            const double y_minmax[2],
89
                            double &z_min,
90
                            double &z_max) const
91
    {
92
        double theta = this->half_angle * D2R;
3✔
93
        double x_abs = abs_max(x_minmax, 2);
3✔
94
        double y_abs = abs_max(y_minmax, 2);
3✔
95
        z_min = 0.0;
3✔
96
        z_max = sqrt(x_abs * x_abs + y_abs * y_abs) / tan(theta);
3✔
97
        return;
3✔
98
    }
99

100
    surface_ptr Cone::make_copy() const
1✔
101
    {
102
        return make_surface<Cone>(*this);
1✔
103
    }
104

NEW
105
    void Cone::write_json(nlohmann::ordered_json &jnode) const
×
106
    {
NEW
107
        SurfaceType type = SurfaceType::CONE;
×
NEW
108
        jnode["surface_type"] = SurfaceTypeMap.at(type);
×
NEW
109
        jnode["half_angle"] = this->half_angle;
×
NEW
110
    }
×
111

112
    Cylinder::Cylinder(const nlohmann::ordered_json &jnode)
3✔
113
        : Surface(SurfaceType::CYLINDER)
3✔
114
    {
115
        this->radius = jnode.at("radius");
3✔
116
    }
3✔
117

118
    void Cylinder::bounding_box(const double x_minmax[2],
3✔
119
                                const double y_minmax[2],
120
                                double &z_min,
121
                                double &z_max) const
122
    {
123
        double r = this->radius;
3✔
124
        // Debug check only. This should be caught upstream before
125
        // any bounding box calculations are done by a SimulationRunner.
126
        // See, e.g., native_runner/cylinder_calculator.cpp.
127
        assert(is_approx(x_minmax[0], -r, 1e-6));
3✔
128
        assert(is_approx(x_minmax[1], r, 1e-6));
3✔
129
        z_min = 0.0;
3✔
130
        z_max = 2.0 * r;
3✔
131
        return;
3✔
132
    }
133

134
    surface_ptr Cylinder::make_copy() const
17✔
135
    {
136
        return make_surface<Cylinder>(*this);
17✔
137
    }
138

139
    void Cylinder::write_json(nlohmann::ordered_json &jnode) const
1✔
140
    {
141
        SurfaceType type = SurfaceType::CYLINDER;
1✔
142
        jnode["surface_type"] = SurfaceTypeMap.at(type);
1✔
143
        jnode["radius"] = this->radius;
1✔
144
    }
1✔
145

146
    void Flat::bounding_box(const double x_minmax[2],
3✔
147
                            const double y_minmax[2],
148
                            double &z_min,
149
                            double &z_max) const
150
    {
151
        z_min = -1e-4;
3✔
152
        z_max = 1e-4;
3✔
153
        return;
3✔
154
    }
155

156
    surface_ptr Flat::make_copy() const
79✔
157
    {
158
        return make_surface<Flat>(*this);
79✔
159
    }
160

161
    void Flat::write_json(nlohmann::ordered_json &jnode) const
6✔
162
    {
163
        SurfaceType type = SurfaceType::FLAT;
6✔
164
        jnode["surface_type"] = SurfaceTypeMap.at(type);
6✔
165
    }
6✔
166

167
    Parabola::Parabola(const nlohmann::ordered_json &jnode)
2,372✔
168
        : Surface(SurfaceType::PARABOLA)
2,372✔
169
    {
170
        this->focal_length_x = jnode.at("focal_length_x");
2,372✔
171
        this->focal_length_y = jnode.at("focal_length_y");
2,372✔
172
    }
2,372✔
173

174
    void Parabola::bounding_box(const double x_minmax[2],
4✔
175
                                const double y_minmax[2],
176
                                double &z_min,
177
                                double &z_max) const
178
    {
179
        double cx = 0.5 / this->focal_length_x;
4✔
180
        double cy = 0.5 / this->focal_length_y;
4✔
181
        double x_max = abs_max(x_minmax, 2);
4✔
182
        double y_max = abs_max(y_minmax, 2);
4✔
183
        z_max = 0.5 * (cx * x_max * x_max + cy * y_max * y_max);
4✔
184

185
        if (x_minmax[0] <= 0.0 && 0.0 <= x_minmax[1] &&
4✔
186
            y_minmax[0] <= 0.0 && 0.0 <= y_minmax[1])
3✔
187
        {
188
            z_min = 0.0;
3✔
189
        }
190
        else
191
        {
192
            double x_min = abs_min(x_minmax, 2);
1✔
193
            double y_min = abs_min(y_minmax, 2);
1✔
194
            z_min = 0.5 * (cx * x_min * x_min + cy * y_min * y_min);
1✔
195
        }
196

197
        return;
4✔
198
    }
199

200
    surface_ptr Parabola::make_copy() const
18,897✔
201
    {
202
        return make_surface<Parabola>(*this);
18,897✔
203
    }
204

205
    void Parabola::write_json(nlohmann::ordered_json &jnode) const
2,370✔
206
    {
207
        SurfaceType type = SurfaceType::PARABOLA;
2,370✔
208
        jnode["surface_type"] = SurfaceTypeMap.at(type);
2,370✔
209
        jnode["focal_length_x"] = this->focal_length_x;
2,370✔
210
        jnode["focal_length_y"] = this->focal_length_y;
2,370✔
211
    }
2,370✔
212

213
    Sphere::Sphere(const nlohmann::ordered_json &jnode)
52✔
214
        : Surface(SurfaceType::SPHERE)
52✔
215
    {
216
        this->vertex_curv = jnode.at("vertex_curv");
52✔
217
    }
52✔
218

219
    void Sphere::bounding_box(const double x_minmax[2],
4✔
220
                              const double y_minmax[2],
221
                              double &z_min,
222
                              double &z_max) const
223
    {
224
        z_min = 0.0;
4✔
225
        double R = 1.0 / this->vertex_curv;
4✔
226
        double x_max = abs_max(x_minmax, 2);
4✔
227
        double y_max = abs_max(y_minmax, 2);
4✔
228
        double rsq = x_max * x_max + y_max * y_max;
4✔
229
        z_max = R > sqrt(rsq) ? R - sqrt(R * R - rsq) : R;
4✔
230
        return;
4✔
231
    }
232

233
    surface_ptr Sphere::make_copy() const
78✔
234
    {
235
        return make_surface<Sphere>(*this);
78✔
236
    }
237

238
    void Sphere::write_json(nlohmann::ordered_json &jnode) const
75✔
239
    {
240
        SurfaceType type = SurfaceType::SPHERE;
75✔
241
        jnode["surface_type"] = SurfaceTypeMap.at(type);
75✔
242
        jnode["vertex_curv"] = this->vertex_curv;
75✔
243
    }
75✔
244

245
    double Cone::z(double x, double y) const
2✔
246
    {
247
        return sqrt(x * x + y * y) / tan(half_angle);
2✔
248
    }
249

250
    double Cylinder::z(double x, double) const
2✔
251
    {
252
        // TODO: Fix ? This is really only the top half of the cylinder.
253
        //       Cylinder breaks the model since it is a multi-valued function: each
254
        //       x value produces two z values. Returning only the positive root.
255
        return radius + sqrt(x * x + radius * radius);
2✔
256
    }
257

258
    double Parabola::z(double x, double y) const
2✔
259
    {
260
        // z(x,y) = (cx * x^2 + cy * y^2) / 2
261
        return x * x / focal_length_x + y * y / focal_length_y;
2✔
262
    }
263

264
    double Sphere::z(double x, double y) const
2✔
265
    {
266
        return vertex_curv * (x * x + y * y) /
2✔
267
               (1 + sqrt(1 - vertex_curv * vertex_curv * (x * x + y * y)));
2✔
268
    }
269

270
} // namespace SolTrace::Data
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc