use std::marker::PhantomData;
use rand::Rng;
use crate::algorithm::{Algorithm, Creator};
use crate::utils::math::calc_radius;
pub mod algorithm;
mod utils;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Type {
Normal,
Periodic,
}
impl Default for Type {
fn default() -> Type {
Type::Normal
}
}
#[derive(Default, Clone, Debug, PartialEq)]
pub struct Builder {
radius: f32,
poisson_type: Type,
}
impl Builder {
pub fn with_radius(radius: f32, poisson_type: Type) -> Self {
assert!(0.0 < radius && radius <= 2f32.sqrt() / 2.0);
Builder {
radius,
poisson_type,
}
}
pub fn with_relative_radius(relative: f32, poisson_type: Type) -> Self {
assert!(0.0 < relative && relative <= 1.0);
Builder {
radius: relative * 2f32.sqrt() / 2.0,
poisson_type,
}
}
pub fn with_samples(samples: usize, relative: f32, poisson_type: Type) -> Self {
Builder {
radius: calc_radius(samples, relative, poisson_type),
poisson_type,
}
}
pub fn radius(&self) -> f32 {
self.radius
}
pub fn poisson_type(&self) -> Type {
self.poisson_type
}
pub fn build<R, A>(self, rng: R, _algo: A) -> Generator<R, A>
where
R: Rng,
A: Creator,
{
Generator::new(self, rng)
}
}
#[derive(Clone, Debug)]
pub struct Generator<R, A>
where
R: Rng,
A: Creator,
{
poisson: Builder,
rng: R,
_algo: PhantomData<A>,
}
impl<R, A> Generator<R, A>
where
R: Rng,
A: Creator,
{
fn new(poisson: Builder, rng: R) -> Self {
Generator {
rng,
poisson,
_algo: PhantomData,
}
}
pub fn set_radius(&mut self, radius: f32) {
assert!(0.0 < radius && radius <= 2f32.sqrt() / 2.0);
self.poisson.radius = radius;
}
pub fn radius(&self) -> f32 {
self.poisson.radius
}
pub fn poisson_type(&self) -> Type {
self.poisson.poisson_type
}
pub fn generate(self) -> Vec<mint::Vector2<f32>> {
self.into_iter().collect()
}
}
impl<R, A> IntoIterator for Generator<R, A>
where
R: Rng,
A: Creator,
{
type Item = mint::Vector2<f32>;
type IntoIter = PoissonIter<R, A::Algo>;
fn into_iter(self) -> Self::IntoIter {
PoissonIter {
rng: self.rng,
algo: A::create(&self.poisson),
poisson: self.poisson,
}
}
}
#[derive(Clone)]
pub struct PoissonIter<R, A>
where
R: Rng,
A: Algorithm,
{
poisson: Builder,
rng: R,
algo: A,
}
impl<R, A> Iterator for PoissonIter<R, A>
where
R: Rng,
A: Algorithm,
{
type Item = mint::Vector2<f32>;
fn next(&mut self) -> Option<Self::Item> {
self.algo.next(&mut self.poisson, &mut self.rng)
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.algo.size_hint(&self.poisson)
}
}
impl<R, A> PoissonIter<R, A>
where
R: Rng,
A: Algorithm,
{
pub fn radius(&self) -> f32 {
self.poisson.radius
}
pub fn poisson_type(&self) -> Type {
self.poisson.poisson_type
}
pub fn restrict(&mut self, value: mint::Vector2<f32>) {
self.algo.restrict(value);
}
pub fn stays_legal(&self, value: mint::Vector2<f32>) -> bool {
self.algo.stays_legal(&self.poisson, value)
}
}