{-# LANGUAGE GeneralizedNewtypeDeriving #-} module Zoom where import Point newtype Ratio = MkRatio { fromRatio :: Double } deriving (Show, RealFrac, Fractional, Real, Ord, Num, Eq, Enum) type Speed = Ratio data Zoom = MkZoom { ratio :: !Ratio , focus :: !Point } deriving Show noZoom :: Zoom noZoom = MkZoom 1 (MkPoint 0 0) nextZoom :: Zoom -> (Ratio -> Ratio) -> Zoom nextZoom z f = z{ ratio = fixRatio $ f (ratio z) } fixRatio :: Ratio -> Ratio fixRatio = min maxBound . max minBound instance Bounded Ratio where minBound = 1 maxBound = 2 (***) :: (Integral b, Integral a) => a -> Zoom -> b x *** MkZoom r _ = round (fromIntegral x * r) (~~~) :: (Integral b, Integral a) => a -> Zoom -> b x ~~~ MkZoom r (MkPoint dx _) = round (fromIntegral x * r + ((fromIntegral dx - 256) * 2 / pred maxBound) * (1-r)) (|||) :: (Integral b, Integral a) => a -> Zoom -> b y ||| MkZoom r (MkPoint _ dy) = round (fromIntegral y * r + ((fromIntegral dy - 192) * 2 / pred maxBound) * (1-r))