TerrainGen coverage


terraingen/
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
10 / 10
100.0%
Branches:
13 / 22
59.1%
Functions:
2 / 2, 1 excl
100.0%

layers/craters/shaping/slope.h
Line Branch Exec Source
1 /// @file
2 /// @brief Craters formed on slopes: floors offset downslope and raised rims lowered upslope.
3 #pragma once
4
5 #include "terraingen/layers/craters/crater.h"
6 #include "terraingen/random/value_distribution.h"
7 #include "terraingen/util/geometry.h"
8
9 #include <cstdint>
10 #include <optional>
11
12 namespace terraingen {
13
14 /// How craters formed on a slope become asymmetric along it and wear faster.
15 ///
16 /// Lunar craters on slopes have their deepest point offset downslope, an upslope margin that is
17 /// often only a break in slope with little raised rim, and ejecta thrown mostly downslope; the
18 /// asymmetry shows from slopes of a few degrees and does not grow on steeper ones, and they are
19 /// on average no longer downslope than across (Plescia et al. 2019,
20 /// https://www.hou.usra.edu/meetings/lpsc2019/pdf/2984.pdf).
21 ///
22 /// The slope is that of the ground beneath the layer, its source and earlier layers, across each
23 /// crater's datum footprint; the craters of the layer itself are left out, so each crater's shape
24 /// depends on no other and the relief its datum is fitted to is the relief applied. A crater on the
25 /// wall of a larger one responds to it when the larger craters are in an earlier layer. Needs the
26 /// `Plane` datum.
27 struct CraterSlopeResponse {
28 39 bool enabled = false; ///< Off: craters keep their shape on any slope.
29 39 std::uint32_t seed = 0; ///< Varies the floor offsets.
30 /// How far the deepest point lies downslope of the centre, in diameters, drawn per crater;
31 /// below 0.23. The default spans the interquartile range of the upslope wall width over the
32 /// downslope diameter, 0.55 to 0.69 with a median of 0.61, digitized from Plescia et al.
33 /// (2019, Fig. 3).
34 39 ValueDistribution floorOffset{ValueDistribution::Kind::Uniform, 0.045, 0.194};
35 /// Share of the raised rim and ejecta kept straight upslope, in [0, 1]; the rest returns as
36 /// the squared cosine of the angle from upslope falls, all of it across the slope and
37 /// downslope.
38 39 double upslopeRim = 0.0;
39 /// Slope (radians) at which the asymmetry is complete, rising from none on level ground along
40 /// a smoothstep; 5 degrees, the "few degrees" of Plescia et al. (2019).
41 39 double fullSlope = 0.08726646259971647;
42 /// The critical gradient Sc (rise over run) toward which downslope transport grows without
43 /// bound: a crater on a regional gradient S wears 1 / (1 - (S / Sc)^2) times as fast, the
44 /// nonlinear hillslope transport of Roering et al. (1999,
45 /// https://doi.org/10.1029/1998WR900090) that Fassett and Thomson (2014,
46 /// https://doi.org/10.1002/2014JE004698) suggest for steep lunar slopes. Unset wears craters
47 /// alike on any slope; it applies whether or not `enabled` is set. No lunar value is
48 /// published, so it has no default.
49 39 std::optional<double> criticalGradient{};
50 /// The fastest a slope makes craters wear, over level ground; at least 1. It caps the rate as
51 /// S nears Sc, where the form grows without bound; a numerical limit, not a measured one.
52 39 double maxWearRate = 10.0;
53
54
7/14
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
✗ Branch 2 not taken.
✓ Branch 3 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 14 not taken.
✓ Branch 15 taken 39 times.
39 bool operator==(const CraterSlopeResponse&) const = default;
55 };
56
57 /// How many times as fast a crater wears on ground rising `east` and `north` metres per metre,
58 /// under `response`'s critical gradient; 1 without one.
59 double SlopeWearRate(const CraterSlopeResponse& response, double east, double north);
60
61 /// Checks slope response settings.
62 /// @throws std::invalid_argument for an invalid floor offset distribution or one outside
63 /// [0, 0.23), an `upslopeRim` outside [0, 1], or a `fullSlope` that is not positive and finite.
64 void ValidateCraterSlopeResponse(const CraterSlopeResponse& response);
65
66 /// One crater's asymmetry on its slope.
67 struct CraterSlopeShape {
68 Vec2d shift{}; ///< Where the deepest point moves, east and north of the centre (m).
69 Vec2d upslope{}; ///< Upslope unit vector times the share of raised relief removed there.
70
71 /// Whether the crater keeps its level-ground shape.
72 1587521 bool Level() const {
73
6/8
✓ Branch 0 taken 1528613 times.
✓ Branch 1 taken 58908 times.
✓ Branch 2 taken 1528612 times.
✓ Branch 3 taken 1 time.
✓ Branch 4 taken 1528612 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1528612 times.
✗ Branch 7 not taken.
1587521 return shift.x == 0.0 && shift.y == 0.0 && upslope.x == 0.0 && upslope.y == 0.0;
74 }
75 };
76
77 /// The asymmetry `response` gives `crater` on ground rising `east` and `north` metres per metre,
78 /// its floor offset drawn from its ID; level when disabled or on level ground.
79 CraterSlopeShape SlopeShape(const Crater& crater, double east, double north,
80 const CraterSlopeResponse& response);
81
82 /// Where the round profile is read for a point at `offset` metres from the centre: moved back by
83 /// `shape`'s shift in full within 0.3 radii, fading along a smoothstep to none at the rim.
84 /// @param radius Crater radius in metres.
85 Vec2d SlopeShiftedOffset(const CraterSlopeShape& shape, const Vec2d& offset, double radius);
86
87 /// The share of a crater's raised relief, rim and ejecta, kept at `offset` from its centre: 1 less
88 /// the removed share times the squared cosine of the angle from upslope, smooth across the slope.
89 double SlopeRaisedShare(const CraterSlopeShape& shape, const Vec2d& offset);
90
91 } // namespace terraingen
92