module Geometry.Algorithms.Sampling (
poissonDisc
, uniformlyDistributedPoints
, gaussianDistributedPoints
, rejection
) where
import Control.Applicative
import Control.Monad.Primitive
import Data.Function
import Data.Vector (Vector)
import qualified Data.Vector as V
import System.Random.MWC
import System.Random.MWC.Distributions
import Geometry
import Geometry.Algorithms.Sampling.PoissonDisc
uniformlyDistributedPoints
:: (PrimMonad m, HasBoundingBox boundingBox)
=> Gen (PrimState m)
-> boundingBox
-> Int
-> m (Vector Vec2)
uniformlyDistributedPoints :: forall (m :: * -> *) boundingBox.
(PrimMonad m, HasBoundingBox boundingBox) =>
Gen (PrimState m) -> boundingBox -> Int -> m (Vector Vec2)
uniformlyDistributedPoints Gen (PrimState m)
gen boundingBox
bb Int
count = Int -> m Vec2 -> m (Vector Vec2)
forall (m :: * -> *) a. Monad m => Int -> m a -> m (Vector a)
V.replicateM Int
count m Vec2
randomPoint
where
BoundingBox (Vec2 Double
xMin Double
yMin) (Vec2 Double
xMax Double
yMax) = boundingBox -> BoundingBox
forall a. HasBoundingBox a => a -> BoundingBox
boundingBox boundingBox
bb
randomPoint :: m Vec2
randomPoint = (Double -> Double -> Vec2) -> m Double -> m Double -> m Vec2
forall a b c. (a -> b -> c) -> m a -> m b -> m c
forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 Double -> Double -> Vec2
Vec2 ((Double, Double) -> Gen (PrimState m) -> m Double
forall a (m :: * -> *).
(Variate a, PrimMonad m) =>
(a, a) -> Gen (PrimState m) -> m a
forall (m :: * -> *).
PrimMonad m =>
(Double, Double) -> Gen (PrimState m) -> m Double
uniformR (Double
xMin, Double
xMax) Gen (PrimState m)
gen) ((Double, Double) -> Gen (PrimState m) -> m Double
forall a (m :: * -> *).
(Variate a, PrimMonad m) =>
(a, a) -> Gen (PrimState m) -> m a
forall (m :: * -> *).
PrimMonad m =>
(Double, Double) -> Gen (PrimState m) -> m Double
uniformR (Double
yMin, Double
yMax) Gen (PrimState m)
gen)
gaussianDistributedPoints
:: (PrimMonad m, HasBoundingBox boundingBox)
=> Gen (PrimState m)
-> boundingBox
-> Mat2
-> Int
-> m (Vector Vec2)
gaussianDistributedPoints :: forall (m :: * -> *) boundingBox.
(PrimMonad m, HasBoundingBox boundingBox) =>
Gen (PrimState m) -> boundingBox -> Mat2 -> Int -> m (Vector Vec2)
gaussianDistributedPoints Gen (PrimState m)
gen boundingBox
container Mat2
covariance Int
count = Int -> m Vec2 -> m (Vector Vec2)
forall (m :: * -> *) a. Monad m => Int -> m a -> m (Vector a)
V.replicateM Int
count m Vec2
randomPoint
where
bb :: BoundingBox
bb = boundingBox -> BoundingBox
forall a. HasBoundingBox a => a -> BoundingBox
boundingBox boundingBox
container
center :: Vec2
center = BoundingBox -> Vec2
forall a. HasBoundingBox a => a -> Vec2
boundingBoxCenter BoundingBox
bb
randomPoint :: m Vec2
randomPoint = do
let t :: Transformation
t = Mat2 -> Vec2 -> Transformation
Transformation Mat2
covariance Vec2
center
Vec2
vec <- Transformation -> (Double -> Vec2) -> Double -> Vec2
forall geo. Transform geo => Transformation -> geo -> geo
transform Transformation
t ((Double -> Vec2) -> Double -> Vec2)
-> (Double -> Double -> Vec2) -> Double -> Double -> Vec2
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Double -> Double -> Vec2
Vec2 (Double -> Double -> Vec2) -> m Double -> m (Double -> Vec2)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen (PrimState m) -> m Double
forall g (m :: * -> *). StatefulGen g m => g -> m Double
standard Gen (PrimState m)
gen m (Double -> Vec2) -> m Double -> m Vec2
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Gen (PrimState m) -> m Double
forall g (m :: * -> *). StatefulGen g m => g -> m Double
standard Gen (PrimState m)
gen
if Vec2
vec Vec2 -> BoundingBox -> Bool
forall thing bigObject.
(HasBoundingBox thing, HasBoundingBox bigObject) =>
thing -> bigObject -> Bool
`insideBoundingBox` BoundingBox
bb
then Vec2 -> m Vec2
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Vec2
vec
else m Vec2
randomPoint
rejection
:: (PrimMonad m, HasBoundingBox boundingBox)
=> Gen (PrimState m)
-> boundingBox
-> (Vec2 -> Double)
-> Int
-> m (Vector Vec2)
rejection :: forall (m :: * -> *) boundingBox.
(PrimMonad m, HasBoundingBox boundingBox) =>
Gen (PrimState m)
-> boundingBox -> (Vec2 -> Double) -> Int -> m (Vector Vec2)
rejection Gen (PrimState m)
gen boundingBox
bb Vec2 -> Double
distribution Int
numPoints = Int -> (Int -> m Vec2) -> m (Vector Vec2)
forall (m :: * -> *) a.
Monad m =>
Int -> (Int -> m a) -> m (Vector a)
V.generateM Int
numPoints ((Int -> m Vec2) -> m (Vector Vec2))
-> (Int -> m Vec2) -> m (Vector Vec2)
forall a b. (a -> b) -> a -> b
$ \Int
_ -> m Vec2
sampleSinglePoint
where
sampleSinglePoint :: m Vec2
sampleSinglePoint = (m Vec2 -> m Vec2) -> m Vec2
forall a. (a -> a) -> a
fix ((m Vec2 -> m Vec2) -> m Vec2) -> (m Vec2 -> m Vec2) -> m Vec2
forall a b. (a -> b) -> a -> b
$ \m Vec2
loop -> do
Vec2
p <- (Vec2, Vec2) -> Gen (PrimState m) -> m Vec2
forall a g (m :: * -> *).
(UniformRange a, StatefulGen g m) =>
(a, a) -> g -> m a
forall g (m :: * -> *).
StatefulGen g m =>
(Vec2, Vec2) -> g -> m Vec2
uniformRM (Vec2
bbMin, Vec2
bbMax) Gen (PrimState m)
gen
let pVal :: Double
pVal = Vec2 -> Double
distribution Vec2
p
Double
threshold <- (Double, Double) -> Gen (PrimState m) -> m Double
forall a g (m :: * -> *).
(UniformRange a, StatefulGen g m) =>
(a, a) -> g -> m a
forall g (m :: * -> *).
StatefulGen g m =>
(Double, Double) -> g -> m Double
uniformRM (Double
0,Double
1) Gen (PrimState m)
gen
if Double
threshold Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
pVal
then Vec2 -> m Vec2
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Vec2
p
else m Vec2
loop
BoundingBox Vec2
bbMin Vec2
bbMax = boundingBox -> BoundingBox
forall a. HasBoundingBox a => a -> BoundingBox
boundingBox boundingBox
bb