TerrainGen coverage


terraingen/
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
46 / 51
90.2%
Branches:
41 / 78
52.6%
Functions:
7 / 7, 2 excl
100.0%

layers/craters/shaping/apply_options.h
Line Branch Exec Source
1 /// @file
2 /// @brief How craters are applied to the terrain: their order, datum, blend, outlines and rims.
3 #pragma once
4
5 #include "terraingen/layers/craters/generation/population.h"
6 #include "terraingen/layers/craters/shaping/irregularity.h"
7 #include "terraingen/layers/craters/shaping/slope.h"
8 #include "terraingen/layers/fade.h"
9 #include "terraingen/util/surface.h"
10
11 #include <cstddef>
12 #include <cstdint>
13 #include <vector>
14
15 namespace terraingen {
16
17 /// The order in which overlapping craters are applied; later craters overprint earlier ones.
18 enum class CraterOrder {
19 OldestFirst, ///< Decreasing age, then decreasing diameter: the physical order.
20 LargestFirst, ///< Decreasing diameter, then decreasing age.
21 };
22
23 /// The reference surface a crater's interior is cut relative to.
24 enum class CraterDatum {
25 None, ///< No datum: the profile is added onto the terrain everywhere.
26 Plane, ///< Least-squares plane over the fit footprint; keeps regional slopes.
27 MeanHeight, ///< Flat datum at the mean height over the fit footprint.
28 CentreHeight, ///< Flat datum at the terrain height under the crater centre.
29 };
30
31 /// Where a crater's replaced interior blends into the surrounding terrain, in crater radii.
32 struct CraterBlend {
33 39 double startRadii = 0.8; ///< Interior weight is 1 up to here.
34 39 double endRadii = 1.2; ///< And 0 from here; above `startRadii`.
35 39 BlendShape shape = BlendShape::Smootherstep; ///< The curve in between.
36
37 /// The interior weight at `radii` crater radii from the centre: 1 up to `startRadii`, 0 from
38 /// `endRadii`, and `shape` in between.
39 236223 double Weight(double radii) const {
40 236223 return Falloff(radii, startRadii, endRadii, shape);
41 }
42
43
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 39 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 39 times.
39 bool operator==(const CraterBlend&) const = default;
44 };
45
46 /// How crater rims are rounded: near the rim, the profile is blended toward itself smoothed across
47 /// distance by a Gaussian, with full weight at the rim fading to none at the band's edges.
48 struct RimSmoothing {
49 /// Gaussian standard deviation in crater radii; 0 leaves rims sharp.
50 40 double sigmaRadii = 0.0;
51 40 double innerRadii = 0.8; ///< Inner edge of the smoothed band, in crater radii; in [0, 1).
52 40 double outerRadii = 1.2; ///< Outer edge of the smoothed band, in crater radii; above 1.
53 40 BlendShape shape = BlendShape::Smootherstep; ///< How the weight falls toward the edges.
54 40 double strength = 1.0; ///< Share of the smoothed height used at the rim, in [0, 1].
55
56 /// The smoothing weight at `radii` crater radii from the centre: `strength` at the rim, 0 from
57 /// the band's edges and when `sigmaRadii` is 0.
58 double Weight(double radii) const;
59
60
5/10
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 40 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 40 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 40 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 40 times.
40 bool operator==(const RimSmoothing&) const = default;
61 };
62
63 /// Checks rim smoothing settings.
64 /// @throws std::invalid_argument for a negative or non-finite `sigmaRadii`, a `strength` outside
65 /// [0, 1], or a band that does not satisfy 0 <= `innerRadii` < 1 < `outerRadii`.
66 void ValidateRimSmoothing(const RimSmoothing& smoothing);
67
68 /// Fractal noise added to each crater, keyed to its ID so tiles and point queries agree: over the
69 /// whole footprint, fading out to nothing at the profile's reach, and in a band around the rim.
70 /// Amplitudes are shares of the crater's diameter, so the noise scales with the crater.
71 struct CraterNoise {
72 39 double amplitude = 0.0; ///< Footprint noise amplitude over the diameter; 0 adds none.
73 39 double wavelengthRadii = 0.5; ///< Wavelength of its first octave, in crater radii.
74 39 int octaves = 4; ///< Octaves of both noises, 1 to 12.
75 39 double gain = 0.5; ///< Weight ratio between successive octaves; positive.
76 39 double rimAmplitude = 0.0; ///< Rim noise amplitude over the diameter; 0 adds none.
77 39 double rimWavelengthRadii = 0.1; ///< Wavelength of its first octave, in crater radii.
78 39 double rimInnerRadii = 0.8; ///< Inner edge of the rim band, in crater radii; in [0, 1).
79 39 double rimOuterRadii = 1.2; ///< Outer edge of the rim band, in crater radii; above 1.
80 39 std::uint32_t seed = 0; ///< Varies the noise of every crater.
81
82
9/18
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 39 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 39 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 39 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 39 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 39 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 39 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 39 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 39 times.
39 bool operator==(const CraterNoise&) const = default;
83 };
84
85 /// Checks crater noise settings.
86 /// @throws std::invalid_argument for a negative or non-finite amplitude, a non-positive
87 /// wavelength or gain, octaves outside 1 to 12, or a rim band that does not satisfy
88 /// 0 <= `rimInnerRadii` < 1 < `rimOuterRadii`.
89 void ValidateCraterNoise(const CraterNoise& noise);
90
91 /// The texture of a crater's walls and ejecta, keyed to its ID: radial gullies down the inner
92 /// wall, hummocky ejecta lineated away from the rim, and older relief buried under the ejecta.
93 /// Ejecta follow McGetchin et al.'s (1973) thickness 0.14 R^0.74 (r / R)^-3 m, tapered to nothing
94 /// at `ejectaReachRadii`. Gullies and ejecta texture fade as the crater wears; burial stays.
95 struct CraterTexture {
96 39 double wallStreaks = 0.0; ///< Gully amplitude over the diameter; 0 adds none.
97 39 double wallStreakWidthRadii = 0.15; ///< Width of the gullies across the wall, in radii.
98 39 double ejecta = 0.0; ///< Ejecta texture amplitude over the ejecta thickness; 0 adds none.
99 39 double ejectaLineationRadii = 0.15; ///< Width of the lineations across, in radii at the rim.
100 /// Share of older relief the ejecta replace by the crater's datum at the rim, falling with
101 /// their thickness; 0 buries nothing, and without a datum nothing is buried.
102 39 double mantling = 0.0;
103 39 double ejectaReachRadii = 3.0; ///< How far ejecta texture and burial reach, in radii.
104 /// Freshness (`CraterState::Freshness`) at or below which gullies and ejecta texture are gone,
105 /// in [0, 1); they fade in along a smoothstep above it.
106 39 double minFreshness = 0.5;
107 39 std::uint32_t seed = 0; ///< Varies the texture of every crater.
108
109 /// Whether anything is drawn beyond the profile: ejecta texture or burial.
110 1773812 bool ReachesBeyondRim() const {
111
4/4
✓ Branch 0 taken 1659416 times.
✓ Branch 1 taken 114396 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1659414 times.
1773812 return ejecta > 0.0 || mantling > 0.0;
112 }
113
114
8/16
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 39 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 39 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 39 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 39 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 39 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 39 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 39 times.
39 bool operator==(const CraterTexture&) const = default;
115 };
116
117 /// Checks crater texture settings.
118 /// @throws std::invalid_argument for a negative or non-finite amplitude, a non-positive width, a
119 /// mantling outside [0, 1], a reach of 1 radius or less, or a freshness outside [0, 1).
120 void ValidateCraterTexture(const CraterTexture& texture);
121
122 /// McGetchin et al.'s (1973) ejecta thickness at `radii` crater radii over that at the rim,
123 /// (r / R)^-3, tapered linearly in it to nothing at `reachRadii`; 1 within the rim.
124 double EjectaThicknessShare(double radii, double reachRadii);
125
126 /// How `ApplyCraters` shapes craters into the terrain.
127 struct CraterApplyOptions {
128 39 CraterOrder order = CraterOrder::OldestFirst; ///< Which craters overprint which.
129 /// How craters too small to resolve at the sample spacing fade out.
130 39 ResolutionFade fade{};
131 /// Reference surface for the interior (`FitCraterDatum`); with `None` craters are purely
132 /// additive and the datum settings below are unused.
133 39 CraterDatum datum = CraterDatum::None;
134 /// Footprint the datum is fitted over, in crater radii.
135 39 double datumFitRadii = 1.0;
136 /// Share of the interior replaced by datum plus profile, in [0, 1]: 1 erases older relief, 0
137 /// keeps it.
138 39 double interiorReplacement = 1.0;
139 39 CraterBlend blend{}; ///< Where the replaced interior blends out.
140 /// Irregular, non-circular outlines; off by default.
141 39 CraterIrregularity irregularity{};
142 39 RimSmoothing rimSmoothing{}; ///< Rounded rims; off by default.
143 39 CraterNoise noise{}; ///< Fractal noise over each crater; off by default.
144 39 CraterTexture texture{}; ///< Wall gullies, ejecta texture and burial; off by default.
145 /// Floors offset downslope, rims lowered upslope and faster wear on the slope of the ground
146 /// beneath the layer; needs the `Plane` datum.
147 39 CraterSlopeResponse slope{};
148 /// What craters are shaped on; on a sphere, centres and rasters are longitude and latitude and
149 /// each crater is shaped in its local frame, spacings in metres.
150 39 Surface surface{};
151
152
12/24
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 39 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 39 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 39 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 39 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 39 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 39 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 39 times.
✗ Branch 21 not taken.
✓ Branch 22 taken 39 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 39 times.
✗ Branch 27 not taken.
✓ Branch 28 taken 39 times.
✗ Branch 30 not taken.
✓ Branch 31 taken 39 times.
39 bool operator==(const CraterApplyOptions&) const = default;
153 };
154
155 /// Checks crater apply options.
156 /// @throws std::invalid_argument for an invalid `fade`, `irregularity`, `rimSmoothing` or `slope`,
157 /// a slope response without the `Plane` datum, a
158 /// non-positive `datumFitRadii`, an `interiorReplacement` outside [0, 1], or a blend that does not
159 /// satisfy 0 <= `startRadii` < `endRadii`.
160 void ValidateCraterApplyOptions(const CraterApplyOptions& options);
161
162 /// Indices into `craters` in the order they are applied; ties fall to age, then diameter, then
163 /// the smaller ID.
164 std::vector<std::size_t> CraterApplyOrder(const CraterList& craters, CraterOrder order);
165
166 } // namespace terraingen
167