distribution/sp8023.cpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "terraingen/distribution/sp8023.h" | ||
| 2 | |||
| 3 | #include <array> | ||
| 4 | #include <cmath> | ||
| 5 | #include <span> | ||
| 6 | #include <stdexcept> | ||
| 7 | #include <utility> | ||
| 8 | #include <vector> | ||
| 9 | |||
| 10 | namespace terraingen { | ||
| 11 | |||
| 12 | namespace { | ||
| 13 | |||
| 14 | /// A point of a digitized curve: log10 of the diameter in metres and of N per m^2. | ||
| 15 | struct LogPoint { | ||
| 16 | double logDiameter; | ||
| 17 | double logCumulative; | ||
| 18 | }; | ||
| 19 | |||
| 20 | constexpr std::array<LogPoint, 4> kIntercraterFine{ | ||
| 21 | {{-4.5, 7.885}, {-3.839, 6.154}, {-3.194, 4.416}, {-2.749, 3.304}}}; | ||
| 22 | constexpr std::array<LogPoint, 11> kIntercraterMaximum{{{-2.293, 2.489}, | ||
| 23 | {-1.844, 1.713}, | ||
| 24 | {-1.409, 0.951}, | ||
| 25 | {-0.973, 0.164}, | ||
| 26 | {-0.744, -0.230}, | ||
| 27 | {-0.515, -0.819}, | ||
| 28 | {-0.286, -1.489}, | ||
| 29 | {-0.057, -2.153}, | ||
| 30 | {0.358, -3.469}, | ||
| 31 | {0.768, -4.777}, | ||
| 32 | {0.973, -5.426}}}; | ||
| 33 | constexpr std::array<LogPoint, 12> kIntercraterNominal{{{-2.293, 2.136}, | ||
| 34 | {-1.844, 1.220}, | ||
| 35 | {-1.409, 0.287}, | ||
| 36 | {-0.973, -0.615}, | ||
| 37 | {-0.744, -1.063}, | ||
| 38 | {-0.515, -1.515}, | ||
| 39 | {-0.286, -1.933}, | ||
| 40 | {-0.057, -2.455}, | ||
| 41 | {0.154, -3.184}, | ||
| 42 | {0.358, -3.769}, | ||
| 43 | {0.563, -4.481}, | ||
| 44 | {0.768, -5.196}}}; | ||
| 45 | constexpr std::array<LogPoint, 10> kIntercraterMinimum{{{-2.293, 2.136}, | ||
| 46 | {-1.844, 1.078}, | ||
| 47 | {-1.409, -0.044}, | ||
| 48 | {-0.973, -1.174}, | ||
| 49 | {-0.286, -2.825}, | ||
| 50 | {-0.057, -3.397}, | ||
| 51 | {0.154, -3.874}, | ||
| 52 | {0.358, -4.447}, | ||
| 53 | {0.563, -5.052}, | ||
| 54 | {0.768, -5.522}}}; | ||
| 55 | constexpr std::array<LogPoint, 11> kCraterMaximum{{{0.152, -2.022}, | ||
| 56 | {0.286, -2.299}, | ||
| 57 | {0.419, -2.608}, | ||
| 58 | {0.552, -2.927}, | ||
| 59 | {0.686, -3.271}, | ||
| 60 | {0.819, -3.651}, | ||
| 61 | {0.952, -4.093}, | ||
| 62 | {1.082, -4.608}, | ||
| 63 | {1.211, -5.170}, | ||
| 64 | {1.339, -5.748}, | ||
| 65 | {1.382, -5.940}}}; | ||
| 66 | constexpr std::array<LogPoint, 11> kCraterNominal{{{-0.071, -2.282}, | ||
| 67 | {0.063, -2.574}, | ||
| 68 | {0.197, -2.887}, | ||
| 69 | {0.330, -3.239}, | ||
| 70 | {0.463, -3.603}, | ||
| 71 | {0.597, -4.028}, | ||
| 72 | {0.730, -4.436}, | ||
| 73 | {0.863, -4.841}, | ||
| 74 | {0.997, -5.190}, | ||
| 75 | {1.125, -5.572}, | ||
| 76 | {1.254, -5.935}}}; | ||
| 77 | constexpr std::array<LogPoint, 8> kCraterMinimum{{{-0.071, -2.606}, | ||
| 78 | {0.063, -3.050}, | ||
| 79 | {0.197, -3.547}, | ||
| 80 | {0.330, -3.998}, | ||
| 81 | {0.463, -4.497}, | ||
| 82 | {0.597, -4.968}, | ||
| 83 | {0.730, -5.422}, | ||
| 84 | {0.863, -5.889}}}; | ||
| 85 | |||
| 86 | /// The table through the points of `first` then `second`, converted from log10. | ||
| 87 | 41 | std::shared_ptr<TabulatedSfd> Table(std::span<const LogPoint> first, | |
| 88 | std::span<const LogPoint> second = {}) { | ||
| 89 | 41 | std::vector<double> diameters; | |
| 90 | 41 | std::vector<double> cumulative; | |
| 91 | 123 | for (const auto points : {first, second}) { | |
| 92 | 604 | for (const LogPoint& point : points) { | |
| 93 | 522 | diameters.push_back(std::pow(10.0, point.logDiameter)); | |
| 94 | 522 | cumulative.push_back(std::pow(10.0, point.logCumulative)); | |
| 95 | } | ||
| 96 | } | ||
| 97 | 82 | return std::make_shared<TabulatedSfd>(std::move(diameters), std::move(cumulative)); | |
| 98 | 41 | } | |
| 99 | |||
| 100 | } // namespace | ||
| 101 | |||
| 102 | 19 | std::shared_ptr<TabulatedSfd> Sp8023IntercraterBlocks(SpecificationCurve curve) { | |
| 103 | 19 | switch (curve) { | |
| 104 | 2 | case SpecificationCurve::Minimum: | |
| 105 | 2 | return Table(kIntercraterFine, kIntercraterMinimum); | |
| 106 | 7 | case SpecificationCurve::Nominal: | |
| 107 | 7 | return Table(kIntercraterFine, kIntercraterNominal); | |
| 108 | 9 | case SpecificationCurve::Maximum: | |
| 109 | 9 | return Table(kIntercraterFine, kIntercraterMaximum); | |
| 110 | } | ||
| 111 | 1 | throw std::invalid_argument("Unknown specification curve"); | |
| 112 | } | ||
| 113 | |||
| 114 | 24 | std::shared_ptr<TabulatedSfd> Sp8023CraterBlocks(SpecificationCurve curve) { | |
| 115 | 24 | switch (curve) { | |
| 116 | 2 | case SpecificationCurve::Minimum: | |
| 117 | 2 | return Table(kCraterMinimum); | |
| 118 | 19 | case SpecificationCurve::Nominal: | |
| 119 | 19 | return Table(kCraterNominal); | |
| 120 | 2 | case SpecificationCurve::Maximum: | |
| 121 | 2 | return Table(kCraterMaximum); | |
| 122 | } | ||
| 123 | 1 | throw std::invalid_argument("Unknown specification curve"); | |
| 124 | } | ||
| 125 | |||
| 126 | } // namespace terraingen | ||
| 127 |