use mint::Vector2;
use crate::Zip;
use crate::traits::{Array2dStorageMut, Array2dStorageOwned};
use crate::{Array2d, GenericArray2d, traits::Array2dStorage, zip::GenericArray2dRef};
impl<T: Array2dStorage> GenericArray2d<T> {
pub fn copied(&self) -> Array2d<T::Item>
where
T::Item: Copy,
{
let mut data = Vec::with_capacity(self.len());
data.extend(self.values().copied());
Array2d {
data,
boundary: self.boundary,
pitch: self.pitch,
}
}
pub fn cloned(&self) -> Array2d<T::Item>
where
T::Item: Clone,
{
let mut data = Vec::with_capacity(self.len());
data.extend(self.values().cloned());
Array2d {
data,
boundary: self.boundary,
pitch: self.pitch,
}
}
pub fn mapped<U>(&self, f: impl FnMut(&T::Item) -> U) -> Array2d<U> {
let mut data = Vec::with_capacity(self.len());
data.extend(self.values().map(f));
Array2d {
data,
boundary: self.boundary,
pitch: self.pitch,
}
}
pub fn zip<U: GenericArray2dRef>(&self, rhs: U) -> Zip<&Self, U> {
Zip(self, rhs)
}
pub fn zip_mut<U: GenericArray2dRef>(&mut self, rhs: U) -> Zip<&mut Self, U>
where
T: Array2dStorageMut,
{
Zip(self, rhs)
}
}
pub trait Truthy {
fn is_true(&self) -> bool;
}
impl Truthy for bool {
fn is_true(&self) -> bool {
*self
}
}
impl<T> Truthy for Option<T> {
fn is_true(&self) -> bool {
self.is_some()
}
}
impl<T: Array2dStorage<Item: Truthy>> GenericArray2d<T> {
pub fn iter_points<U: From<Vector2<i32>>>(&self) -> impl Iterator<Item = U> {
self.iter::<U>()
.filter_map(|(pos, val)| val.is_true().then_some(pos))
}
pub fn iter_points_owned<U: From<Vector2<i32>>>(self) -> impl Iterator<Item = U>
where
T: Array2dStorageOwned,
{
self.iter_owned::<U>()
.filter_map(|(pos, val)| val.is_true().then_some(pos))
}
pub fn border_detection<U: From<Vector2<i32>>>(&self) -> impl Iterator<Item = U> {
let pitch = self.pitch;
let slice = self.data.slice();
self.boundary()
.trim_border()
.iter()
.filter(move |p| {
let i = self.index_internal(*p).unwrap();
slice[i].is_true()
&& (!slice[i - 1].is_true()
|| !slice[i + 1].is_true()
|| !slice[i - pitch].is_true()
|| !slice[i + pitch].is_true())
})
.chain(
self.boundary()
.iter_border()
.filter(move |p| self.get(*p).is_some_and(|x| x.is_true())),
)
.map(Into::into)
}
}
impl<T: Array2dStorage<Item = Option<A>>, A> GenericArray2d<T> {
pub fn iter_some<'t, U: From<Vector2<i32>>>(&'t self) -> impl Iterator<Item = (U, &'t A)>
where
A: 't,
{
self.iter::<U>()
.filter_map(|(pos, value)| value.as_ref().map(|v| (pos, v)))
}
pub fn iter_some_mut<'t, U: From<Vector2<i32>>>(
&'t mut self,
) -> impl Iterator<Item = (U, &'t mut A)>
where
T: Array2dStorageMut,
A: 't,
{
self.iter_mut::<U>()
.filter_map(|(pos, value)| value.as_mut().map(|v| (pos, v)))
}
pub fn iter_some_owned<U: From<Vector2<i32>>>(self) -> impl Iterator<Item = (U, A)>
where
T: Array2dStorageOwned,
{
self.iter_owned::<U>()
.filter_map(|(pos, value)| value.map(|v| (pos, v)))
}
}