eorst 1.0.0

Earth Observation and Remote Sensing Toolkit - library for raster processing pipelines
//! Geospatial and array shape types.
//!
//! This module contains all the fundamental data structures for describing
//! raster dimensions, coordinates, geotransforms, and block configurations.

use clap::ValueEnum;
use serde::{Deserialize, Serialize};

/// Shape of a 4D raster array (times, layers, rows, cols).
#[derive(PartialEq, Debug, Clone, Copy)]
pub struct RasterDataShape {
    /// Number of time steps.
    pub times: usize,
    /// Number of layers/bands.
    pub layers: usize,
    /// Number of rows.
    pub rows: usize,
    /// Number of columns.
    pub cols: usize,
}

/// Dimension along which to stack or layer data.
#[derive(Debug, std::cmp::PartialEq, Clone, Copy, Default)]
pub enum Dimension {
    /// Stack along the layer dimension.
    #[default]
    Layer,
    /// Stack along the time dimension.
    Time,
}

/// Image resolution (pixel size in georeferenced units).
#[derive(Debug, Default, PartialEq, Clone, Copy)]
pub struct ImageResolution {
    /// X resolution (pixel width).
    pub x: f64,
    /// Y resolution (pixel height, typically negative for north-up).
    pub y: f64,
}

/// Image dimensions in pixels.
#[derive(Default, Debug, PartialEq, Clone, Copy)]
pub struct ImageSize {
    /// Number of rows (height).
    pub rows: usize,
    /// Number of columns (width).
    pub cols: usize,
}

/// Offset in array coordinates.
#[derive(PartialEq, Debug, Clone, Copy)]
pub struct Offset {
    /// Row offset.
    pub rows: isize,
    /// Column offset.
    pub cols: isize,
}

/// Size in array coordinates.
#[derive(PartialEq, Debug, Clone, Copy)]
pub struct Size {
    /// Number of rows.
    pub rows: isize,
    /// Number of columns.
    pub cols: isize,
}

/// Block size for chunked raster operations.
#[derive(Debug, PartialEq, Clone, Copy)]
pub struct BlockSize {
    /// Number of rows per block.
    pub rows: usize,
    /// Number of columns per block.
    pub cols: usize,
}

impl Default for BlockSize {
    fn default() -> Self {
        BlockSize {
            rows: 1024,
            cols: 1024,
        }
    }
}

/// Geotransform parameters defining the affine transformation from pixel to georeferenced coordinates.
#[derive(Default, Debug, PartialEq, Clone, Copy)]
pub struct GeoTransform {
    /// X coordinate of the upper-left pixel center.
    pub x_ul: f64,
    /// X resolution (pixel width).
    pub x_res: f64,
    /// X rotation (typically 0).
    pub x_rot: f64,
    /// Y coordinate of the upper-left pixel center.
    pub y_ul: f64,
    /// Y rotation (typically 0).
    pub y_rot: f64,
    /// Y resolution (pixel height, typically negative).
    pub y_res: f64,
}

impl GeoTransform {
    /// Converts the GeoTransform to a 6-element array.
    /// Array format: [x_ul, x_res, x_rot, y_ul, y_rot, y_res].
    pub fn to_array(&self) -> [f64; 6] {
        let array: [f64; 6] = [
            self.x_ul, self.x_res, self.x_rot, self.y_ul, self.y_rot, self.y_res,
        ];
        array
    }
}

/// Window for reading raster data.
#[derive(PartialEq, Debug, Clone, Copy)]
pub struct ReadWindow {
    /// Offset from which to start reading.
    pub offset: Offset,
    /// Size of the window to read.
    pub size: Size,
}

/// Overlap size for block-based operations (padding around each block).
#[derive(Debug, PartialEq, Clone, Copy, Default)]
pub struct Overlap {
    /// Number of pixels to pad on the left side.
    pub left: usize,
    /// Number of pixels to pad on the top side.
    pub top: usize,
    /// Number of pixels to pad on the right side.
    pub right: usize,
    /// Number of pixels to pad on the bottom side.
    pub bottom: usize,
}

/// Sampling method for aggregating raster values.
#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize, ValueEnum)]
pub enum SamplingMethod {
    /// Use the actual value.
    Value,
    /// Use the most common value (mode).
    Mode,
    /// Use the minimum value.
    Min,
    /// Use the standard deviation.
    StdDev,
    /// Use the average value.
    Avg,
}

/// 2D index into an array (column, row).
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct Index2d {
    /// Column index.
    pub col: usize,
    /// Row index.
    pub row: usize,
}

/// x and y coordinates of a location.
#[derive(Default, Debug, PartialEq, Clone, Copy)]
pub struct Coordinates {
    pub(crate) x: f64,
    pub(crate) y: f64,
}

/// Rectangle for array indexing (distances from a center point).
#[derive(Debug, Copy, Clone)]
pub struct Rectangle {
    /// Number of columns to the left of the center.
    pub left: usize,
    /// Number of rows above the center.
    pub top: usize,
    /// Number of columns to the right of the center.
    pub right: usize,
    /// Number of rows below the center.
    pub bottom: usize,
}

/// Coordinate value type for spatial coordinates.
#[derive(Debug, PartialEq)]
pub enum CoordType {
    /// Integer coordinate value.
    EInt(i64),
    /// Floating-point coordinate value.
    EFloat(f32),
    /// String coordinate value.
    EString(String),
}