TerrainGen coverage


terraingen/
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
6 / 6
100.0%
Branches:
-
-%
Functions:
3 / 3
100.0%

layers/region.h
Line Branch Exec Source
1 /// @file
2 /// @brief `RegionLayer`, another layer applied only inside a rectangle or circle.
3 #pragma once
4
5 #include "terraingen/layers/boulders/boulder_placer.h"
6 #include "terraingen/layers/craters/crater_placer.h"
7 #include "terraingen/layers/fade.h"
8 #include "terraingen/layers/layer.h"
9 #include "terraingen/raster/cell_loops.h"
10 #include "terraingen/raster/grid.h"
11 #include "terraingen/util/geometry.h"
12
13 #include <memory>
14 #include <optional>
15
16 namespace terraingen {
17
18 /// An area of the surface: a rectangle or a circle.
19 struct RegionShape {
20 /// Which shape the region is.
21 enum class Kind { Rectangle, Circle };
22
23 Kind kind = Kind::Rectangle; ///< Which of the fields below apply.
24 Bounds2d rectangle{}; ///< For `Rectangle`; a longitude-latitude box on a sphere.
25 Vec2d centre{}; ///< For `Circle`; longitude and latitude on a sphere.
26 double radius = 0.0; ///< For `Circle`, in metres.
27
28 /// A rectangular region of `bounds` (surface coordinates).
29 26 static RegionShape Rectangle(const Bounds2d& bounds) {
30 26 return {Kind::Rectangle, bounds, {}, 0.0};
31 }
32 /// A circular region around `centre` (surface coordinates).
33 /// @param radius In metres.
34 25 static RegionShape Circle(Vec2d centre, double radius) {
35 25 return {Kind::Circle, {}, centre, radius};
36 }
37
38 /// How far surface (x, y) lies outside the shape, in metres; 0 inside.
39 ///
40 /// On a sphere a rectangle's distance is measured in the point's local frame, east shortened
41 /// by the cosine of latitude, an approximation for feathers small against the body.
42 double DistanceOutside(double x, double y, const Surface& surface = {}) const;
43
44 /// The smallest box holding the shape, in `surface`'s coordinates.
45 Bounds2d Bounds(const Surface& surface = {}) const;
46
47 bool operator==(const RegionShape&) const = default;
48 };
49
50 /// Checks a region shape.
51 /// @throws std::invalid_argument for a shape that is not finite, a rectangle with a min above its
52 /// max, or a circle with a negative radius.
53 void ValidateRegionShape(const RegionShape& shape);
54
55 /// Another layer applied only inside a region, blended back to the unchanged height over
56 /// `feather` metres outside it.
57 ///
58 /// The inner layer sees the same context and, on grids, is applied only to the cells near the
59 /// region. Of its features, those centred within the region or its feather (`Holds`) belong to it.
60 class RegionLayer final : public Layer, public CraterPlacer, public BoulderPlacer {
61 public:
62 /// @param feather Width of the blend outside the region, in metres; non-negative.
63 /// @throws std::invalid_argument for a null `inner`, an invalid `shape`, or a negative or
64 /// non-finite `feather`.
65 RegionLayer(std::shared_ptr<const Layer> inner, RegionShape shape, double feather = 0.0,
66 BlendShape blend = BlendShape::Smoothstep, Surface surface = {});
67
68 /// The inner layer's weight at surface (x, y): 1 inside the shape, 0 from `feather` outside
69 /// it, the blend between.
70 double Weight(double x, double y) const;
71
72 /// The confined layer.
73 2 const Layer& Inner() const {
74 2 return *inner_;
75 }
76
77 /// Whether a feature centred at (x, y) belongs to the region: within it or its feather.
78 bool Holds(double x, double y) const;
79
80 /// The part of `grid` the inner layer is applied to, the cells near the region; nothing when no
81 /// cell is.
82 std::optional<RasterGrid> InnerGrid(const RasterGrid& grid) const;
83
84 /// The inner layer's craters over its part of `grid` that the region `Holds`; none when the
85 /// inner layer places no craters.
86 CraterFeatures CratersOver(const RasterGrid& grid, double spacing) const override;
87
88 /// The inner layer's boulders over its part of `grid` that the region `Holds`; none when the
89 /// inner layer places no boulders.
90 BoulderFeatures BouldersOver(const RasterGrid& grid, double spacing,
91 const Ground* ground) const override;
92
93 protected:
94 /// Applies the inner layer to the samples near the region and blends it in by `Weight`.
95 void ApplySamples(SampleBlock& samples, const LayerContext& context) const override;
96
97 private:
98 void ApplyToGrid(Raster<float>& heights, const LayerContext& context) const;
99 void ApplyToPoints(SampleBlock& samples, const LayerContext& context) const;
100 PixelWindow InnerWindow(const RasterGrid& grid) const;
101
102 std::shared_ptr<const Layer> inner_;
103 RegionShape shape_;
104 double feather_;
105 BlendShape blend_;
106 Surface surface_;
107 };
108
109 } // namespace terraingen
110