TerrainGen coverage


terraingen/
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
65 / 65
100.0%
Branches:
31 / 33
93.9%
Functions:
8 / 8
100.0%

raster/grid.cpp
Line Branch Exec Source
1 #include "terraingen/raster/grid.h"
2
3 #include "terraingen/util/checks.h"
4
5 #include <algorithm>
6 #include <cmath>
7 #include <limits>
8 #include <stdexcept>
9
10 namespace terraingen {
11
12 883 Bounds2d RasterGrid::Bounds() const {
13 883 constexpr double kInf = std::numeric_limits<double>::infinity();
14 883 Bounds2d bounds{kInf, kInf, -kInf, -kInf};
15
2/2
✓ Branch 2 taken 1766 times.
✓ Branch 3 taken 883 times.
2649 for (const double col : {0.0, static_cast<double>(width)}) {
16
2/2
✓ Branch 2 taken 3532 times.
✓ Branch 3 taken 1766 times.
5298 for (const double row : {0.0, static_cast<double>(height)}) {
17 3532 const Vec2d corner = transform.PixelToWorld(col, row);
18 3532 bounds.minX = std::fmin(bounds.minX, corner.x);
19 3532 bounds.minY = std::fmin(bounds.minY, corner.y);
20 3532 bounds.maxX = std::fmax(bounds.maxX, corner.x);
21 3532 bounds.maxY = std::fmax(bounds.maxY, corner.y);
22 }
23 }
24 883 return bounds;
25 }
26
27 410 double RasterGrid::Area() const {
28 410 return static_cast<double>(width) * static_cast<double>(height) * PixelSize() * PixelSize();
29 }
30
31 4703 double RasterGrid::PixelSize() const {
32 4703 return std::sqrt(std::fabs(transform.pixelWidth * transform.pixelHeight -
33 4703 transform.rowRotation * transform.colRotation));
34 }
35
36 1261 Raster<float> RasterGrid::MakeRaster(float fill) const {
37 1261 Raster<float> raster(width, height, fill);
38 1261 raster.SetTransform(transform);
39 1261 return raster;
40 }
41
42 3906 double RasterGrid::Spacing(const Surface& surface) const {
43
2/2
✓ Branch 1 taken 3426 times.
✓ Branch 2 taken 480 times.
3906 if (!surface.IsBody()) {
44 3426 return PixelSize();
45 }
46 480 return std::hypot(transform.rowRotation, transform.pixelHeight) * surface.UnitLength();
47 }
48
49 40 RasterGrid ResampledGrid(const RasterGrid& grid, double pixelSize) {
50
1/1
✓ Branch 2 taken 36 times.
40 RequirePositive(pixelSize, "Pixel size");
51 36 const GeoTransform& source = grid.transform;
52
3/4
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 33 times.
36 if (source.rowRotation != 0.0 || source.colRotation != 0.0) {
53
1/1
✓ Branch 2 taken 3 times.
3 throw std::invalid_argument("Cannot resample a rotated raster");
54 }
55 33 const double scaleX = std::fabs(source.pixelWidth) / pixelSize;
56 33 const double scaleY = std::fabs(source.pixelHeight) / pixelSize;
57 33 const double width = std::max(1.0, std::round(static_cast<double>(grid.width) * scaleX));
58 33 const double height = std::max(1.0, std::round(static_cast<double>(grid.height) * scaleY));
59
3/4
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 31 times.
33 if (width > 2147483647.0 || height > 2147483647.0) {
60
1/1
✓ Branch 2 taken 2 times.
2 throw std::invalid_argument("Resampled raster would be too large");
61 }
62 31 RasterGrid resampled{static_cast<std::size_t>(width), static_cast<std::size_t>(height), source};
63 31 resampled.transform.pixelWidth = std::copysign(pixelSize, source.pixelWidth);
64 31 resampled.transform.pixelHeight = std::copysign(pixelSize, source.pixelHeight);
65 31 return resampled;
66 }
67
68 450 double ResolvedSpacing(const Raster<float>& raster, double spacing, const Surface& surface) {
69
1/1
✓ Branch 1 taken 450 times.
450 const RasterGrid grid = RasterGrid::FromRaster(raster);
70
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 448 times.
450 if (!(grid.PixelSize() > 0.0)) {
71
1/1
✓ Branch 2 taken 2 times.
2 throw std::domain_error("The raster's transform is not invertible");
72 }
73 448 return std::max(spacing, grid.Spacing(surface));
74 }
75
76 453 double RasterGrid::SurfaceArea(const Surface& surface) const {
77
2/2
✓ Branch 1 taken 406 times.
✓ Branch 2 taken 47 times.
453 if (!surface.IsBody()) {
78
1/1
✓ Branch 1 taken 406 times.
406 return Area();
79 }
80 47 const Bounds2d box = Bounds();
81 47 const double turn = std::fmin(box.maxX - box.minX, 360.0) * kDegree;
82 47 const double south = std::fmax(box.minY, -90.0) * kDegree;
83 47 const double north = std::fmin(box.maxY, 90.0) * kDegree;
84
2/2
✓ Branch 1 taken 44 times.
✓ Branch 2 taken 3 times.
47 if (surface.IsSphere()) {
85 44 const double radius = surface.Radius();
86 44 return radius * radius * turn * std::fmax(0.0, std::sin(north) - std::sin(south));
87 }
88
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 2 times.
3 if (!(north > south)) {
89 1 return 0.0;
90 }
91 2 constexpr int kSteps = 64;
92 2 const double west = box.minX * kDegree;
93 2 double area = 0.0;
94
2/2
✓ Branch 0 taken 128 times.
✓ Branch 1 taken 2 times.
130 for (int j = 0; j < kSteps; ++j) {
95 128 const double lat = south + (north - south) * (j + 0.5) / kSteps;
96
2/2
✓ Branch 0 taken 8192 times.
✓ Branch 1 taken 128 times.
8320 for (int i = 0; i < kSteps; ++i) {
97 8192 const double lon = west + turn * (i + 0.5) / kSteps;
98
1/1
✓ Branch 1 taken 8192 times.
8192 area += surface.AreaPerSteradian({lon / kDegree, lat / kDegree}) * std::cos(lat);
99 }
100 }
101 2 return area * turn * (north - south) / (kSteps * kSteps);
102 }
103
104 } // namespace terraingen
105