TerrainGen coverage


terraingen/
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
80 / 80
100.0%
Branches:
58 / 59
98.3%
Functions:
13 / 13
100.0%

albedo/albedo.cpp
Line Branch Exec Source
1 #include "terraingen/albedo/albedo.h"
2
3 #include "terraingen/util/checks.h"
4 #include "terraingen/util/log.h"
5 #include "terraingen/util/parallel.h"
6
7 #include <algorithm>
8 #include <cmath>
9 #include <limits>
10 #include <stdexcept>
11
12 namespace terraingen {
13
14 1450427 void ValidateAlbedoContext(const AlbedoContext& context) {
15
1/1
✓ Branch 2 taken 1450425 times.
1450427 RequirePositive(context.spacing, "Albedo sample spacing");
16 1450425 }
17
18 namespace {
19
20 /// Visits the cells of one row of `bands`.
21 24780 void VisitRow(std::vector<Raster<float>>& bands, std::size_t row, const AlbedoCellVisitor& visit) {
22 24780 const Raster<float>& first = bands.front();
23
2/2
✓ Branch 1 taken 17103216 times.
✓ Branch 2 taken 24780 times.
17127996 for (std::size_t col = 0; col < first.Width(); ++col) {
24 17103216 AlbedoSample value{};
25
2/2
✓ Branch 1 taken 17909986 times.
✓ Branch 2 taken 17103216 times.
35013202 for (std::size_t band = 0; band < bands.size(); ++band) {
26 17909986 value[band] = bands[band](col, row);
27 }
28 17103216 const Vec2d centre = first.CellCenter(col, row);
29
1/1
✓ Branch 1 taken 17103216 times.
17103216 visit(value, centre.x, centre.y);
30
2/2
✓ Branch 1 taken 17909986 times.
✓ Branch 2 taken 17103216 times.
35013202 for (std::size_t band = 0; band < bands.size(); ++band) {
31 17909986 bands[band](col, row) = value[band];
32 }
33 }
34 24780 }
35
36 } // namespace
37
38 82 void ForEachAlbedoCell(std::vector<Raster<float>>& bands, unsigned threads,
39 const AlbedoCellVisitor& visit) {
40
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 81 times.
82 if (bands.empty()) {
41 1 return;
42 }
43
1/1
✓ Branch 3 taken 81 times.
81 ParallelFor(bands.front().Height(), threads,
44 15353 [&](std::size_t row) { VisitRow(bands, row, visit); });
45 }
46
47 43 void ForEachAlbedoBlock(
48 std::vector<Raster<float>>& bands, unsigned threads, std::size_t blockRows,
49 const std::function<AlbedoCellVisitor(std::size_t rowBegin, std::size_t rowEnd)>& visitorFor) {
50
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 42 times.
43 if (bands.empty()) {
51 1 return;
52 }
53 42 const std::size_t height = bands.front().Height();
54 42 const std::size_t blocks = (height + blockRows - 1) / blockRows;
55
2/2
✓ Branch 1 taken 42 times.
✓ Branch 4 taken 42 times.
42 ParallelFor(blocks, threads, [&](std::size_t block) {
56 325 const std::size_t rowBegin = block * blockRows;
57 325 const std::size_t rowEnd = std::min(height, rowBegin + blockRows);
58
1/1
✓ Branch 1 taken 325 times.
325 const AlbedoCellVisitor visit = visitorFor(rowBegin, rowEnd);
59
2/2
✓ Branch 0 taken 9589 times.
✓ Branch 1 taken 325 times.
9914 for (std::size_t row = rowBegin; row < rowEnd; ++row) {
60
1/1
✓ Branch 1 taken 9589 times.
9589 VisitRow(bands, row, visit);
61 }
62 325 });
63 }
64
65 74 void AlbedoSource::Fill(std::vector<Raster<float>>& bands, const AlbedoContext& context) const {
66
1/1
✓ Branch 2 taken 74 times.
74 ForEachAlbedoCell(bands, context.threads, [&](AlbedoSample& value, double x, double y) {
67 8529267 value = ValueAt(x, y, context);
68 8529267 });
69 74 }
70
71 7 void AlbedoLayer::Apply(std::vector<Raster<float>>& bands, const AlbedoContext& context) const {
72 7 const std::size_t count = bands.size();
73
2/2
✓ Branch 1 taken 7 times.
✓ Branch 4 taken 7 times.
7 ForEachAlbedoCell(bands, context.threads, [&](AlbedoSample& value, double x, double y) {
74 1514274 ApplyAt(value, count, x, y, context);
75 1514274 });
76 7 }
77
78 namespace {
79
80 1724 std::size_t CheckAlbedo(const Albedo& albedo, const AlbedoContext& context) {
81
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 1723 times.
1724 if (!albedo.source) {
82
1/1
✓ Branch 2 taken 1 time.
1 throw std::invalid_argument("An albedo needs a source");
83 }
84
2/2
✓ Branch 5 taken 1699 times.
✓ Branch 6 taken 1722 times.
3421 for (const auto& layer : albedo.layers) {
85
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 1698 times.
1699 if (!layer) {
86
1/1
✓ Branch 2 taken 1 time.
1 throw std::invalid_argument("An albedo layer is null");
87 }
88 }
89 1722 const std::size_t bands = albedo.source->Bands();
90
4/4
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 1696 times.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 25 times.
1722 if (bands != 1 && bands != kMaxAlbedoBands) {
91
1/1
✓ Branch 2 taken 1 time.
1 throw std::invalid_argument("An albedo source must have 1 or 3 bands");
92 }
93 1721 ValidateAlbedoContext(context);
94 1720 return bands;
95 }
96
97 } // namespace
98
99 79 std::vector<Raster<float>> EvaluateAlbedo(const Albedo& albedo, const RasterGrid& grid,
100 AlbedoContext context) {
101
3/4
✓ Branch 0 taken 78 times.
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
✓ Branch 3 taken 78 times.
79 if (grid.width == 0 || grid.height == 0) {
102
1/1
✓ Branch 2 taken 1 time.
1 throw std::invalid_argument("Cannot evaluate an albedo over an empty grid");
103 }
104
1/1
✓ Branch 2 taken 77 times.
78 RequireNonNegative(context.spacing, "Albedo sample spacing");
105 77 context.spacing = std::fmax(context.spacing, grid.Spacing(albedo.surface));
106 77 const std::size_t count = CheckAlbedo(albedo, context);
107 74 std::vector<Raster<float>> bands;
108
2/2
✓ Branch 0 taken 104 times.
✓ Branch 1 taken 74 times.
178 for (std::size_t band = 0; band < count; ++band) {
109
1/1
✓ Branch 1 taken 104 times.
104 Raster<float> raster = grid.MakeRaster(0.0f);
110 104 raster.SetNoData(std::numeric_limits<float>::quiet_NaN());
111
1/1
✓ Branch 2 taken 104 times.
104 bands.push_back(std::move(raster));
112 104 }
113
1/1
✓ Branch 2 taken 74 times.
74 albedo.source->Fill(bands, context);
114
2/2
✓ Branch 1 taken 56 times.
✓ Branch 2 taken 74 times.
130 for (std::size_t n = 0; n < albedo.layers.size(); ++n) {
115 56 const Stopwatch stopwatch;
116
1/1
✓ Branch 3 taken 56 times.
56 albedo.layers[n]->Apply(bands, context);
117
1/1
✓ Branch 2 taken 56 times.
56 LogDebug("albedo", "Applied albedo layer ", n + 1, " in ",
118
2/2
✓ Branch 1 taken 56 times.
✓ Branch 4 taken 56 times.
112 FormatDuration(stopwatch.Milliseconds()));
119 }
120 74 return bands;
121 }
122
123 1647 AlbedoSample EvaluateAlbedoAt(const Albedo& albedo, double x, double y,
124 const AlbedoContext& context) {
125
1/1
✓ Branch 1 taken 1646 times.
1647 const std::size_t count = CheckAlbedo(albedo, context);
126
1/1
✓ Branch 2 taken 1646 times.
1646 AlbedoSample value = albedo.source->ValueAt(x, y, context);
127
2/2
✓ Branch 0 taken 3272 times.
✓ Branch 1 taken 1646 times.
4918 for (std::size_t band = count; band < kMaxAlbedoBands; ++band) {
128 3272 value[band] = 0.0f;
129 }
130
2/2
✓ Branch 5 taken 1642 times.
✓ Branch 6 taken 1646 times.
3288 for (const auto& layer : albedo.layers) {
131
1/1
✓ Branch 2 taken 1642 times.
1642 layer->ApplyAt(value, count, x, y, context);
132 }
133 1646 return value;
134 }
135
136 } // namespace terraingen
137