rustial_engine/layers/
hillshade_layer.rs1use crate::layer::{Layer, LayerId};
8use std::any::Any;
9
10#[derive(Debug, Clone, Copy, PartialEq)]
12pub struct HillshadeParams {
13 pub opacity: f32,
15 pub highlight_color: [f32; 4],
17 pub shadow_color: [f32; 4],
19 pub accent_color: [f32; 4],
21 pub illumination_direction: f32,
23 pub illumination_altitude: f32,
25 pub exaggeration: f32,
27}
28
29impl Default for HillshadeParams {
30 fn default() -> Self {
31 Self {
32 opacity: 1.0,
33 highlight_color: [1.0, 1.0, 1.0, 1.0],
34 shadow_color: [0.0, 0.0, 0.0, 1.0],
35 accent_color: [0.42, 0.48, 0.42, 1.0],
36 illumination_direction: 335.0f32.to_radians(),
37 illumination_altitude: 45.0f32.to_radians(),
38 exaggeration: 1.0,
39 }
40 }
41}
42
43#[derive(Debug, Clone)]
49pub struct HillshadeLayer {
50 id: LayerId,
51 name: String,
52 visible: bool,
53 opacity: f32,
54 highlight_color: [f32; 4],
55 shadow_color: [f32; 4],
56 accent_color: [f32; 4],
57 illumination_direction_deg: f32,
58 illumination_altitude_deg: f32,
59 exaggeration: f32,
60}
61
62impl HillshadeLayer {
63 pub fn new(name: impl Into<String>) -> Self {
65 Self {
66 id: LayerId::next(),
67 name: name.into(),
68 visible: true,
69 opacity: 1.0,
70 highlight_color: [1.0, 1.0, 1.0, 1.0],
71 shadow_color: [0.0, 0.0, 0.0, 1.0],
72 accent_color: [0.42, 0.48, 0.42, 1.0],
73 illumination_direction_deg: 335.0,
74 illumination_altitude_deg: 45.0,
75 exaggeration: 1.0,
76 }
77 }
78
79 #[inline]
81 pub fn highlight_color(&self) -> [f32; 4] {
82 self.highlight_color
83 }
84
85 #[inline]
87 pub fn shadow_color(&self) -> [f32; 4] {
88 self.shadow_color
89 }
90
91 #[inline]
93 pub fn accent_color(&self) -> [f32; 4] {
94 self.accent_color
95 }
96
97 #[inline]
99 pub fn illumination_direction_deg(&self) -> f32 {
100 self.illumination_direction_deg
101 }
102
103 #[inline]
105 pub fn illumination_altitude_deg(&self) -> f32 {
106 self.illumination_altitude_deg
107 }
108
109 #[inline]
111 pub fn exaggeration(&self) -> f32 {
112 self.exaggeration
113 }
114
115 pub fn set_highlight_color(&mut self, color: [f32; 4]) {
117 self.highlight_color = color;
118 }
119
120 pub fn set_shadow_color(&mut self, color: [f32; 4]) {
122 self.shadow_color = color;
123 }
124
125 pub fn set_accent_color(&mut self, color: [f32; 4]) {
127 self.accent_color = color;
128 }
129
130 pub fn set_illumination_direction_deg(&mut self, direction_deg: f32) {
132 if direction_deg.is_finite() {
133 self.illumination_direction_deg = direction_deg.rem_euclid(360.0);
134 }
135 }
136
137 pub fn set_illumination_altitude_deg(&mut self, altitude_deg: f32) {
139 if altitude_deg.is_finite() {
140 self.illumination_altitude_deg = altitude_deg.clamp(0.0, 90.0);
141 }
142 }
143
144 pub fn set_exaggeration(&mut self, exaggeration: f32) {
146 if exaggeration.is_finite() {
147 self.exaggeration = exaggeration.max(0.0);
148 }
149 }
150
151 pub fn effective_params(&self) -> HillshadeParams {
153 HillshadeParams {
154 opacity: self.opacity,
155 highlight_color: self.highlight_color,
156 shadow_color: self.shadow_color,
157 accent_color: self.accent_color,
158 illumination_direction: self.illumination_direction_deg.to_radians(),
159 illumination_altitude: self.illumination_altitude_deg.to_radians(),
160 exaggeration: self.exaggeration,
161 }
162 }
163}
164
165impl Layer for HillshadeLayer {
166 fn id(&self) -> LayerId {
167 self.id
168 }
169
170 fn kind(&self) -> crate::layer::LayerKind {
171 crate::layer::LayerKind::Hillshade
172 }
173
174 fn name(&self) -> &str {
175 &self.name
176 }
177
178 fn visible(&self) -> bool {
179 self.visible
180 }
181
182 fn set_visible(&mut self, visible: bool) {
183 self.visible = visible;
184 }
185
186 fn opacity(&self) -> f32 {
187 self.opacity
188 }
189
190 fn set_opacity(&mut self, opacity: f32) {
191 self.opacity = opacity.clamp(0.0, 1.0);
192 }
193
194 fn as_any(&self) -> &dyn Any {
195 self
196 }
197
198 fn as_any_mut(&mut self) -> &mut dyn Any {
199 self
200 }
201}
202
203#[cfg(test)]
204mod tests {
205 use super::*;
206 use crate::layer::Layer;
207
208 #[test]
209 fn defaults_match_expected_contract() {
210 let layer = HillshadeLayer::new("hillshade");
211 assert_eq!(layer.kind(), crate::layer::LayerKind::Hillshade);
212 assert_eq!(layer.illumination_direction_deg(), 335.0);
213 assert_eq!(layer.illumination_altitude_deg(), 45.0);
214 assert_eq!(layer.exaggeration(), 1.0);
215 }
216
217 #[test]
218 fn setters_clamp_values() {
219 let mut layer = HillshadeLayer::new("hillshade");
220 layer.set_illumination_direction_deg(725.0);
221 layer.set_illumination_altitude_deg(120.0);
222 layer.set_exaggeration(-2.0);
223
224 assert_eq!(layer.illumination_direction_deg(), 5.0);
225 assert_eq!(layer.illumination_altitude_deg(), 90.0);
226 assert_eq!(layer.exaggeration(), 0.0);
227 }
228}