use ndarray::{Array2, Array3};
use crate::error::ImgalError;
pub fn circle_kernel(radius: usize) -> Result<Array2<bool>, ImgalError> {
if radius == 0 {
return Err(ImgalError::InvalidParameterValueLess {
param_name: "radius",
value: 0,
});
}
let dim = radius * 2 + 1;
let center = radius as f64;
let mut kernel = Array2::<bool>::default((dim, dim));
kernel.indexed_iter_mut().for_each(|((row, col), v)| {
let x = col as f64;
let y = row as f64;
let dist = ((x - center).powi(2) + (y - center).powi(2)).sqrt();
*v = dist <= center;
});
Ok(kernel)
}
pub fn sphere_kernel(radius: usize) -> Result<Array3<bool>, ImgalError> {
if radius == 0 {
return Err(ImgalError::InvalidParameterValueEqual {
param_name: "radius",
value: 0,
});
}
let dim = radius * 2 + 1;
let center = radius as f64;
let mut kernel = Array3::<bool>::default((dim, dim, dim));
kernel.indexed_iter_mut().for_each(|((pln, row, col), v)| {
let x = col as f64;
let y = row as f64;
let z = pln as f64;
let dist = ((x - center).powi(2) + (y - center).powi(2) + (z - center).powi(2)).sqrt();
*v = dist <= center;
});
Ok(kernel)
}
pub fn weighted_circle_kernel(
circle_radius: usize,
falloff_radius: f64,
initial_value: Option<f64>,
) -> Result<Array2<f64>, ImgalError> {
if circle_radius == 0 {
return Err(ImgalError::InvalidParameterValueLess {
param_name: "circle_radius",
value: 0,
});
}
let dim = circle_radius * 2 + 1;
let center = circle_radius as f64;
let norm_center = center / falloff_radius;
let iv = initial_value.unwrap_or(1.0);
let mut kernel = Array2::<f64>::zeros((dim, dim));
kernel.indexed_iter_mut().for_each(|((row, col), v)| {
let x = col as f64;
let y = row as f64;
let mut norm_dist = ((x - center).powi(2) + (y - center).powi(2)).sqrt() / falloff_radius;
if norm_dist <= norm_center {
if norm_dist >= iv {
norm_dist = 0.0;
} else {
norm_dist = iv - norm_dist;
}
*v = norm_dist;
} else {
*v = 0.0;
}
});
Ok(kernel)
}
pub fn weighted_sphere_kernel(
sphere_radius: usize,
falloff_radius: f64,
initial_value: Option<f64>,
) -> Result<Array3<f64>, ImgalError> {
if sphere_radius == 0 {
return Err(ImgalError::InvalidParameterValueLess {
param_name: "sphere_radius",
value: 0,
});
}
let dim = sphere_radius * 2 + 1;
let center = sphere_radius as f64;
let norm_center = center / falloff_radius;
let iv = initial_value.unwrap_or(1.0);
let mut kernel = Array3::<f64>::zeros((dim, dim, dim));
kernel.indexed_iter_mut().for_each(|((pln, row, col), v)| {
let x = col as f64;
let y = row as f64;
let z = pln as f64;
let mut norm_dist = ((x - center).powi(2) + (y - center).powi(2) + (z - center).powi(2))
.sqrt()
/ falloff_radius;
if norm_dist <= norm_center {
if norm_dist >= iv {
norm_dist = 0.0;
} else {
norm_dist = iv - norm_dist;
}
*v = norm_dist;
} else {
*v = 0.0;
}
});
Ok(kernel)
}