layers/strata.h
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /// @file | ||
| 2 | /// @brief `StrataLayer`, layered rock: the ground beneath terraced into benches and cliffs. | ||
| 3 | #pragma once | ||
| 4 | |||
| 5 | #include "terraingen/layers/layer.h" | ||
| 6 | #include "terraingen/layers/material.h" | ||
| 7 | #include "terraingen/util/geometry.h" | ||
| 8 | |||
| 9 | #include <cstdint> | ||
| 10 | |||
| 11 | namespace terraingen { | ||
| 12 | |||
| 13 | /// The beds a `StrataLayer` cuts. Lengths are in metres, angles in radians. | ||
| 14 | struct StrataOptions { | ||
| 15 | 4 | double bedThickness = 2.0; ///< Mean thickness of a bed. | |
| 16 | /// How far each bed boundary strays, in bed thicknesses, in [0, 1). | ||
| 17 | 4 | double thicknessVariation = 0.4; | |
| 18 | 4 | double dip = 0.0; ///< Dip of the beds from horizontal, below 90 deg. | |
| 19 | /// Direction the beds dip toward, radians counter-clockwise from +x (local east on a body). | ||
| 20 | 4 | double dipAzimuth = 0.0; | |
| 21 | /// How sharply each bed is cut into a flat bench and a cliff, at least 1: 1 leaves the ground | ||
| 22 | /// as it is, larger values flatten the benches and steepen the cliffs. | ||
| 23 | 4 | double sharpness = 4.0; | |
| 24 | 4 | double strength = 1.0; ///< Share of the terracing applied, in [0, 1]. | |
| 25 | /// Share of a bed's height, at its top, that counts as the cliff (bedrock) in the material map, | ||
| 26 | /// in (0, 1]. | ||
| 27 | 4 | double cliffShare = 0.3; | |
| 28 | 4 | std::uint32_t seed = 1; ///< Varies the bed boundaries. | |
| 29 | /// On a body, the surface point whose tangent frame the dip is measured in. | ||
| 30 | 4 | Vec2d anchor{}; | |
| 31 | /// Share of the beds that are hard, resistant rock, in [0, 1]: a hard bed is cut at | ||
| 32 | /// `sharpness` into a bench and a cliff and lays bedrock there, a soft one at `softSharpness` | ||
| 33 | /// into a slope without bedrock. Each bed is drawn hard or soft by the seed. | ||
| 34 | 4 | double hardShare = 1.0; | |
| 35 | 4 | double softSharpness = 1.0; ///< How sharply soft beds are cut, at least 1. | |
| 36 | |||
| 37 | 4 | bool operator==(const StrataOptions&) const = default; | |
| 38 | }; | ||
| 39 | |||
| 40 | /// Checks strata options. | ||
| 41 | /// @throws std::invalid_argument for a bed thickness that is not positive and finite, a thickness | ||
| 42 | /// variation outside [0, 1), a dip outside [0, 90) deg, a sharpness or soft sharpness below 1, a | ||
| 43 | /// strength or hard share outside [0, 1], a cliff share outside (0, 1], or a non-finite azimuth or | ||
| 44 | /// anchor. | ||
| 45 | void ValidateStrataOptions(const StrataOptions& options); | ||
| 46 | |||
| 47 | /// Layered rock: the ground beneath terraced into beds, each a flat bench below a cliff at its | ||
| 48 | /// top, so hills become stepped buttes and mesas. | ||
| 49 | /// | ||
| 50 | /// A point's stratigraphic level is its height less the dipping bed plane; within its bed it is | ||
| 51 | /// remapped by u^sharpness (u its height through the bed), which keeps the bed's top and bottom in | ||
| 52 | /// place, so the surface stays continuous. A function of the height beneath and position only, so | ||
| 53 | /// grids, tiles and points agree; it lays bedrock over the material map on the cliffs. | ||
| 54 | class StrataLayer final : public FormulaLayer, public MaterialSource { | ||
| 55 | public: | ||
| 56 | /// On a body, the dip is measured in the tangent frame of `options.anchor`. | ||
| 57 | /// @throws std::invalid_argument as `ValidateStrataOptions`. | ||
| 58 | explicit StrataLayer(StrataOptions options, Surface surface = {}); | ||
| 59 | |||
| 60 | /// The terraced height of ground `height` metres high at world (x, y) (m). | ||
| 61 | double TerracedAt(double height, double x, double y) const; | ||
| 62 | |||
| 63 | /// How far through its bed ground `height` metres high at world (x, y) lies, in [0, 1). | ||
| 64 | double BedPositionAt(double height, double x, double y) const; | ||
| 65 | |||
| 66 | /// The options the layer was made with. | ||
| 67 | ✗ | const StrataOptions& Options() const { | |
| 68 | ✗ | return options_; | |
| 69 | } | ||
| 70 | |||
| 71 | 3 | MaterialClass Material() const override { | |
| 72 | 3 | return MaterialClass::Bedrock; | |
| 73 | } | ||
| 74 | /// 1 on the cliffs of hard beds, the top `cliffShare` of each, fading to 0 on the benches; 0 on | ||
| 75 | /// soft beds. | ||
| 76 | /// @throws std::invalid_argument without `ground`. | ||
| 77 | double MaterialCoverAt(double x, double y, double spacing, const Ground* ground) const override; | ||
| 78 | |||
| 79 | protected: | ||
| 80 | float HeightAt(float height, double x, double y, double spacing, | ||
| 81 | const Ground* ground) const override; | ||
| 82 | |||
| 83 | private: | ||
| 84 | /// The bed holding stratigraphic level `level`: its bottom and top levels. | ||
| 85 | struct Bed { | ||
| 86 | double bottom = 0.0; | ||
| 87 | double top = 0.0; | ||
| 88 | bool hard = true; | ||
| 89 | }; | ||
| 90 | Bed BedOf(double level) const; | ||
| 91 | double BoundaryOf(std::int64_t k) const; | ||
| 92 | /// The stratigraphic level of ground `height` metres high at (x, y): its height less the | ||
| 93 | /// dipping bed plane. False on the far hemisphere of a body, where the layer does nothing. | ||
| 94 | bool LevelOf(double height, double x, double y, double& level) const; | ||
| 95 | |||
| 96 | StrataOptions options_; | ||
| 97 | Vec2d dipDirection_{1.0, 0.0}; | ||
| 98 | double dipSlope_ = 0.0; | ||
| 99 | Vec3d anchorDirection_{}; | ||
| 100 | }; | ||
| 101 | |||
| 102 | } // namespace terraingen | ||
| 103 |