packages feed

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)