layers/craters/crater_layer.h
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /// @file | ||
| 2 | /// @brief `CraterLayer`, craters generated over the grid being evaluated and applied to it. | ||
| 3 | #pragma once | ||
| 4 | |||
| 5 | #include "terraingen/distribution/size_frequency.h" | ||
| 6 | #include "terraingen/layers/craters/ages/age_model.h" | ||
| 7 | #include "terraingen/layers/craters/crater_placer.h" | ||
| 8 | #include "terraingen/layers/craters/degradation/degradation_model.h" | ||
| 9 | #include "terraingen/layers/craters/generation/cell_cache.h" | ||
| 10 | #include "terraingen/layers/craters/generation/population.h" | ||
| 11 | #include "terraingen/layers/craters/profiles/profile.h" | ||
| 12 | #include "terraingen/layers/craters/secondary_model.h" | ||
| 13 | #include "terraingen/layers/craters/shaping/apply.h" | ||
| 14 | #include "terraingen/layers/craters/shaping/attributes.h" | ||
| 15 | #include "terraingen/layers/density_map.h" | ||
| 16 | #include "terraingen/layers/layer.h" | ||
| 17 | |||
| 18 | #include <cstdint> | ||
| 19 | #include <limits> | ||
| 20 | #include <memory> | ||
| 21 | #include <optional> | ||
| 22 | #include <vector> | ||
| 23 | |||
| 24 | namespace terraingen { | ||
| 25 | |||
| 26 | /// The models a crater layer generates and shapes craters with. | ||
| 27 | struct CraterModels { | ||
| 28 | std::shared_ptr<const SizeFrequencyDistribution> density; ///< Craters per m^2 by diameter. | ||
| 29 | std::shared_ptr<const CraterAgeModel> ages; ///< Each crater's age. | ||
| 30 | std::shared_ptr<const DegradationModel> degradation; ///< Each crater's state. | ||
| 31 | std::shared_ptr<const CraterProfile> profile; ///< Height by distance. | ||
| 32 | |||
| 33 | /// The profile and degradation, the models that shape the craters. | ||
| 34 | 244606 | CraterShapeModels Shape() const { | |
| 35 | 978424 | return {profile, degradation}; | |
| 36 | 244606 | } | |
| 37 | }; | ||
| 38 | |||
| 39 | /// How a `CraterLayer` generates and applies its craters. | ||
| 40 | struct CraterLayerOptions { | ||
| 41 | /// Generate craters from the density; otherwise only the manual craters in `generation` apply. | ||
| 42 | bool generate = true; | ||
| 43 | std::uint32_t seed = 1; ///< Varies the generated craters. | ||
| 44 | /// Diameter range, spacing, manual craters and cap; `marginRadii` is set from the profile's | ||
| 45 | /// reach. | ||
| 46 | CraterGenerationOptions generation{.dMin = 4.0, .dMax = 250.0}; | ||
| 47 | CraterApplyOptions apply{}; ///< How the craters are shaped into the terrain. | ||
| 48 | /// Most craters to keep generated cells of (`CraterCellCache`); 0 regenerates cells every time. | ||
| 49 | std::size_t cacheCraters = 4000000; | ||
| 50 | /// What the craters lie on, copied into `generation.surface` and `apply.surface`. | ||
| 51 | Surface surface{}; | ||
| 52 | /// A map that sets the density point by point (`DensityMap`); unset keeps the density the | ||
| 53 | /// same everywhere. Manual craters are not thinned by it; with a catalog among them, set | ||
| 54 | /// `generation.completeness` so generated craters do not repeat it. | ||
| 55 | std::optional<DensityMap> densityMap{}; | ||
| 56 | /// The secondaries `SecondaryCraterLayer`s throw from these craters. A `total` count or areal | ||
| 57 | /// fraction map counts them too, so craters too small to throw secondaries the map measures | ||
| 58 | /// are drawn at the map less those secondaries' density there; larger craters, which throw | ||
| 59 | /// them, follow the map alone; with spacing they also take precedence over smaller craters, so | ||
| 60 | /// the throwers never depend on what they throw at. Not with `generation.maxCraters`. | ||
| 61 | std::vector<SecondaryCraterOptions> secondaries{}; | ||
| 62 | }; | ||
| 63 | |||
| 64 | /// Craters generated over the grid being evaluated (`GenerateCraters`) and applied to it | ||
| 65 | /// (`ApplyCraters`) at the evaluation's spacing. | ||
| 66 | /// | ||
| 67 | /// Generated craters are the same in a tile as in any larger grid, unless `maxCraters` caps them | ||
| 68 | /// over the whole grid; bands too small to resolve are not generated. | ||
| 69 | class CraterLayer final : public Layer, public CraterPlacer { | ||
| 70 | public: | ||
| 71 | /// @param models None may be null. | ||
| 72 | /// @throws std::invalid_argument for a missing model or invalid options. | ||
| 73 | CraterLayer(CraterModels models, CraterLayerOptions options); | ||
| 74 | |||
| 75 | /// `dMax` (the density's largest valid diameter when unbounded) or the largest manual crater, | ||
| 76 | /// in metres. | ||
| 77 | double MaxFeatureDiameter() const; | ||
| 78 | |||
| 79 | /// The craters this layer applies to a grid covering `region` (surface coordinates): generated | ||
| 80 | /// and manual ones centred in it or within the profile's reach of it. | ||
| 81 | /// @param spacing Sample spacing in metres; bands too small to resolve at it are skipped | ||
| 82 | /// (`CraterGenerationOptions::minResolvedDiameter`), 0 keeps every band. | ||
| 83 | /// @param minDiameter,maxDiameter Diameters (m) of the craters wanted: generated bands wholly | ||
| 84 | /// outside them may be skipped (`maxBandDiameter`), so craters outside them can still come | ||
| 85 | /// back. | ||
| 86 | CraterList Craters(const Bounds2d& region, double spacing = 0.0, double minDiameter = 0.0, | ||
| 87 | double maxDiameter = std::numeric_limits<double>::infinity()) const; | ||
| 88 | |||
| 89 | /// A crater's depth, rim height and freshness in the state the degradation model gives it. | ||
| 90 | /// @throws std::domain_error as `DegradationModel::State`. | ||
| 91 | CraterAttributes Attributes(const Crater& crater) const; | ||
| 92 | |||
| 93 | CraterFeatures CratersOver(const RasterGrid& grid, double spacing) const override; | ||
| 94 | |||
| 95 | /// The cell cache, or null when `cacheCraters` is 0. | ||
| 96 | 3 | const CraterCellCache* Cache() const { | |
| 97 | 3 | return cache_.get(); | |
| 98 | } | ||
| 99 | |||
| 100 | /// The models the layer was made with. | ||
| 101 | 193147 | const CraterModels& Models() const { | |
| 102 | 193147 | return models_; | |
| 103 | } | ||
| 104 | |||
| 105 | /// The options, with surfaces and `marginRadii` filled in. | ||
| 106 | 967959 | const CraterLayerOptions& Options() const { | |
| 107 | 967959 | return options_; | |
| 108 | } | ||
| 109 | |||
| 110 | protected: | ||
| 111 | /// Generates and applies the craters reaching the samples. Datums are fitted to | ||
| 112 | /// `context.ground` where given, otherwise to a grid's heights as passed in. | ||
| 113 | /// @throws std::invalid_argument for points when the layer has a datum and no | ||
| 114 | /// `context.ground`, or has `maxCraters` (which ranks craters over a whole grid). | ||
| 115 | /// @throws std::domain_error as `DegradationModel::State`. | ||
| 116 | void ApplySamples(SampleBlock& samples, const LayerContext& context) const override; | ||
| 117 | |||
| 118 | private: | ||
| 119 | /// The keep share for craters over `region`: the map's, less the secondaries thrown there | ||
| 120 | /// by the craters around it that are large enough, when they are taken out of the map. | ||
| 121 | CraterKeepShare KeepShare(const Bounds2d& region) const; | ||
| 122 | |||
| 123 | CraterModels models_; | ||
| 124 | CraterLayerOptions options_; | ||
| 125 | std::shared_ptr<const SurfaceCells> cells_; | ||
| 126 | std::shared_ptr<CraterCellCache> cache_; | ||
| 127 | /// The density craters are drawn at: `models_.density`, times the map's largest scale. | ||
| 128 | std::shared_ptr<const SizeFrequencyDistribution> candidates_; | ||
| 129 | std::shared_ptr<const DensityScale> scale_; | ||
| 130 | /// Craters at least this large (m) throw secondaries the map measures and follow it alone. | ||
| 131 | double throwFrom_ = std::numeric_limits<double>::infinity(); | ||
| 132 | }; | ||
| 133 | |||
| 134 | } // namespace terraingen | ||
| 135 |