1use crate::core_types::{RasterData, RasterType};
7use crate::data_sources::DateType;
8use crate::types::{BlockSize, GeoTransform, RasterDataShape};
9use anyhow::Result;
10use num_traits::NumCast;
11use std::path::PathBuf;
12use std::str::FromStr;
13
14#[derive(Debug, PartialEq, Clone)]
16pub struct Extent {
17 pub xmin: f64,
19 pub ymin: f64,
21 pub xmax: f64,
23 pub ymax: f64,
25}
26
27impl FromStr for Extent {
28 type Err = String;
29
30 fn from_str(s: &str) -> Result<Self, Self::Err> {
31 let parts: Vec<&str> = s.split(',').collect();
32 if parts.len() != 4 {
33 return Err("Extent must be in the format xmin,ymin,xmax,ymax".to_string());
34 }
35
36 let xmin = parts[0].parse().map_err(|_| "Invalid xmin")?;
37 let ymin = parts[1].parse().map_err(|_| "Invalid ymin")?;
38 let xmax = parts[2].parse().map_err(|_| "Invalid xmax")?;
39 let ymax = parts[3].parse().map_err(|_| "Invalid ymax")?;
40
41 Ok(Extent {
42 xmin,
43 ymin,
44 xmax,
45 ymax,
46 })
47 }
48}
49
50impl Extent {
51 pub fn snap_to_grid(&self, resolution: f64) -> Self {
56 Extent {
57 xmin: (self.xmin / resolution).floor() * resolution,
58 ymin: (self.ymin / resolution).floor() * resolution,
59 xmax: (self.xmax / resolution).ceil() * resolution,
60 ymax: (self.ymax / resolution).ceil() * resolution,
61 }
62 }
63
64 pub fn union(&self, other: &Self) -> Self {
66 Extent {
67 xmin: self.xmin.min(other.xmin),
68 ymin: self.ymin.min(other.ymin),
69 xmax: self.xmax.max(other.xmax),
70 ymax: self.ymax.max(other.ymax),
71 }
72 }
73}
74
75#[derive(Debug, Clone, PartialEq)]
79pub struct Layer {
80 pub source: PathBuf,
81 pub(crate) layer_pos: usize,
82 pub(crate) time_pos: usize,
83}
84
85impl Layer {
86 pub fn new(source: PathBuf, layer_pos: usize, time_pos: usize) -> Self {
87 Layer {
88 source,
89 layer_pos,
90 time_pos,
91 }
92 }
93
94 pub fn stack_position(
96 &mut self,
97 original_layer: Layer,
98 dimension_to_stack: crate::types::Dimension,
99 max_dim: usize,
100 ) -> &mut Layer {
101 match dimension_to_stack {
102 crate::types::Dimension::Layer => self.layer_pos = original_layer.layer_pos + max_dim,
103 crate::types::Dimension::Time => self.time_pos = original_layer.time_pos + max_dim,
104 }
105 self
106 }
107}
108
109#[derive(Debug, Clone, PartialEq)]
111pub struct RasterMetadata<U>
112where
113 U: RasterType,
114{
115 pub layers: Vec<Layer>,
117 pub shape: RasterDataShape,
119 pub(crate) block_size: BlockSize,
120 pub epsg_code: u32,
122 pub geo_transform: GeoTransform,
124 pub overlap_size: usize,
126 pub date_indices: Vec<DateType>,
128 pub layer_indices: Vec<String>,
130 pub na_value: U,
132}
133
134impl<U> Default for RasterMetadata<U>
135where
136 U: RasterType,
137{
138 fn default() -> Self {
139 Self::new()
140 }
141}
142
143impl<U> RasterMetadata<U>
144where
145 U: RasterType,
146{
147 pub fn new() -> Self {
149 let layers = Vec::new();
150 let shape = RasterDataShape {
151 times: 0,
152 layers: 0,
153 rows: 0,
154 cols: 0,
155 };
156 let block_size = BlockSize { rows: 0, cols: 0 };
157 let epsg_code = 4326;
158 let geo_transform = GeoTransform {
159 x_ul: 0.,
160 x_res: 0.,
161 x_rot: 0.,
162 y_ul: 0.,
163 y_rot: 0.,
164 y_res: 0.,
165 };
166 let overlap_size = 0;
167 let date_indices = Vec::new();
168 let layer_indices = Vec::new();
169 let na_value = U::zero();
170
171 RasterMetadata {
172 layers,
173 shape,
174 block_size,
175 epsg_code,
176 geo_transform,
177 overlap_size,
178 date_indices,
179 layer_indices,
180 na_value: NumCast::from(na_value).unwrap(),
181 }
182 }
183}
184
185#[derive(Debug, Clone, PartialEq)]
187pub struct RasterDataBlock<T>
188where
189 T: RasterType,
190{
191 pub data: RasterData<T>,
193 pub metadata: RasterMetadata<T>,
195 pub no_data: T,
197}