use std::{
ops::Deref,
sync::atomic::{AtomicU64, Ordering},
};
use geo::Intersects;
use crate::{Feature, FeaturesVecLayer, GeometryType};
#[cfg(feature = "image")]
pub use image_integration::{GeoImage, load_image_from_memory, open_image};
#[cfg(feature = "image")]
mod image_integration;
static ID_COUNTER: AtomicU64 = AtomicU64::new(0);
fn next_id() -> u64
{
ID_COUNTER.fetch_add(1, Ordering::Relaxed)
}
pub trait ImageData: Send + Sync
{
fn bounding_box(&self) -> geo::Rect;
fn pixel_size(&self) -> (u32, u32);
fn rgba_data(&self) -> Vec<u8>;
}
pub type BoxedImageDataRef<'a> = Box<&'a dyn ImageData>;
impl<'a> ImageData for BoxedImageDataRef<'a>
{
fn bounding_box(&self) -> geo::Rect
{
self.deref().bounding_box()
}
fn pixel_size(&self) -> (u32, u32)
{
self.deref().pixel_size()
}
fn rgba_data(&self) -> Vec<u8>
{
self.deref().rgba_data()
}
}
pub struct ImageFeature<TImageData: ImageData>
{
image_data: TImageData,
id: u64,
}
impl<TImageData: ImageData> ImageFeature<TImageData>
{
pub fn new(image_data: TImageData) -> Self
{
Self {
image_data,
id: next_id(),
}
}
pub fn image_data(&self) -> &TImageData
{
&self.image_data
}
pub fn id(&self) -> u64
{
self.id
}
}
impl<TImageData: ImageData> From<TImageData> for ImageFeature<TImageData>
{
fn from(value: TImageData) -> Self
{
Self::new(value)
}
}
impl<TImageData: ImageData> Feature for ImageFeature<TImageData>
{
fn geometry(&self) -> Option<geo::Geometry>
{
None
}
fn element_geometry_type(&self) -> GeometryType
{
GeometryType::Invalid
}
fn geometry_type(&self) -> crate::geometry::GeometryType
{
GeometryType::Invalid
}
fn image(&self) -> Option<ImageFeature<BoxedImageDataRef<'_>>>
{
Some(ImageFeature::<BoxedImageDataRef<'_>> {
image_data: Box::new(&self.image_data),
id: self.id,
})
}
fn intersects(&self, rect: geo::Rect) -> bool
{
self.image_data.bounding_box().intersects(&rect)
}
}
#[allow(type_alias_bounds)]
pub type VecLayer<TImageData: ImageData> = FeaturesVecLayer<ImageFeature<TImageData>>;
impl<TImageData: ImageData> VecLayer<TImageData>
{
pub fn from_images(images: Vec<TImageData>) -> VecLayer<TImageData>
{
let images: Vec<_> = images.into_iter().map(|x| ImageFeature::new(x)).collect();
VecLayer::<TImageData>::from(images)
}
}