hevolisa-0.0: Hevolisa/Shapes/DnaPoint.hs
--
-- Module : DnaPoint
-- Copyright : (c) Daniel Neun 2008
-- License : BSD-style
-- Maintainer : daniel.neun@gmx.de
-- Stability : experimental
-- Portability : portable
module Hevolisa.Shapes.DnaPoint (
DnaPoint (DnaPoint),
-- * Accessors
pointX,
pointY,
-- * Constructors, mutate
randomPoint
) where
import Hevolisa.Settings
import Hevolisa.Tools
-- |Mutable Point
data DnaPoint = DnaPoint {
pointX :: Double,
pointY :: Double
} deriving (Show,Eq,Read)
-- |DnaPoint is mutable
instance Mutable DnaPoint where
mutate = mutatePoint
-- |Initialize point with random garbage
instance RandomInit DnaPoint where
randomInit = do x <- getRandomNumber 0.0 maxWidth
y <- getRandomNumber 0.0 maxHeight
return (DnaPoint x y)
-- |Mutate points dna randomly, rates can be adjusted
mutatePoint :: DnaPoint -> IO DnaPoint
mutatePoint p = mutateMax p >>= mutateMid >>= mutateMin
where mutateMax = maybeMutate activeMovePointMaxMutationRate randomInit
mutateMid p = maybeMutate activeMovePointMidMutationRate
(pointFunction midX midY p) p
mutateMin p = maybeMutate activeMovePointMinMutationRate
(pointFunction minX minY p) p
-- |Change the x and y values of the point with functions
pointFunction :: (Double -> IO Double) -- ^ Function to change the x value
-> (Double -> IO Double) -- ^ Function to change the y value
-> DnaPoint -- ^ Original point
-> IO DnaPoint -- ^ Changed point (action)
pointFunction fx fy p = do x <- fx $ pointX p
y <- fy $ pointY p
return (DnaPoint x y)
-- |Helper functions for different ranges
midX, midY, minX, minY :: Double -> IO Double
midX = mutateDim activeMovePointRangeMid maxWidth
midY = mutateDim activeMovePointRangeMid maxHeight
minX = mutateDim activeMovePointRangeMin maxWidth
minY = mutateDim activeMovePointRangeMin maxHeight
-- |Mutate a one-dimensional value
mutateDim :: Double -- ^ Randomisation range
-> Double -- ^ Maximum
-> Double -- ^ Original value
-> IO Double -- ^ New value (action)
mutateDim range maxn n = getRandomNumber (-range) range >>=
return . min maxn . max 0 . (+ n)
-- |Create a random point using another point
randomPoint :: DnaPoint -> IO DnaPoint
randomPoint (DnaPoint x y) = do x <- mutateDim 3 maxWidth x
y <- mutateDim 3 maxHeight y
return (DnaPoint x y)