use std::fmt;
use std::marker::PhantomData;
use std::ops::Index;
use crate::image_io::buffer::{CoverSource, ImageBuffer};
pub mod hill;
pub struct CostMap<'img> {
pub(crate) data: Vec<f32>,
pub(crate) width: u32,
pub(crate) height: u32,
_phantom: PhantomData<&'img ImageBuffer>,
}
impl<'img> CostMap<'img> {
pub(crate) fn new(image: &'img ImageBuffer, data: Vec<f32>) -> Self {
let (width, height) = image.dimensions();
Self {
data,
width,
height,
_phantom: PhantomData,
}
}
pub fn dimensions(&self) -> (u32, u32) {
(self.width, self.height)
}
pub fn pixel_count(&self) -> usize {
self.width as usize * self.height as usize
}
pub fn costs(&self) -> &[f32] {
&self.data
}
pub fn get(&self, x: u32, y: u32) -> Option<f32> {
if x >= self.width || y >= self.height {
return None;
}
self.data.get(self.linear_index(x, y)).copied()
}
fn linear_index(&self, x: u32, y: u32) -> usize {
y as usize * self.width as usize + x as usize
}
}
impl Index<(u32, u32)> for CostMap<'_> {
type Output = f32;
fn index(&self, (x, y): (u32, u32)) -> &f32 {
&self.data[self.linear_index(x, y)]
}
}
impl fmt::Debug for CostMap<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("CostMap")
.field("width", &self.width)
.field("height", &self.height)
.field("costs", &self.data.len())
.finish()
}
}
pub trait CostProvider {
type Error;
fn compute<'img>(&self, image: &'img ImageBuffer) -> Result<CostMap<'img>, Self::Error>;
}