TerrainGen coverage


terraingen/
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
13 / 13
100.0%
Branches:
6 / 12
50.0%
Functions:
4 / 4, 1 excl
100.0%

sources/geotiff_source.h
Line Branch Exec Source
1 /// @file
2 /// @brief Heights read from a band of a GeoTIFF DEM.
3 #pragma once
4
5 #include "terraingen/raster/geotiff/geotiff.h"
6 #include "terraingen/raster/resample.h"
7 #include "terraingen/sources/source.h"
8
9 #include <cstddef>
10 #include <filesystem>
11 #include <memory>
12 #include <mutex>
13 #include <optional>
14
15 namespace terraingen {
16
17 /// How a `GeoTiffSource` reads its band.
18 struct GeoTiffSourceOptions {
19 6 std::size_t band = 0; ///< Zero-based band index.
20 /// Cell size to resample to, in CRS units; unset keeps the file's cells.
21 6 std::optional<double> pixelSize{};
22 /// Interpolation for resampling and for cells off the source's lattice.
23 6 ResampleMethod resampling = ResampleMethod::Cubic;
24 6 std::optional<double> scale{}; ///< Replaces the band's scale when set; finite.
25 6 std::optional<double> offset{}; ///< Replaces the band's offset when set; finite.
26 /// Standard deviation in metres of a Gaussian low-pass applied to the file's heights once,
27 /// before any resampling: the low frequencies of a DEM to add finer synthetic detail to
28 /// (`DetailLayer` can add the removed detail back). 0 keeps every frequency.
29 6 double lowPass = 0.0;
30
31
6/12
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 6 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 6 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 6 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 6 times.
6 bool operator==(const GeoTiffSourceOptions&) const = default;
32 };
33
34 /// Heights from one band of a GeoTIFF in a projected CRS, optionally resampled to square
35 /// cells of `pixelSize` over the file's extent.
36 ///
37 /// The file is read on first use and kept. On the source's own lattice `Fill` copies cells exactly;
38 /// on any other grid each cell is the file interpolated at its centre with `resampling`. Cells
39 /// beyond the file are no-data. Samples are scaled with the band's scale and offset, which `scale`
40 /// and `offset` replace; when that changes the samples, cells without data become NaN.
41 class GeoTiffSource final : public Source {
42 public:
43 /// Reads the file's header.
44 /// @throws GeoTiffError if the file cannot be read.
45 /// @throws std::invalid_argument for a missing band, a geographic CRS (craters are sized in
46 /// metres), a non-positive `pixelSize`, a rotated raster that would need resampling, a
47 /// `scale` or `offset` that is not finite, or a negative or non-finite
48 /// `lowPass`.
49 explicit GeoTiffSource(std::filesystem::path path, GeoTiffSourceOptions options = {});
50
51 /// The file's grid, resampled to `pixelSize` when set.
52 36 RasterGrid Grid() const override {
53 36 return grid_;
54 }
55
56 /// The top-left corner of the grid, in CRS units.
57 Vec2d ReferencePoint() const override;
58
59 /// Copies cells on the source's lattice, otherwise samples the file at cell centres.
60 /// @throws std::invalid_argument for a rotated grid off the source's lattice.
61 /// @throws GeoTiffError if the file cannot be read.
62 void Fill(Raster<float>& heights) const override;
63
64 /// The height in metres of the source cell centred at CRS (`x`, `y`) when there is one,
65 /// otherwise of the file interpolated there with `resampling` (`SampleRaster`); NaN beyond
66 /// the file and where it has no data.
67 /// @throws GeoTiffError if the file cannot be read.
68 float HeightAt(double x, double y) const override;
69
70 /// The file's projection.
71 12 GeoKeys Keys() const override {
72 12 return info_.geoKeys;
73 }
74
75 /// The scale and offset the samples are read with.
76 5 const BandScaling& Scaling() const {
77 5 return scaling_;
78 }
79
80 private:
81 /// Where a grid on the source's lattice starts, in source cells.
82 struct LatticeOffset {
83 long long col = 0;
84 long long row = 0;
85 };
86
87 /// The offset of a grid with transform `target` when it lies on the source's lattice.
88 std::optional<LatticeOffset> OffsetOnLattice(const GeoTransform& target) const;
89 /// Copies the source cells under `heights`, which starts at `offset`.
90 void CopyFromLattice(Raster<float>& heights, LatticeOffset offset) const;
91 /// Sets each cell of `heights` to `HeightAt` its centre.
92 void FillBySampling(Raster<float>& heights) const;
93 /// Reads the file once, low-passes and resamples it as the options say.
94 void Load() const;
95 const Raster<float>& Heights() const;
96 const Raster<float>& Native() const;
97
98 std::filesystem::path path_;
99 GeoTiffSourceOptions options_;
100 GeoTiffInfo info_;
101 BandScaling scaling_;
102 RasterGrid grid_;
103 mutable std::once_flag loaded_;
104 mutable std::shared_ptr<const Raster<float>> native_;
105 mutable std::shared_ptr<const Raster<float>> heights_;
106 };
107
108 } // namespace terraingen
109