TerrainGen coverage


terraingen/
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
11 / 11
100.0%
Branches:
6 / 12
50.0%
Functions:
3 / 3, 1 excl
100.0%

layers/sand_shadow.h
Line Branch Exec Source
1 /// @file
2 /// @brief `SandShadowLayer`, sand tails in the lee of a boulder layer's boulders.
3 #pragma once
4
5 #include "terraingen/layers/boulders/boulder_layer.h"
6 #include "terraingen/layers/fade.h"
7 #include "terraingen/layers/layer.h"
8 #include "terraingen/layers/material.h"
9
10 #include <memory>
11 #include <vector>
12
13 namespace terraingen {
14
15 /// The sand shadows a `SandShadowLayer` lays behind boulders. Angles are in radians.
16 struct SandShadowOptions {
17 /// Where the wind blows toward, radians counter-clockwise from +x (local east on a body).
18 5 double windAzimuth = 0.0;
19 /// Length of a shadow beyond the boulder over the boulder's width. 1.1 is the reattachment
20 /// length behind a dome (Savory and Toy 1986, after Hesp and Smyth 2017); their modelled
21 /// shadow dunes run 1.3 to 5.6 widths, longer in lighter winds.
22 5 double lengthRatio = 1.1;
23 /// Slope of a shadow's flanks, below 90 deg; at most the angle of repose, about 32 deg for dry
24 /// medium sand (Hesp 1981).
25 5 double flankAngle = 0.5585053606381855;
26 5 double minDiameter = 0.0; ///< Smallest boulder (m) with a shadow.
27 /// Sand depth (m) that fully covers the ground in the material map.
28 5 double coverThickness = 0.02;
29 5 ResolutionFade fade{}; ///< Fade of shadows behind boulders too small for the spacing.
30
31
6/12
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 5 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 5 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 5 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 5 times.
5 bool operator==(const SandShadowOptions&) const = default;
32 };
33
34 /// Checks sand shadow options.
35 /// @throws std::invalid_argument for a non-finite wind azimuth, a length ratio or cover thickness
36 /// that is not positive and finite, a flank angle outside (0, 90) deg, a negative minimum
37 /// diameter, or an invalid fade.
38 void ValidateSandShadowOptions(const SandShadowOptions& options);
39
40 /// Sand shadows: a sand tail in the lee of each boulder of a boulder layer, after Hesp (1981).
41 ///
42 /// A tail is a pyramid starting at the boulder's downwind edge as wide as the boulder (its
43 /// diameter), its flanks at `flankAngle`, so its crest is (width / 2) tan(flankAngle) high; where
44 /// that is higher than the boulder stands, the crest is lowered to the boulder's top and the flanks
45 /// eased. It narrows and lowers to a point `lengthRatio` widths downwind. Overlapping tails take
46 /// the deepest sand. The tails are added to the height beneath, so place the layer after the
47 /// boulder layer; it lays sand over the material map.
48 ///
49 /// The boulders are those the boulder layer places, read with this layer's ground; with the
50 /// boulder layer's bedrock exposure field that ground includes the boulders' relief.
51 class SandShadowLayer final : public Layer, public MaterialSource {
52 public:
53 /// @param boulders The boulder layer whose boulders cast shadows; on `surface`.
54 /// @throws std::invalid_argument for invalid options or a null boulder layer.
55 SandShadowLayer(std::shared_ptr<const BoulderLayer> boulders, SandShadowOptions options,
56 Surface surface = {});
57
58 /// The sand depth (m) the shadows lay at world (x, y).
59 /// @param spacing Sample spacing in metres, which picks the boulders as the boulder layer does.
60 /// @param ground Needed with the boulder layer's exposure field.
61 double ThicknessAt(double x, double y, double spacing = 0.0,
62 const Ground* ground = nullptr) const;
63
64 /// The options the layer was made with.
65 1 const SandShadowOptions& Options() const {
66 1 return options_;
67 }
68
69 3076 MaterialClass Material() const override {
70 3076 return MaterialClass::Sand;
71 }
72 /// The sand depth over `coverThickness`, smoothed, in [0, 1].
73 double MaterialCoverAt(double x, double y, double spacing, const Ground* ground) const override;
74 /// `MaterialCoverAt` over `grid`, the boulders found once for the whole grid.
75 Raster<double> MaterialCoverOver(const RasterGrid& grid, double spacing, const Ground* ground,
76 unsigned threads) const override;
77
78 protected:
79 void ApplySamples(SampleBlock& samples, const LayerContext& context) const override;
80
81 private:
82 /// One boulder's shadow, ready to draw.
83 struct Shadow {
84 Vec2d centre{};
85 double width = 0.0;
86 double cap = 0.0;
87 double weight = 1.0;
88 Bounds2d box{};
89 };
90 std::vector<Shadow> ShadowsOver(const Bounds2d& region, double spacing,
91 const Ground* ground) const;
92 double DepthOf(const Shadow& shadow, double x, double y) const;
93
94 std::shared_ptr<const BoulderLayer> boulders_;
95 SandShadowOptions options_;
96 Surface surface_;
97 Vec2d downwind_{1.0, 0.0};
98 double flankSlope_ = 0.0;
99 };
100
101 } // namespace terraingen
102