use num_traits::{NumCast, Zero};
use std::fmt::Debug;
pub trait RasterCell:
Copy + Clone + Debug + PartialEq + Zero + Send + Sync + 'static
{
fn default_nodata() -> Self;
fn is_nodata(&self, nodata: Option<Self>) -> bool;
}
pub trait RasterElement: RasterCell + PartialOrd + NumCast {
fn min_value() -> Self;
fn max_value() -> Self;
fn is_float() -> bool;
fn to_f64(self) -> Option<f64> {
NumCast::from(self)
}
}
macro_rules! impl_raster_element_int {
($t:ty) => {
impl RasterCell for $t {
fn default_nodata() -> Self {
<$t>::MIN
}
fn is_nodata(&self, nodata: Option<Self>) -> bool {
match nodata {
Some(nd) => *self == nd,
None => false,
}
}
}
impl RasterElement for $t {
fn min_value() -> Self {
<$t>::MIN
}
fn max_value() -> Self {
<$t>::MAX
}
fn is_float() -> bool {
false
}
}
};
}
macro_rules! impl_raster_element_float {
($t:ty) => {
impl RasterCell for $t {
fn default_nodata() -> Self {
<$t>::NAN
}
fn is_nodata(&self, nodata: Option<Self>) -> bool {
if self.is_nan() {
return true;
}
match nodata {
Some(nd) => (self - nd).abs() < <$t>::EPSILON * 100.0,
None => false,
}
}
}
impl RasterElement for $t {
fn min_value() -> Self {
<$t>::MIN
}
fn max_value() -> Self {
<$t>::MAX
}
fn is_float() -> bool {
true
}
}
};
}
impl_raster_element_int!(i8);
impl_raster_element_int!(i16);
impl_raster_element_int!(i32);
impl_raster_element_int!(i64);
impl_raster_element_int!(u8);
impl_raster_element_int!(u16);
impl_raster_element_int!(u32);
impl_raster_element_int!(u64);
impl_raster_element_float!(f32);
impl_raster_element_float!(f64);
#[cfg(feature = "complex")]
macro_rules! impl_raster_cell_complex {
($t:ty) => {
impl RasterCell for num_complex::Complex<$t> {
fn default_nodata() -> Self {
num_complex::Complex::new(<$t>::NAN, <$t>::NAN)
}
fn is_nodata(&self, nodata: Option<Self>) -> bool {
if self.re.is_nan() && self.im.is_nan() {
return true;
}
match nodata {
Some(nd) => {
(self.re - nd.re).abs() < <$t>::EPSILON * 100.0
&& (self.im - nd.im).abs() < <$t>::EPSILON * 100.0
}
None => false,
}
}
}
};
}
#[cfg(feature = "complex")]
impl_raster_cell_complex!(f32);
#[cfg(feature = "complex")]
impl_raster_cell_complex!(f64);