diff --git a/src/random_distributions/mod.rs b/src/random_distributions/mod.rs index 0df18b3..d74beca 100644 --- a/src/random_distributions/mod.rs +++ b/src/random_distributions/mod.rs @@ -1,6 +1,9 @@ mod uniform_square; pub use uniform_square::UniformSquare; +mod unit_disc; +pub use unit_disc::UnitDisc; + pub trait RandomDistribution { fn value(&self) -> T; } diff --git a/src/random_distributions/unit_disc.rs b/src/random_distributions/unit_disc.rs new file mode 100644 index 0000000..84ce12c --- /dev/null +++ b/src/random_distributions/unit_disc.rs @@ -0,0 +1,49 @@ +use std::f64::consts::PI; + +use crate::math::Vec2; + +use super::{RandomDistribution, UniformSquare}; + +#[derive(Debug)] +pub struct UnitDisc { + square_distribution: UniformSquare, +} + +impl UnitDisc { + pub fn new() -> UnitDisc { + let square_distribution = UniformSquare::new(Vec2::new(-1.0, -1.0), 2.0); + UnitDisc { + square_distribution, + } + } +} + +impl RandomDistribution for UnitDisc { + fn value(&self) -> Vec2 { + let offset = self.square_distribution.value(); + if offset.x() == 0.0 && offset.y() == 0.0 { + offset + } else { + let (radius, angle) = if offset.x().abs() > offset.y().abs() { + (offset.x(), (PI / 4.0) * offset.y() / offset.x()) + } else { + (offset.y(), PI / 2.0 - (PI / 4.0) * offset.x() / offset.y()) + }; + Vec2::new(angle.cos(), angle.sin()) * radius + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn print_values() { + let target = UnitDisc::new(); + for _ in 0..1000 { + let value = target.value(); + println!("{}, {}", value.x(), value.y()); + } + } +}