TerrainGen coverage


terraingen/
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
19 / 19
100.0%
Branches:
12 / 24
50.0%
Functions:
4 / 4, 1 excl
100.0%

layers/bedforms.h
Line Branch Exec Source
1 /// @file
2 /// @brief `BedformLayer`, fields of wind-blown ripples or dunes.
3 #pragma once
4
5 #include "terraingen/layers/exposure.h"
6 #include "terraingen/layers/fade.h"
7 #include "terraingen/layers/layer.h"
8 #include "terraingen/layers/material.h"
9 #include "terraingen/random/stream.h"
10 #include "terraingen/util/cells.h"
11
12 #include <cstdint>
13 #include <optional>
14
15 namespace terraingen {
16
17 /// The bedform fields a `BedformLayer` scatters: their ripples, cover and wind.
18 struct BedformOptions {
19 3 double wavelength = 1.0; ///< Crest to crest (m); each field's varies from 0.8 to 1.2 times it.
20 3 double height = 0.1; ///< Trough to crest (m), scaled with each field's wavelength.
21 /// Where the wind blows toward, radians counter-clockwise from +x; crests lie across it.
22 3 double windAzimuth = 0.0;
23 3 double azimuthSpread = 0.0; ///< Each field's wind differs by up to this (radians).
24 /// Share of a wavelength the lee face takes, in (0, 1): 0.5 is symmetric, less is steeper.
25 3 double leeFraction = 0.5;
26 3 double sinuosity = 0.5; ///< How far a crest wanders along its length, in wavelengths.
27 3 double cover = 0.0; ///< Share of the ground under fields, in [0, 0.9].
28 3 double fieldSize = 100.0; ///< Typical width of a field (m).
29 3 std::uint32_t seed = 1; ///< Varies the fields.
30 /// When set, a field is left out with probability the exposure at its centre, read from the
31 /// ground beneath the layer.
32 3 std::optional<ExposureParams> exposure;
33 3 double exposureSpacing = 1.0; ///< Spacing the ground is read at for the exposure field (m).
34 /// How bedforms too fine for the spacing fade out, by samples per wavelength.
35 3 ResolutionFade fade{};
36
37
12/24
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 3 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 3 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 3 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 3 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 3 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 3 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 3 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 3 times.
3 bool operator==(const BedformOptions&) const = default;
38 };
39
40 /// Checks bedform options.
41 /// @throws std::invalid_argument for a non-positive wavelength or field size, a negative height,
42 /// a lee fraction outside (0, 1), a cover outside [0, 0.9], a negative sinuosity or spread, a
43 /// non-positive exposure spacing, or an invalid fade or exposure.
44 void ValidateBedformOptions(const BedformOptions& options);
45
46 /// Martian large wind ripples: 2 m wavelength, 0.2 m height, a 30 degree lee slope and sinuous
47 /// crests; cover and field size are placeholders to set per site.
48 BedformOptions MarsLargeRipples();
49
50 /// Martian transverse aeolian ridges: symmetric, 25.8 m wavelength and 1.3 m height; cover and
51 /// field size are placeholders to set per site.
52 BedformOptions MarsTransverseAeolianRidges();
53
54 /// Fields of wind-blown bedforms, ripples or dunes, added to the terrain.
55 ///
56 /// Each lattice cell may hold a field with a ragged edge whose crests run across its wind; relief
57 /// is C1 and zero in the troughs, and overlapping fields average by cover. A function of position
58 /// only, so grids, tiles and points agree.
59 class BedformLayer final : public FormulaLayer, public MaterialSource {
60 public:
61 /// On a sphere, fields are drawn in `CubeSphereCells`, shaped in their centres' local frames,
62 /// with the azimuth counter-clockwise from local east. Applying the layer with the exposure
63 /// field enabled needs `context.ground`.
64 /// @throws std::invalid_argument as `ValidateBedformOptions`.
65 explicit BedformLayer(BedformOptions options, Surface surface = {});
66
67 /// How fully world (x, y) lies in a field, in [0, 1]; independent of the spacing.
68 /// @param ground Read by the exposure field; may be null without one.
69 /// @throws std::invalid_argument if the exposure field is enabled and `ground` is null.
70 double CoverAt(double x, double y, const Ground* ground = nullptr) const;
71
72 /// The options the layer was made with.
73 1 const BedformOptions& Options() const {
74 1 return options_;
75 }
76
77 2 MaterialClass Material() const override {
78 2 return MaterialClass::Sand;
79 }
80 /// `CoverAt`: the bedform fields are sand.
81 66078 double MaterialCoverAt(double x, double y, double /*spacing*/,
82 const Ground* ground) const override {
83 66078 return CoverAt(x, y, ground);
84 }
85
86 protected:
87 float HeightAt(float height, double x, double y, double spacing,
88 const Ground* ground) const override;
89 void CheckContext(const LayerContext& context) const override;
90
91 private:
92 struct Point {
93 double cover = 0.0;
94 double relief = 0.0;
95 };
96 Point Evaluate(double x, double y, const Ground* ground) const;
97 void AddField(Point& point, RandomStream& random, const Vec2d& centre, const Vec2d& offset,
98 const Ground* ground) const;
99
100 BedformOptions options_;
101 double cell_ = 1.0;
102 double density_ = 0.0;
103 std::optional<ExposureField> exposure_;
104 std::optional<CubeSphereCells> cells_;
105 };
106
107 } // namespace terraingen
108