TerrainGen coverage


terraingen/
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
234 / 235
99.6%
Branches:
150 / 152
98.7%
Functions:
27 / 27
100.0%

layers/boulders/abundance.cpp
Line Branch Exec Source
1 #include "terraingen/layers/boulders/boulder_layer.h"
2
3 #include "terraingen/layers/exposure.h"
4 #include "terraingen/layers/fade.h"
5 #include "terraingen/noise/worley.h"
6 #include "terraingen/random/philox.h"
7 #include "terraingen/random/samplers.h"
8 #include "terraingen/random/stream.h"
9 #include "terraingen/util/checks.h"
10 #include "terraingen/util/parallel.h"
11
12 #include <algorithm>
13 #include <cmath>
14 #include <cstdint>
15 #include <numbers>
16
17 namespace terraingen {
18
19 namespace {
20
21 constexpr std::uint32_t kBoulderPatches = 0x50415443u;
22 constexpr std::uint32_t kBoulderClusters = 0x434C5553u;
23 constexpr std::uint32_t kThomasCentres2 = 0x54484D32u;
24 constexpr std::uint32_t kThomasCentres3 = 0x54484D33u;
25 constexpr std::uint32_t kBedrockMeans = 0x4245444Du;
26
27 /// Golombek-Rapp boulders per m^2 per metre of diameter at `diameter` for coverage `k`.
28 5858606 double GolombekRappDensity(double diameter, double k, double qa, double qb) {
29 5858606 const double q = qa + qb / k;
30 5858606 return k * q * std::exp(-q * diameter) / (std::numbers::pi * diameter * diameter / 4.0);
31 }
32
33 /// How far, in radii from its centre, a crater's blocks reach.
34 1219494 double EjectaReach(const BoulderEjecta& ejecta, double diameter) {
35
5/6
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 1219490 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 4 times.
✓ Branch 6 taken 1219490 times.
✓ Branch 7 taken 4 times.
1219494 if (!(ejecta.gravity && ejecta.regolithThickness)) {
36 1219490 return ejecta.reach;
37 }
38 4 const double radius = 0.5 * diameter;
39 const double thrown =
40 4 BoulderThrowDistance(diameter, *ejecta.regolithThickness, *ejecta.gravity) / radius;
41 4 return std::fmin(ejecta.reach, std::fmax(1.0, thrown));
42 }
43
44 /// A crater's share of blocks at `rho` radii from its centre, within its `reach`.
45 265596 double RadialShare(const BoulderEjecta& ejecta, double rho, double reach) {
46
2/2
✓ Branch 0 taken 265592 times.
✓ Branch 1 taken 4 times.
265596 if (ejecta.profile == EjectaProfile::Smoothstep) {
47
2/2
✓ Branch 0 taken 29928 times.
✓ Branch 1 taken 235664 times.
265592 return rho <= 1.0 ? 1.0 : Smoothstep((reach - rho) / (reach - 1.0));
48 }
49
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 3 times.
4 return rho <= 1.0 ? ejecta.floorShare : std::exp(-(rho - 1.0) / ejecta.decayRadii);
50 }
51
52 /// The share of its blocks `crater` keeps at its age.
53 205345 double Retention(const BoulderEjecta& ejecta, const Crater& crater,
54 const DegradationModel& degradation) {
55
2/2
✓ Branch 0 taken 205341 times.
✓ Branch 1 taken 4 times.
205345 if (ejecta.aging == EjectaAging::Freshness) {
56
1/1
✓ Branch 1 taken 205341 times.
205341 const CraterState state = degradation.State(crater);
57
1/2
✓ Branch 0 taken 205341 times.
✗ Branch 1 not taken.
205341 const double freshness = state.fresh.depthRatio > 0.0 ? state.Freshness() : 0.0;
58
1/1
✓ Branch 1 taken 205341 times.
205341 return Smoothstep((freshness - ejecta.minFreshness) / (1.0 - ejecta.minFreshness));
59 }
60 4 return std::pow(std::fmax(0.0, 1.0 - crater.ageGyr / ejecta.lifetimeGyr), ejecta.agingExponent);
61 }
62
63 } // namespace
64
65 2884723 EjectaIndex BoulderLayer::EjectaCraters(const Bounds2d& region) const {
66
2/2
✓ Branch 0 taken 2878436 times.
✓ Branch 1 taken 6287 times.
2884723 if (minCraterDiameter_ <= 0.0) {
67 2878436 return {};
68 }
69
1/1
✓ Branch 2 taken 6287 times.
6287 const double margin = options_.ejecta.reach * 0.5 * craters_->MaxFeatureDiameter();
70 6287 const double spacing = minCraterDiameter_ / craters_->Options().apply.fade.startSamples;
71
2/2
✓ Branch 3 taken 6287 times.
✓ Branch 6 taken 6287 times.
6287 const CraterList all = craters_->Craters(surface_.Expand(region, margin), spacing);
72 ✗ CraterList ejecta = FilterCraters(all, [&](std::size_t, const Crater& crater) {
73 15065 return crater.diameter >= minCraterDiameter_;
74
1/1
✓ Branch 1 taken 6287 times.
6287 });
75 12630 const auto reach = [&](const Crater& crater) {
76 12630 return EjectaReach(options_.ejecta, crater.diameter) * 0.5 * crater.diameter;
77 6287 };
78
1/1
✓ Branch 4 taken 6287 times.
6287 return {std::move(ejecta), surface_, reach};
79 6287 }
80
81 219157 double BoulderLayer::NearestClusterDistance(double x, double y) const {
82 219157 const double spacing = options_.clusters.spacing;
83 219157 const std::uint32_t seed = options_.seed ^ kBoulderClusters;
84
2/2
✓ Branch 1 taken 2088 times.
✓ Branch 2 taken 217069 times.
219157 if (surface_.IsBody()) {
85
1/1
✓ Branch 1 taken 2088 times.
2088 const Vec3d p = surface_.Position({x, y});
86 2088 const double s = 1.0 / spacing;
87 2088 return spacing * static_cast<double>(
88 2088 Worley3(SplitLatticePrecise3(s * p.x, s * p.y, s * p.z), seed).f1);
89 }
90 return spacing *
91 217069 static_cast<double>(
92 217069 Worley2(static_cast<float>(x / spacing), static_cast<float>(y / spacing), seed).f1);
93 }
94
95 392549 double BoulderLayer::ThomasClusterField(double x, double y) const {
96 392549 const BoulderClusters& clusters = options_.clusters;
97 392549 const double sigma = clusters.radius;
98 392549 const double side = kThomasReachRadii * sigma;
99 392549 const double perArea = 1.0 / (clusters.spacing * clusters.spacing);
100 392549 const std::uint32_t seed = options_.seed ^ kBoulderClusters;
101 12735882 const auto word = [](double cell) {
102 12735882 return static_cast<std::uint32_t>(static_cast<std::int64_t>(cell));
103 };
104 12762650 const auto bump = [&](double squared) {
105
2/2
✓ Branch 0 taken 2742369 times.
✓ Branch 1 taken 10020281 times.
12762650 return squared < side * side ? std::exp(-0.5 * squared / (sigma * sigma)) : 0.0;
106 392549 };
107 392549 double sum = 0.0;
108
2/2
✓ Branch 1 taken 90000 times.
✓ Branch 2 taken 302549 times.
392549 if (surface_.IsBody()) {
109
1/1
✓ Branch 1 taken 90000 times.
90000 const Vec3d p = surface_.Position({x, y});
110 90000 const double perCell =
111 90000 perArea / (std::sqrt(2.0 * std::numbers::pi) * sigma) * side * side * side;
112 90000 const double cx = std::floor(p.x / side);
113 90000 const double cy = std::floor(p.y / side);
114 90000 const double cz = std::floor(p.z / side);
115
2/2
✓ Branch 0 taken 270000 times.
✓ Branch 1 taken 90000 times.
360000 for (double k = cz - 1.0; k <= cz + 1.0; k += 1.0) {
116
2/2
✓ Branch 0 taken 810000 times.
✓ Branch 1 taken 270000 times.
1080000 for (double j = cy - 1.0; j <= cy + 1.0; j += 1.0) {
117
2/2
✓ Branch 0 taken 2430000 times.
✓ Branch 1 taken 810000 times.
3240000 for (double i = cx - 1.0; i <= cx + 1.0; i += 1.0) {
118
1/1
✓ Branch 4 taken 2430000 times.
2430000 RandomStream random(seed, kThomasCentres3, word(i), word(j), word(k));
119
1/1
✓ Branch 1 taken 2430000 times.
2430000 const std::uint64_t count = SamplePoisson(random, perCell);
120
2/2
✓ Branch 0 taken 8825112 times.
✓ Branch 1 taken 2430000 times.
11255112 for (std::uint64_t n = 0; n < count; ++n) {
121
1/1
✓ Branch 1 taken 8825112 times.
8825112 const double dx = (i + random.NextDouble()) * side - p.x;
122
1/1
✓ Branch 1 taken 8825112 times.
8825112 const double dy = (j + random.NextDouble()) * side - p.y;
123
1/1
✓ Branch 1 taken 8825112 times.
8825112 const double dz = (k + random.NextDouble()) * side - p.z;
124 8825112 sum += bump(dx * dx + dy * dy + dz * dz);
125 }
126 }
127 }
128 }
129 90000 return sum;
130 }
131 302549 const double perCell = perArea * side * side;
132 302549 const double cx = std::floor(x / side);
133 302549 const double cy = std::floor(y / side);
134
2/2
✓ Branch 0 taken 907647 times.
✓ Branch 1 taken 302549 times.
1210196 for (double j = cy - 1.0; j <= cy + 1.0; j += 1.0) {
135
2/2
✓ Branch 0 taken 2722941 times.
✓ Branch 1 taken 907647 times.
3630588 for (double i = cx - 1.0; i <= cx + 1.0; i += 1.0) {
136
1/1
✓ Branch 3 taken 2722941 times.
2722941 RandomStream random(seed, kThomasCentres2, word(i), word(j));
137
1/1
✓ Branch 1 taken 2722941 times.
2722941 const std::uint64_t count = SamplePoisson(random, perCell);
138
2/2
✓ Branch 0 taken 3937538 times.
✓ Branch 1 taken 2722941 times.
6660479 for (std::uint64_t n = 0; n < count; ++n) {
139
1/1
✓ Branch 1 taken 3937538 times.
3937538 const double dx = (i + random.NextDouble()) * side - x;
140
1/1
✓ Branch 1 taken 3937538 times.
3937538 const double dy = (j + random.NextDouble()) * side - y;
141 3937538 sum += bump(dx * dx + dy * dy);
142 }
143 }
144 }
145 302549 return sum;
146 }
147
148 3712818 double BoulderLayer::BackgroundAbundance(double x, double y, const Ground* ground,
149 double ejecta) const {
150 double background =
151
4/4
✓ Branch 1 taken 1083705 times.
✓ Branch 2 taken 2629113 times.
✓ Branch 6 taken 1083705 times.
✓ Branch 9 taken 1083705 times.
3712818 mapAbundance_ ? mapAbundance_->At(MapValueAt(*options_.densityMap, x, y), ejecta) : 1.0;
152 3712818 const BoulderPatches& patches = options_.patches;
153
2/2
✓ Branch 0 taken 2157678 times.
✓ Branch 1 taken 1555140 times.
3712818 if (patches.spread > 1.0) {
154 const double noise =
155
1/1
✓ Branch 1 taken 2157678 times.
2157678 PatchNoise(surface_, x, y, patches.size, options_.seed ^ kBoulderPatches);
156 2157678 background *= std::pow(patches.spread, noise) / patchMean_;
157 }
158 3712818 const BoulderClusters& clusters = options_.clusters;
159
2/2
✓ Branch 0 taken 611706 times.
✓ Branch 1 taken 3101112 times.
3712818 if (clusters.share > 0.0) {
160 611706 const double field = clusters.model == BoulderClusterModel::Thomas
161
3/3
✓ Branch 0 taken 392549 times.
✓ Branch 1 taken 219157 times.
✓ Branch 3 taken 392549 times.
611706 ? ThomasClusterField(x, y)
162
2/2
✓ Branch 1 taken 219157 times.
✓ Branch 4 taken 219157 times.
219157 : ClusterBump(NearestClusterDistance(x, y), clusters);
163 611706 background *= 1.0 - clusters.share + clusters.share * field / clusterMean_;
164 }
165
2/2
✓ Branch 1 taken 126790 times.
✓ Branch 2 taken 3586028 times.
3712818 if (exposure_) {
166
1/1
✓ Branch 2 taken 126789 times.
126790 RequireGround(ground, "Boulders that read the exposure field");
167
1/1
✓ Branch 2 taken 126789 times.
126789 const double bedrock = exposure_->Exposure(*ground, x, y, options_.bedrock.exposureSpacing);
168 126789 background *= 1.0 + bedrock * (options_.bedrock.abundance - 1.0);
169
2/2
✓ Branch 1 taken 80002 times.
✓ Branch 2 taken 46787 times.
126789 if (bedrockMeans_) {
170
1/1
✓ Branch 1 taken 80002 times.
80002 background /= BedrockMean(x, y, *ground);
171 }
172 }
173 7425634 return std::min(background, maxBackground_);
174 }
175
176 640104 std::size_t BoulderLayer::MeanCellHash::operator()(const MeanCell& cell) const {
177 640104 const auto words = static_cast<std::uint64_t>(reinterpret_cast<std::uintptr_t>(cell.ground));
178 const U32x4 hash =
179 640104 Philox4x32({static_cast<std::uint32_t>(cell.i), static_cast<std::uint32_t>(cell.j),
180 640104 static_cast<std::uint32_t>(words), static_cast<std::uint32_t>(words >> 32)},
181 {kBedrockMeans, 0u});
182 640104 return (static_cast<std::size_t>(hash.x) << 32) ^ hash.y;
183 }
184
185 80002 double BoulderLayer::BedrockMean(double x, double y, const Ground& ground) const {
186 80002 constexpr int kSide = 8;
187 80002 const double gain = options_.bedrock.abundance - 1.0;
188 320008 const auto cellMean = [&](std::int64_t i, std::int64_t j) {
189
2/2
✓ Branch 2 taken 320008 times.
✓ Branch 5 taken 320008 times.
640016 return *bedrockMeans_->Get({&ground, i, j}, [&] {
190 72 double sum = 0.0;
191
2/2
✓ Branch 0 taken 576 times.
✓ Branch 1 taken 72 times.
648 for (int b = 0; b < kSide; ++b) {
192
2/2
✓ Branch 0 taken 4608 times.
✓ Branch 1 taken 576 times.
5184 for (int a = 0; a < kSide; ++a) {
193 4608 const double px =
194 4608 meanOrigin_.x + (static_cast<double>(i) + (a + 0.5) / kSide) * meanCell_.x;
195 4608 const double py =
196 4608 meanOrigin_.y + (static_cast<double>(j) + (b + 0.5) / kSide) * meanCell_.y;
197 9216 sum += 1.0 + gain * exposure_->Exposure(ground, px, py,
198 4608 options_.bedrock.exposureSpacing);
199 }
200 }
201 72 return sum / (kSide * kSide);
202 640016 });
203 80002 };
204 80002 const double u = (x - meanOrigin_.x) / meanCell_.x - 0.5;
205 80002 const double v = (y - meanOrigin_.y) / meanCell_.y - 0.5;
206 80002 const double fu = std::floor(u);
207 80002 const double fv = std::floor(v);
208 80002 const auto i = static_cast<std::int64_t>(fu);
209 80002 const auto j = static_cast<std::int64_t>(fv);
210 80002 const double tu = u - fu;
211 80002 const double tv = v - fv;
212
2/2
✓ Branch 1 taken 80002 times.
✓ Branch 4 taken 80002 times.
80002 return (1.0 - tu) * (1.0 - tv) * cellMean(i, j) + tu * (1.0 - tv) * cellMean(i + 1, j) +
213
2/2
✓ Branch 1 taken 80002 times.
✓ Branch 4 taken 80002 times.
160004 (1.0 - tu) * tv * cellMean(i, j + 1) + tu * tv * cellMean(i + 1, j + 1);
214 }
215
216 193137 void BoulderLayer::EjectaAbundance(double x, double y, const EjectaIndex& ejecta,
217 BoulderAbundance& abundance) const {
218 193137 const BoulderEjecta& eject = options_.ejecta;
219 193137 const DegradationModel& degradation = *craters_->Models().degradation;
220 193137 double share = 0.0;
221 193137 double wear = 0.0;
222
3/3
✓ Branch 1 taken 193137 times.
✓ Branch 8 taken 1206864 times.
✓ Branch 9 taken 193137 times.
1400001 for (const std::uint32_t n : ejecta.Near(x, y)) {
223
1/1
✓ Branch 2 taken 1206864 times.
1206864 const Crater crater = ejecta.Craters().At(n);
224
1/1
✓ Branch 1 taken 1206864 times.
1206864 const double reach = EjectaReach(eject, crater.diameter);
225 const double rho =
226
1/1
✓ Branch 1 taken 1206864 times.
1206864 surface_.Distance({crater.x, crater.y}, {x, y}) / (0.5 * crater.diameter);
227
2/2
✓ Branch 0 taken 941268 times.
✓ Branch 1 taken 265596 times.
1206864 if (rho >= reach) {
228 1001519 continue;
229 }
230
1/1
✓ Branch 1 taken 265596 times.
265596 const double radial = RadialShare(eject, rho, reach);
231
2/2
✓ Branch 0 taken 60251 times.
✓ Branch 1 taken 205345 times.
265596 if (radial <= share) {
232 60251 continue;
233 }
234
1/1
✓ Branch 1 taken 205345 times.
205345 const double retention = Retention(eject, crater, degradation);
235
2/2
✓ Branch 0 taken 205333 times.
✓ Branch 1 taken 12 times.
205345 if (retention * radial > share) {
236 205333 share = retention * radial;
237 205333 wear = 1.0 - retention;
238 }
239 }
240 193137 abundance.ejecta = share;
241 193137 abundance.ejectaWear = wear;
242 193137 }
243
244 3712818 BoulderAbundance BoulderLayer::Abundance(double x, double y, const Ground* ground,
245 const EjectaIndex& ejecta) const {
246 3712818 BoulderAbundance abundance;
247
2/2
✓ Branch 1 taken 193137 times.
✓ Branch 2 taken 3519681 times.
3712818 if (!ejecta.Empty()) {
248 193137 EjectaAbundance(x, y, ejecta, abundance);
249 }
250 3712818 abundance.background = BackgroundAbundance(x, y, ground, abundance.ejecta);
251
2/2
✓ Branch 1 taken 287377 times.
✓ Branch 2 taken 3425440 times.
3712817 if (options_.slopeMap) {
252 287377 abundance.exponent = SizeSlopeAt(*options_.slopeMap, x, y);
253 }
254 3712817 return abundance;
255 }
256
257 2740647 BoulderAbundance BoulderLayer::AbundanceAt(double x, double y, const Ground* ground) const {
258
2/2
✓ Branch 2 taken 2740647 times.
✓ Branch 5 taken 2740646 times.
2740648 return Abundance(x, y, ground, EjectaCraters(PointBounds(x, y)));
259 }
260
261 6259317 double BoulderLayer::Density(double diameter, const BoulderAbundance& abundance) const {
262 6259317 const BoulderSizes& sizes = options_.sizes;
263 6259317 double density = 0.0;
264
2/2
✓ Branch 1 taken 287376 times.
✓ Branch 2 taken 5971941 times.
6259317 if (abundance.exponent) {
265 287376 const double alpha = *abundance.exponent;
266 287376 const double d0 = options_.slopeMap->referenceDiameter;
267 287376 density = abundance.background * referenceCount_ * alpha * std::pow(d0, alpha) *
268 287376 std::pow(diameter, -alpha - 1.0);
269 } else {
270 11943882 density = sizes.distribution
271
2/2
✓ Branch 0 taken 113335 times.
✓ Branch 1 taken 5858606 times.
5971941 ? abundance.background * sizes.distribution->Incremental(diameter)
272 5858606 : GolombekRappDensity(diameter, sizes.coverage * abundance.background,
273 5858606 sizes.qConstant, sizes.qCoverageCoefficient);
274 }
275
2/2
✓ Branch 0 taken 4558924 times.
✓ Branch 1 taken 1700393 times.
6259317 if (abundance.ejecta > 0.0) {
276 4558924 density += abundance.ejecta * ejectaSizes_->Incremental(diameter);
277 }
278 6259317 return density;
279 }
280
281 13 double BoulderLayer::DensityAt(double diameter, double x, double y, const Ground* ground) const {
282
2/2
✓ Branch 1 taken 13 times.
✓ Branch 4 taken 13 times.
13 return Density(diameter, AbundanceAt(x, y, ground));
283 }
284
285 170 std::vector<BoulderLayer::UnresolvedNode> BoulderLayer::UnresolvedNodes(double spacing) const {
286 170 const BoulderSizes& sizes = options_.sizes;
287 170 const double start = options_.fade.startSamples * spacing;
288 170 const double end = std::fmin(options_.fade.endSamples * spacing, sizes.maxDiameter);
289 170 std::vector<UnresolvedNode> nodes;
290 340 const auto add = [&](double low, double high) {
291
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 336 times.
340 if (!(high > low)) {
292 4 return;
293 }
294 336 constexpr int kIntervals = 16;
295 336 const double a = std::log(low);
296 336 const double h = (std::log(high) - a) / kIntervals;
297
2/2
✓ Branch 0 taken 5712 times.
✓ Branch 1 taken 336 times.
6048 for (int i = 0; i <= kIntervals; ++i) {
298 5712 const double d = std::exp(a + h * i);
299
6/6
✓ Branch 0 taken 5376 times.
✓ Branch 1 taken 336 times.
✓ Branch 2 taken 5040 times.
✓ Branch 3 taken 336 times.
✓ Branch 4 taken 2688 times.
✓ Branch 5 taken 2352 times.
5712 const double simpson = (i == 0 || i == kIntervals) ? 1.0 : (i % 2 == 1 ? 4.0 : 2.0);
300 5712 const double unresolved = 1.0 - ResolutionWeight(d, spacing, options_.fade);
301
2/2
✓ Branch 0 taken 5546 times.
✓ Branch 1 taken 166 times.
5712 if (unresolved > 0.0) {
302 5546 nodes.push_back(
303
1/1
✓ Branch 1 taken 5546 times.
5546 {d, 0.25 * std::numbers::pi * d * d, unresolved * d * simpson * h / 3.0});
304 }
305 }
306 170 };
307
1/1
✓ Branch 1 taken 170 times.
170 add(sizes.minDiameter, std::fmin(start, end));
308
1/1
✓ Branch 1 taken 170 times.
170 add(std::fmax(sizes.minDiameter, start), end);
309 340 return nodes;
310 }
311
312 165220 UnresolvedCover BoulderLayer::UnresolvedCoverWith(const BoulderAbundance& abundance,
313 const std::vector<UnresolvedNode>& nodes,
314 double spacing) const {
315 165220 UnresolvedCover cover;
316
2/2
✓ Branch 4 taken 5452196 times.
✓ Branch 5 taken 165220 times.
5617416 for (const UnresolvedNode& node : nodes) {
317
1/1
✓ Branch 1 taken 5452196 times.
5452196 const double n = Density(node.diameter, abundance) * node.weight;
318 5452196 cover.mean += node.footprint * n;
319 5452196 cover.variance += node.footprint * node.footprint * n;
320 }
321 165220 cover.variance /= spacing * spacing;
322 165220 return cover;
323 }
324
325 167 UnresolvedCover BoulderLayer::UnresolvedCoverAt(double x, double y, double spacing,
326 const Ground* ground) const {
327
1/1
✓ Branch 2 taken 166 times.
167 RequirePositive(spacing, "Unresolved cover spacing");
328
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 165 times.
166 if (options_.sizes.minDiameter >= options_.fade.endSamples * spacing) {
329 1 return {};
330 }
331
3/3
✓ Branch 1 taken 165 times.
✓ Branch 4 taken 165 times.
✓ Branch 7 taken 165 times.
165 return UnresolvedCoverWith(AbundanceAt(x, y, ground), UnresolvedNodes(spacing), spacing);
332 }
333
334 6 std::vector<UnresolvedCover> BoulderLayer::UnresolvedCoverOver(const RasterGrid& grid,
335 double spacing, const Ground* ground,
336 unsigned threads) const {
337
1/1
✓ Branch 2 taken 6 times.
6 RequirePositive(spacing, "Unresolved cover spacing");
338
1/1
✓ Branch 1 taken 6 times.
6 std::vector<UnresolvedCover> cover(grid.width * grid.height);
339
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 5 times.
6 if (options_.sizes.minDiameter >= options_.fade.endSamples * spacing) {
340 1 return cover;
341 }
342
2/2
✓ Branch 1 taken 5 times.
✓ Branch 4 taken 5 times.
5 const EjectaIndex ejecta = EjectaCraters(grid.Bounds());
343
1/1
✓ Branch 1 taken 5 times.
5 const std::vector<UnresolvedNode> nodes = UnresolvedNodes(spacing);
344
2/2
✓ Branch 1 taken 5 times.
✓ Branch 4 taken 5 times.
5 ParallelFor(grid.height, threads, [&](std::size_t row) {
345
2/2
✓ Branch 0 taken 165055 times.
✓ Branch 1 taken 486 times.
165541 for (std::size_t col = 0; col < grid.width; ++col) {
346 165055 const Vec2d centre = grid.transform.PixelToWorld(static_cast<double>(col) + 0.5,
347 165055 static_cast<double>(row) + 0.5);
348 165055 cover[row * grid.width + col] =
349
2/2
✓ Branch 1 taken 165055 times.
✓ Branch 4 taken 165055 times.
330110 UnresolvedCoverWith(Abundance(centre.x, centre.y, ground, ejecta), nodes, spacing);
350 }
351 486 });
352 5 return cover;
353 5 }
354
355 } // namespace terraingen
356