TerrainGen coverage


terraingen/
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
16 / 16
100.0%
Branches:
8 / 16
50.0%
Functions:
5 / 5, 1 excl
100.0%

albedo/raster_albedo.h
Line Branch Exec Source
1 /// @file
2 /// @brief `RasterAlbedo`, an albedo map upscaled with fractal detail that continues its roughness.
3 #pragma once
4
5 #include "terraingen/albedo/albedo.h"
6 #include "terraingen/layers/fade.h"
7 #include "terraingen/raster/resample.h"
8
9 #include <cstddef>
10 #include <cstdint>
11 #include <optional>
12 #include <vector>
13
14 namespace terraingen {
15
16 /// Detail below a map's resolution: fractal noise that continues the map's own measured
17 /// roughness to finer scales, multiplying the albedo. Octaves too fine for the sample spacing fade
18 /// out.
19 struct AlbedoDetail {
20 1 bool enabled = true; ///< Whether detail is added.
21 1 std::uint32_t seed = 0; ///< Noise seed.
22 1 int octaves = 4; ///< Octaves of detail; 1 to 16.
23 1 double scale = 1.0; ///< Multiplies the RMS of every octave; 0 adds none.
24 /// The Hurst exponent to use instead of the measured one, in [0, 1].
25 1 std::optional<double> hurst;
26 1 ResolutionFade fade{}; ///< How octaves too fine for the sample spacing fade out.
27
28
6/12
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 time.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 time.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 time.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 time.
✗ Branch 12 not taken.
✓ Branch 13 taken 1 time.
1 bool operator==(const AlbedoDetail&) const = default;
29 };
30
31 /// Checks albedo detail settings.
32 /// @throws std::invalid_argument for octaves outside 1 to 16, a negative or non-finite scale, a
33 /// Hurst exponent outside [0, 1], or an invalid fade.
34 void ValidateAlbedoDetail(const AlbedoDetail& detail);
35
36 /// How a `RasterAlbedo` interpolates its map and adds detail.
37 struct RasterAlbedoOptions {
38 1 ResampleMethod method = ResampleMethod::Cubic; ///< Interpolation of the map.
39 1 AlbedoDetail detail{}; ///< Sub-cell detail.
40
41
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 time.
1 bool operator==(const RasterAlbedoOptions&) const = default;
42 };
43
44 /// The logarithm of the mean of a map's bands at each cell, row-major; NaN where a band has no
45 /// data or is not positive.
46 std::vector<double> LogBrightnessGrid(const std::vector<Raster<float>>& bands);
47
48 /// The structure function of a row-major grid at a lag of `lag` cells: the mean squared
49 /// difference of the values a lag apart along rows and columns, skipping non-finite values.
50 /// Empty when no pair was found or every pair is equal.
51 std::optional<double> StructureFunction(const std::vector<double>& values, std::size_t width,
52 std::size_t height, std::size_t lag);
53
54 /// The least-squares slope of a line through points.
55 /// @param x The abscissae; at least two, not all equal.
56 /// @param y The ordinates, one per abscissa.
57 double FitSlope(const std::vector<double>& x, const std::vector<double>& y);
58
59 /// An albedo map, such as a normal albedo mosaic from orbit, upscaled to the grid:
60 /// interpolated with `method` (`SampleRaster`), then given sub-cell detail (`AlbedoDetail`).
61 /// Outside the map, or where it has no data, the albedo is NaN.
62 class RasterAlbedo final : public AlbedoSource {
63 public:
64 /// Builds the albedo and measures the map's roughness.
65 ///
66 /// On a sphere (`surface`) the map is in longitude and latitude, its cell size is its latitude
67 /// step in metres, and the detail is 3D Perlin noise at each point's 3D position.
68 /// @param bands 1 or 3 rasters on one grid.
69 /// @throws std::invalid_argument for another band count, empty, rotated or mismatched rasters,
70 /// or invalid options.
71 RasterAlbedo(std::vector<Raster<float>> bands, RasterAlbedoOptions options = {},
72 Surface surface = {});
73
74 /// 1 or 3 bands, as the map has.
75 12 std::size_t Bands() const override {
76 12 return bands_.size();
77 }
78
79 /// The map interpolated at world (`x`, `y`) (longitude and latitude on a sphere), with detail
80 /// resolved at `context.spacing`; NaN outside the map or where it has no data.
81 AlbedoSample ValueAt(double x, double y, const AlbedoContext& context) const override;
82
83 /// The Hurst exponent the detail uses: `detail.hurst`, or the one measured.
84 12 double Hurst() const {
85 12 return hurst_;
86 }
87
88 /// The map's roughness at one cell, sqrt(D(c) / 2) of the logarithm of the brightness; 0 when
89 /// the map is too small or too uniform to measure.
90 5 double CellRoughness() const {
91 5 return roughness_;
92 }
93
94 /// Interpolation and detail.
95 const RasterAlbedoOptions& Options() const {
96 return options_;
97 }
98
99 private:
100 /// Measures `roughness_` and `hurst_` from the map.
101 void MeasureRoughness();
102 /// The sum of the detail octaves at (`x`, `y`) resolved at `spacing`.
103 double DetailSum(double x, double y, double spacing) const;
104
105 std::vector<Raster<float>> bands_;
106 RasterAlbedoOptions options_;
107 Surface surface_;
108 double cell_ = 0.0;
109 double hurst_ = 0.5;
110 double roughness_ = 0.0;
111 };
112
113 } // namespace terraingen
114