mod convex_hull_2d;
mod convex_hull_3d;
mod convex_hull_3d_2d;
use std::marker::PhantomData;
pub use convex_hull_2d::*;
pub use convex_hull_3d::*;
pub use convex_hull_3d_2d::*;
use crate::{FaceIdType, FaceInstanceType};
use f3l_core::serde::{self, Deserialize, Serialize};
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
#[serde(crate = "self::serde")]
pub struct ConvexHull<'a, T: f3l_core::BasicFloat, P, const D: usize, CVH>
where
P: Into<[T; D]> + Clone + Copy + Send + Sync + std::ops::Index<usize, Output = T>,
CVH: Convex<'a, P>,
{
dim: usize,
#[serde(skip_serializing)]
#[serde(skip_deserializing)]
cvh: CVH,
#[serde(skip_serializing)]
#[serde(skip_deserializing)]
_marker: PhantomData<(T, &'a P)>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(crate = "self::serde")]
pub enum ConvexHullId {
D2(Vec<usize>),
D3(Vec<FaceIdType>),
}
impl Default for ConvexHullId {
fn default() -> Self {
Self::D2(vec![])
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(crate = "self::serde")]
pub enum ConvexHullInstance<P: Copy> {
D2(Vec<P>),
D3(Vec<FaceInstanceType<P>>),
}
impl<P: Copy> Default for ConvexHullInstance<P> {
fn default() -> Self {
Self::D2(vec![])
}
}
impl<'a, T: f3l_core::BasicFloat, P> Convex<'a, P>
for ConvexHull<'a, T, P, 2, ConvexHull2D<'a, T, P>>
where
P: Into<[T; 2]> + Clone + Copy + Send + Sync + std::ops::Index<usize, Output = T>,
{
fn new() -> Self {
Self {
dim: 2,
cvh: ConvexHull2D::new(),
_marker: PhantomData,
}
}
fn with_data(data: &'a Vec<P>) -> Self {
Self {
dim: 2,
cvh: ConvexHull2D::with_data(data),
_marker: PhantomData,
}
}
fn set_data(&mut self, data: &'a Vec<P>) {
self.cvh.set_data(data);
}
fn compute(&mut self) {
self.cvh.compute()
}
}
impl<'a, T: f3l_core::BasicFloat, P> ConvexHull<'a, T, P, 2, ConvexHull2D<'a, T, P>>
where
P: Into<[T; 2]> + Clone + Copy + Send + Sync + std::ops::Index<usize, Output = T>,
{
pub fn hulls(&self) -> ConvexHullId {
ConvexHullId::D2(self.cvh.hulls.clone())
}
pub fn hulls_instance(&self) -> Vec<P> {
self.cvh.hulls.iter().map(|&i| self.cvh.data[i]).collect()
}
}
impl<'a, T: f3l_core::BasicFloat, P> Convex<'a, P>
for ConvexHull<'a, T, P, 3, ConvexHull3D<'a, T, P>>
where
P: Into<[T; 3]> + Clone + Copy + Send + Sync + std::ops::Index<usize, Output = T>,
{
fn new() -> Self {
Self {
dim: 3,
cvh: ConvexHull3D::new(),
_marker: PhantomData,
}
}
fn with_data(data: &'a Vec<P>) -> Self {
Self {
dim: 3,
cvh: ConvexHull3D::with_data(data),
_marker: PhantomData,
}
}
fn set_data(&mut self, data: &'a Vec<P>) {
self.cvh.set_data(data);
}
fn compute(&mut self) {
self.cvh.compute()
}
}
impl<'a, T: f3l_core::BasicFloat, P> ConvexHull<'a, T, P, 3, ConvexHull3D<'a, T, P>>
where
P: Into<[T; 3]> + Clone + Copy + Send + Sync + std::ops::Index<usize, Output = T>,
{
pub fn hulls(&self) -> ConvexHullId {
self.cvh.hulls.clone()
}
pub fn hulls_instance(&self) -> ConvexHullInstance<P> {
match self.cvh.hulls.clone() {
ConvexHullId::D2(edges) => {
ConvexHullInstance::D2(edges.iter().map(|&i| self.cvh.data[i]).collect())
}
ConvexHullId::D3(faces) => ConvexHullInstance::D3(
faces
.iter()
.map(|&tri| FaceInstanceType {
point: [
self.cvh.data[tri.point[0]],
self.cvh.data[tri.point[1]],
self.cvh.data[tri.point[2]],
],
})
.collect(),
),
}
}
}
pub trait Convex<'a, P> {
fn new() -> Self;
fn with_data(data: &'a Vec<P>) -> Self;
fn set_data(&mut self, data: &'a Vec<P>);
fn compute(&mut self);
}