layers/sand_fill.h
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /// @file | ||
| 2 | /// @brief `SandFillLayer`, sand pooled in the lows of the ground beneath it. | ||
| 3 | #pragma once | ||
| 4 | |||
| 5 | #include "terraingen/layers/layer.h" | ||
| 6 | #include "terraingen/layers/material.h" | ||
| 7 | |||
| 8 | namespace terraingen { | ||
| 9 | |||
| 10 | /// How much sand a `SandFillLayer` pools, and where. | ||
| 11 | struct SandFillOptions { | ||
| 12 | 2 | double reach = 10.0; ///< Radius in metres of the surroundings a low is measured against. | |
| 13 | /// Share, in [0, 1], of a low's depth below its surroundings that sand fills. | ||
| 14 | 2 | double fill = 0.6; | |
| 15 | 2 | double maxThickness = 0.5; ///< The thickest the sand gets, approached smoothly (m). | |
| 16 | /// Sand thickness in metres at which it fully covers the ground; thinner sand covers part. | ||
| 17 | 2 | double coverThickness = 0.02; | |
| 18 | |||
| 19 | 2 | bool operator==(const SandFillOptions&) const = default; | |
| 20 | }; | ||
| 21 | |||
| 22 | /// Checks sand fill options. | ||
| 23 | /// @throws std::invalid_argument for a reach, maximum or cover thickness that is not positive and | ||
| 24 | /// finite, or a fill outside [0, 1]. | ||
| 25 | void ValidateSandFillOptions(const SandFillOptions& options); | ||
| 26 | |||
| 27 | /// Sand pooled in the lows of the ground beneath it: cracks, troughs and hollows between rises. | ||
| 28 | /// | ||
| 29 | /// A point's surroundings are the mean ground height on two rings, at half the reach and at the | ||
| 30 | /// reach; where the point lies below them, sand fills `fill` of the depth, thickening smoothly to | ||
| 31 | /// at most `maxThickness`. Reads the ground beneath it at points, so grids, tiles and points | ||
| 32 | /// agree; it lays sand over the material map. | ||
| 33 | class SandFillLayer final : public FormulaLayer, public MaterialSource { | ||
| 34 | public: | ||
| 35 | /// On a body, the rings lie in each point's local frame. | ||
| 36 | /// @throws std::invalid_argument as `ValidateSandFillOptions`. | ||
| 37 | explicit SandFillLayer(SandFillOptions options = {}, Surface surface = {}); | ||
| 38 | |||
| 39 | /// The sand thickness at world (x, y) over `ground`, in metres. | ||
| 40 | /// @param spacing Sample spacing in metres the ground is read at. | ||
| 41 | double ThicknessAt(const Ground& ground, double x, double y, double spacing) const; | ||
| 42 | |||
| 43 | /// The options the layer was made with. | ||
| 44 | ✗ | const SandFillOptions& Options() const { | |
| 45 | ✗ | return options_; | |
| 46 | } | ||
| 47 | |||
| 48 | 10 | MaterialClass Material() const override { | |
| 49 | 10 | return MaterialClass::Sand; | |
| 50 | } | ||
| 51 | /// @throws std::invalid_argument without `ground`. | ||
| 52 | double MaterialCoverAt(double x, double y, double spacing, const Ground* ground) const override; | ||
| 53 | |||
| 54 | protected: | ||
| 55 | float HeightAt(float height, double x, double y, double spacing, | ||
| 56 | const Ground* ground) const override; | ||
| 57 | void CheckContext(const LayerContext& context) const override; | ||
| 58 | |||
| 59 | private: | ||
| 60 | double Thickness(const Ground& ground, double x, double y, double height, double spacing) const; | ||
| 61 | |||
| 62 | SandFillOptions options_; | ||
| 63 | }; | ||
| 64 | |||
| 65 | } // namespace terraingen | ||
| 66 |