albedo/slope_albedo.h
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /// @file | ||
| 2 | /// @brief Slope maturity: steep ground kept fresh, and bright, by regolith moving downslope. | ||
| 3 | #pragma once | ||
| 4 | |||
| 5 | #include "terraingen/albedo/albedo.h" | ||
| 6 | #include "terraingen/albedo/maturity.h" | ||
| 7 | #include "terraingen/util/surface.h" | ||
| 8 | |||
| 9 | #include <vector> | ||
| 10 | |||
| 11 | namespace terraingen { | ||
| 12 | |||
| 13 | /// How steep ground stays immature. Downslope movement keeps regolith on steep slopes fresh: | ||
| 14 | /// Ikeda et al. (2022, Figs. 6d and 11d) found the optical maturity parameter (OMAT) of crater | ||
| 15 | /// walls in Schrodinger and Laue rising with slope from about 0.10 at 20 degrees, about 0.0065 per | ||
| 16 | /// degree, on slopes from the 10 m KAGUYA terrain camera DTM; Lucey et al. (2014) found slopes | ||
| 17 | /// steeper than 20 degrees 0.02 brighter than those below 10, where mass wasting is ineffective, | ||
| 18 | /// and Boyd and Robinson (2019) immature, brighter material on slopes steeper than 25 degrees. OMAT | ||
| 19 | /// rises by `maturityPerDegree` beyond `onsetDegrees`, capped at `maxMaturity`, and the albedo | ||
| 20 | /// moves with it (`ReflectanceAtMaturity`). | ||
| 21 | struct SlopeMaturityOptions { | ||
| 22 | 1 | double onsetDegrees = 20.0; ///< Slope from which ground freshens, in [0, 90). | |
| 23 | 1 | double maturityPerDegree = 0.0065; ///< OMAT gained per degree beyond the onset; >= 0. | |
| 24 | 1 | double backgroundMaturity = 0.10; ///< OMAT of gentler ground; positive. | |
| 25 | 1 | double maxMaturity = 0.42; ///< Cap on OMAT; >= `backgroundMaturity`. | |
| 26 | 1 | double baseline = 10.0; ///< Metres slopes are measured over; positive. | |
| 27 | /// Reflectance of the optical maturity origin (`ReflectanceAtMaturity`). | ||
| 28 | 1 | double originReflectance = OpticalMaturityOrigin{}.reflectance; | |
| 29 | |||
| 30 | 1 | bool operator==(const SlopeMaturityOptions&) const = default; | |
| 31 | }; | ||
| 32 | |||
| 33 | /// Checks slope maturity options. | ||
| 34 | /// @throws std::invalid_argument for an onset outside [0, 90), a negative or unbounded rate, a | ||
| 35 | /// background maturity that is not positive, a cap below it, a baseline that is not positive, or | ||
| 36 | /// any value that is not finite. | ||
| 37 | void ValidateSlopeMaturity(const SlopeMaturityOptions& options); | ||
| 38 | |||
| 39 | /// The albedo of steep ground moved toward fresher material: slopes are read on the ground at the | ||
| 40 | /// nodes of a lattice `baseline` metres apart, fixed to the surface, and interpolated between | ||
| 41 | /// them, so grids, tiles and points agree. Without a ground the albedo is left alone. | ||
| 42 | class SlopeAlbedo final : public AlbedoLayer { | ||
| 43 | public: | ||
| 44 | /// @throws std::invalid_argument for options invalid as `ValidateSlopeMaturity`. | ||
| 45 | explicit SlopeAlbedo(SlopeMaturityOptions options = {}, Surface surface = {}); | ||
| 46 | |||
| 47 | /// Moves `value` to the maturity of the slope at (`x`, `y`); NaN stays NaN. | ||
| 48 | void ApplyAt(AlbedoSample& value, std::size_t bands, double x, double y, | ||
| 49 | const AlbedoContext& context) const override; | ||
| 50 | |||
| 51 | /// `ApplyAt` at every cell centre, the lattice read once. | ||
| 52 | void Apply(std::vector<Raster<float>>& bands, const AlbedoContext& context) const override; | ||
| 53 | |||
| 54 | /// The slope in degrees at (`x`, `y`) on `ground`, interpolated between lattice nodes. | ||
| 55 | double SlopeAt(double x, double y, const Ground& ground) const; | ||
| 56 | |||
| 57 | /// The OMAT of ground of `slopeDegrees`. | ||
| 58 | double MaturityAt(double slopeDegrees) const; | ||
| 59 | |||
| 60 | private: | ||
| 61 | struct Lattice; | ||
| 62 | |||
| 63 | /// The lattice nodes covering `region` and one node beyond, their heights read on `ground`. | ||
| 64 | Lattice ReadLattice(const Bounds2d& region, const Ground& ground) const; | ||
| 65 | /// The slope at (`x`, `y`) from the nodes of `lattice` around it. | ||
| 66 | double Interpolate(const Lattice& lattice, double x, double y) const; | ||
| 67 | void Mature(AlbedoSample& value, std::size_t bands, double slopeDegrees) const; | ||
| 68 | |||
| 69 | SlopeMaturityOptions options_; | ||
| 70 | Surface surface_; | ||
| 71 | double step_ = 0.0; ///< Lattice step in surface coordinates. | ||
| 72 | }; | ||
| 73 | |||
| 74 | } // namespace terraingen | ||
| 75 |