    {-# LANGUAGE FlexibleInstances #-}
    {-# LANGUAGE InstanceSigs #-}
    {-# LANGUAGE MultiParamTypeClasses #-}
    {-# LANGUAGE RecordWildCards #-}
    -----------------------------------------------------------------------------
    -- |
    -- Module      :  XMonad.Layout.CircleEx
    -- Description :  An elliptical, overlapping layout—extended version.
    -- Copyright   :  (c) Peter De Wachter, Ilya V. Portnov
    -- License     :  BSD-style (see LICENSE)
    --
    -- Maintainer  :  Ilya V. Portnov <portnov84@rambler.ru>
    -- Stability   :  unstable
    -- Portability :  unportable
    --
    -- Circle is an elliptical, overlapping layout. Original code by Peter De Wachter,
    -- extended by Ilya Porntov.
    -----------------------------------------------------------------------------

    module XMonad.Layout.CircleEx (
        -- * Usage
        -- $usage
        CircleEx (..), circle, circleEx,
        CircleExMsg (..)
      )
      where

    import Data.Ratio

    import XMonad
    import XMonad.StackSet (Stack)
    import XMonad.Prelude
    import qualified XMonad.StackSet as W

    -- $usage
    --
    -- The layout puts the first N windows (called master) into the center of
    -- screen. All others (called secondary, or stack) are organized in a circle
    -- (well, ellipse). When opening a new secondary window, its size will be
    -- slightly smaller than that of its predecessor (this is configurable). If
    -- the number of master windows is set to zero, all windows will be arranged
    -- in a circle. If there is more than one master window, they will be stacked
    -- in the center on top of each other. The size of each additional master
    -- window will again be slightly smaller than that of the former.
    --
    -- Since a picture says more than a thousand words, you see one
    -- <https://github.com/xmonad/xmonad-contrib/assets/50166980/90ef1273-5201-4380-8b94-9e62d3c98e1c here>.
    --
    -- You can use this module with the following in your @xmonad.hs@:
    --
    -- > import XMonad.Layout.CircleEx
    --
    -- Then edit your @layoutHook@ by adding the 'CircleEx' layout:
    --
    -- > myCircle = circleEx {cDelta = -3*pi/4}
    -- > myLayout = myCircle ||| Full ||| etc..
    -- > main = xmonad def { layoutHook = myLayout }
    --
    -- This layout understands standard messages:
    --
    -- * 'IncMasterN': increase or decrease the number of master windows.
    -- * 'Shrink' and 'Expand': change the size of master windows.
    --
    -- More layout-specific messages are also supported, see 'CircleExMsg' below.
    --
    -- For more detailed instructions on editing the layoutHook see:
    -- "XMonad.Doc.Extending#Editing_the_layout_hook"

    -- | The layout data type. It is recommended to not use the 'CircleEx' data
    -- constructor directly, and instead rely on record update syntax; for
    -- example: @circleEx {cMasterRatio = 4%5}@. In this way you can avoid nasty
    -- surprises if one day additional fields are added to @CircleEx@.
    data CircleEx a = CircleEx
        { forall a. CircleEx a -> Int
    cNMaster :: !Int          -- ^ Number of master windows. Default value is 1.
        , forall a. CircleEx a -> Rational
    cMasterRatio :: !Rational -- ^ Size of master window in relation to screen size.
                                    --   Default value is @4%5@.
        , forall a. CircleEx a -> Rational
    cStackRatio :: !Rational  -- ^ Size of first secondary window in relation to screen size.
                                    --   Default value is @3%5@.
        , forall a. CircleEx a -> Rational
    cMultiplier :: !Rational  -- ^ Coefficient used to calculate the sizes of subsequent secondary
                                    --   windows. The size of the next window is calculated as the
                                    --   size of the previous one multiplied by this value.
                                    --   This value is also used to scale master windows, in case
                                    --   there is more than one.
                                    --   Default value is @5%6@. Set this to 1 if you want all secondary
                                    --   windows to have the same size.
        , forall a. CircleEx a -> Double
    cDelta :: !Double         -- ^ Angle of rotation of the whole circle layout. Usual values
                                    --   are from 0 to 2π, although it will work outside
                                    --   this range as well. Default value of 0 means that the first
                                    --   secondary window will be placed at the right side of screen.
        } deriving (CircleEx a -> CircleEx a -> Bool
    (CircleEx a -> CircleEx a -> Bool)
    -> (CircleEx a -> CircleEx a -> Bool) -> Eq (CircleEx a)
    forall a. CircleEx a -> CircleEx a -> Bool
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: forall a. CircleEx a -> CircleEx a -> Bool
    == :: CircleEx a -> CircleEx a -> Bool
    $c/= :: forall a. CircleEx a -> CircleEx a -> Bool
    /= :: CircleEx a -> CircleEx a -> Bool
    Eq, Int -> CircleEx a -> ShowS
    [CircleEx a] -> ShowS
    CircleEx a -> String
    (Int -> CircleEx a -> ShowS)
    -> (CircleEx a -> String)
    -> ([CircleEx a] -> ShowS)
    -> Show (CircleEx a)
    forall a. Int -> CircleEx a -> ShowS
    forall a. [CircleEx a] -> ShowS
    forall a. CircleEx a -> String
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: forall a. Int -> CircleEx a -> ShowS
    showsPrec :: Int -> CircleEx a -> ShowS
    $cshow :: forall a. CircleEx a -> String
    show :: CircleEx a -> String
    $cshowList :: forall a. [CircleEx a] -> ShowS
    showList :: [CircleEx a] -> ShowS
    Show, ReadPrec [CircleEx a]
    ReadPrec (CircleEx a)
    Int -> ReadS (CircleEx a)
    ReadS [CircleEx a]
    (Int -> ReadS (CircleEx a))
    -> ReadS [CircleEx a]
    -> ReadPrec (CircleEx a)
    -> ReadPrec [CircleEx a]
    -> Read (CircleEx a)
    forall a. ReadPrec [CircleEx a]
    forall a. ReadPrec (CircleEx a)
    forall a. Int -> ReadS (CircleEx a)
    forall a. ReadS [CircleEx a]
    forall a.
    (Int -> ReadS a)
    -> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
    $creadsPrec :: forall a. Int -> ReadS (CircleEx a)
    readsPrec :: Int -> ReadS (CircleEx a)
    $creadList :: forall a. ReadS [CircleEx a]
    readList :: ReadS [CircleEx a]
    $creadPrec :: forall a. ReadPrec (CircleEx a)
    readPrec :: ReadPrec (CircleEx a)
    $creadListPrec :: forall a. ReadPrec [CircleEx a]
    readListPrec :: ReadPrec [CircleEx a]
    Read)

    -- | Circle layout with default settings:
    --
    -- * Number of master windows is set to 1
    -- * @cMasterRatio@ is set to @70/99@, which is nearly @1/sqrt(2)@
    -- * @cStackRatio@ is set to @2/5@
    -- * @cMultiplier@ is set to 1, which means all secondary windows
    --   will have the same size
    --
    -- This can be used as a drop-in replacement for "XMonad.Layout.Circle".
    circle :: CircleEx a
    circle :: forall a. CircleEx a
    circle = Int -> Rational -> Rational -> Rational -> Double -> CircleEx a
    forall a.
    Int -> Rational -> Rational -> Rational -> Double -> CircleEx a
    CircleEx Int
    1 (Integer
    70Integer -> Integer -> Rational
    forall a. Integral a => a -> a -> Ratio a
    %Integer
    99) (Integer
    2Integer -> Integer -> Rational
    forall a. Integral a => a -> a -> Ratio a
    %Integer
    5) Rational
    1 Double
    0

    -- | Another variant of default settings for circle layout:
    --
    -- * Number of master windows is set to 1
    -- * @cMasterRatio@ is set to @4/5@
    -- * @cStackRatio@ is set to @3/5@
    -- * @cMultiplier@ is set to @5/6@
    --
    circleEx :: CircleEx a
    circleEx :: forall a. CircleEx a
    circleEx = Int -> Rational -> Rational -> Rational -> Double -> CircleEx a
    forall a.
    Int -> Rational -> Rational -> Rational -> Double -> CircleEx a
    CircleEx Int
    1 (Integer
    4Integer -> Integer -> Rational
    forall a. Integral a => a -> a -> Ratio a
    %Integer
    5) (Integer
    3Integer -> Integer -> Rational
    forall a. Integral a => a -> a -> Ratio a
    %Integer
    5) (Integer
    5Integer -> Integer -> Rational
    forall a. Integral a => a -> a -> Ratio a
    %Integer
    6) Double
    0

    -- | Specific messages understood by CircleEx layout.
    data CircleExMsg
      = Rotate !Double            -- ^ Rotate secondary windows by specific angle
      | IncStackRatio !Rational   -- ^ Increase (or decrease, with negative value) sizes of secondary windows
      | IncMultiplier !Rational   -- ^ Increase 'cMultiplier'.
      deriving (CircleExMsg -> CircleExMsg -> Bool
    (CircleExMsg -> CircleExMsg -> Bool)
    -> (CircleExMsg -> CircleExMsg -> Bool) -> Eq CircleExMsg
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: CircleExMsg -> CircleExMsg -> Bool
    == :: CircleExMsg -> CircleExMsg -> Bool
    $c/= :: CircleExMsg -> CircleExMsg -> Bool
    /= :: CircleExMsg -> CircleExMsg -> Bool
    Eq, Int -> CircleExMsg -> ShowS
    [CircleExMsg] -> ShowS
    CircleExMsg -> String
    (Int -> CircleExMsg -> ShowS)
    -> (CircleExMsg -> String)
    -> ([CircleExMsg] -> ShowS)
    -> Show CircleExMsg
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> CircleExMsg -> ShowS
    showsPrec :: Int -> CircleExMsg -> ShowS
    $cshow :: CircleExMsg -> String
    show :: CircleExMsg -> String
    $cshowList :: [CircleExMsg] -> ShowS
    showList :: [CircleExMsg] -> ShowS
    Show, Typeable)

    instance Message CircleExMsg

    instance LayoutClass CircleEx Window where
      doLayout :: CircleEx Window -> Rectangle -> Stack Window -> X ([(Window, Rectangle)], Maybe (CircleEx Window))
      doLayout :: CircleEx Window
    -> Rectangle
    -> Stack Window
    -> X ([(Window, Rectangle)], Maybe (CircleEx Window))
    doLayout CircleEx Window
    layout Rectangle
    rect Stack Window
    stack = do
        [(Window, Rectangle)]
    result <- [(Window, Rectangle)] -> X [(Window, Rectangle)]
    raiseFocus ([(Window, Rectangle)] -> X [(Window, Rectangle)])
    -> [(Window, Rectangle)] -> X [(Window, Rectangle)]
    forall a b. (a -> b) -> a -> b
    $ CircleEx Window -> Rectangle -> [Window] -> [(Window, Rectangle)]
    forall a. CircleEx a -> Rectangle -> [a] -> [(a, Rectangle)]
    circleLayout CircleEx Window
    layout Rectangle
    rect ([Window] -> [(Window, Rectangle)])
    -> [Window] -> [(Window, Rectangle)]
    forall a b. (a -> b) -> a -> b
    $ Stack Window -> [Window]
    forall a. Stack a -> [a]
    W.integrate Stack Window
    stack
        ([(Window, Rectangle)], Maybe (CircleEx Window))
    -> X ([(Window, Rectangle)], Maybe (CircleEx Window))
    forall a. a -> X a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ([(Window, Rectangle)]
    result, Maybe (CircleEx Window)
    forall a. Maybe a
    Nothing)

      pureMessage :: CircleEx Window -> SomeMessage -> Maybe (CircleEx Window)
      pureMessage :: CircleEx Window -> SomeMessage -> Maybe (CircleEx Window)
    pureMessage CircleEx Window
    layout SomeMessage
    m =
          [Maybe (CircleEx Window)] -> Maybe (CircleEx Window)
    forall (t :: * -> *) (m :: * -> *) a.
    (Foldable t, MonadPlus m) =>
    t (m a) -> m a
    msum [IncMasterN -> CircleEx Window
    forall a. IncMasterN -> CircleEx a
    changeMasterN (IncMasterN -> CircleEx Window)
    -> Maybe IncMasterN -> Maybe (CircleEx Window)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> SomeMessage -> Maybe IncMasterN
    forall m. Message m => SomeMessage -> Maybe m
    fromMessage SomeMessage
    m,
                Resize -> CircleEx Window
    forall a. Resize -> CircleEx a
    resize (Resize -> CircleEx Window)
    -> Maybe Resize -> Maybe (CircleEx Window)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> SomeMessage -> Maybe Resize
    forall m. Message m => SomeMessage -> Maybe m
    fromMessage SomeMessage
    m,
                CircleExMsg -> CircleEx Window
    forall a. CircleExMsg -> CircleEx a
    specific (CircleExMsg -> CircleEx Window)
    -> Maybe CircleExMsg -> Maybe (CircleEx Window)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> SomeMessage -> Maybe CircleExMsg
    forall m. Message m => SomeMessage -> Maybe m
    fromMessage SomeMessage
    m]
        where
          deltaSize :: Rational
    deltaSize = Integer
    11 Integer -> Integer -> Rational
    forall a. Integral a => a -> a -> Ratio a
    % Integer
    10

          resize :: Resize -> CircleEx a
          resize :: forall a. Resize -> CircleEx a
    resize Resize
    Shrink = CircleEx Window
    layout {cMasterRatio = max 0.1 $ min 1.0 $ cMasterRatio layout / deltaSize}
          resize Resize
    Expand = CircleEx Window
    layout {cMasterRatio = max 0.1 $ min 1.0 $ cMasterRatio layout * deltaSize}

          changeMasterN :: IncMasterN -> CircleEx a
          changeMasterN :: forall a. IncMasterN -> CircleEx a
    changeMasterN (IncMasterN Int
    d) = CircleEx Window
    layout {cNMaster = max 0 (cNMaster layout + d)}

          specific :: CircleExMsg -> CircleEx a
          specific :: forall a. CircleExMsg -> CircleEx a
    specific (Rotate Double
    delta) = CircleEx Window
    layout {cDelta = delta + cDelta layout}
          specific (IncStackRatio Rational
    delta) = CircleEx Window
    layout {cStackRatio = max 0.1 $ min 2.0 $ delta + cStackRatio layout}
          specific (IncMultiplier Rational
    delta) = CircleEx Window
    layout {cMultiplier = max 0.1 $ min 2.0 $ delta + cMultiplier layout}

    circleLayout :: CircleEx a -> Rectangle -> [a] -> [(a, Rectangle)]
    circleLayout :: forall a. CircleEx a -> Rectangle -> [a] -> [(a, Rectangle)]
    circleLayout CircleEx a
    _ Rectangle
    _ [] = []
    circleLayout (CircleEx {Double
    Int
    Rational
    cNMaster :: forall a. CircleEx a -> Int
    cMasterRatio :: forall a. CircleEx a -> Rational
    cStackRatio :: forall a. CircleEx a -> Rational
    cMultiplier :: forall a. CircleEx a -> Rational
    cDelta :: forall a. CircleEx a -> Double
    cNMaster :: Int
    cMasterRatio :: Rational
    cStackRatio :: Rational
    cMultiplier :: Rational
    cDelta :: Double
    ..}) Rectangle
    rectangle [a]
    wins =
        [a] -> [(a, Rectangle)]
    forall a. [a] -> [(a, Rectangle)]
    master (Int -> [a] -> [a]
    forall a. Int -> [a] -> [a]
    take Int
    cNMaster [a]
    wins) [(a, Rectangle)] -> [(a, Rectangle)] -> [(a, Rectangle)]
    forall a. [a] -> [a] -> [a]
    ++ [a] -> [(a, Rectangle)]
    forall a. [a] -> [(a, Rectangle)]
    rest (Int -> [a] -> [a]
    forall a. Int -> [a] -> [a]
    drop Int
    cNMaster [a]
    wins)
      where
        master :: [a] -> [(a, Rectangle)]
        master :: forall a. [a] -> [(a, Rectangle)]
    master [a]
    ws = [a] -> [Rectangle] -> [(a, Rectangle)]
    forall a b. [a] -> [b] -> [(a, b)]
    zip [a]
    ws ([Rectangle] -> [(a, Rectangle)])
    -> [Rectangle] -> [(a, Rectangle)]
    forall a b. (a -> b) -> a -> b
    $ (Int -> Rectangle) -> [Int] -> [Rectangle]
    forall a b. (a -> b) -> [a] -> [b]
    map (Rational -> Rational -> Rectangle -> Int -> Rectangle
    placeCenter Rational
    cMasterRatio Rational
    cMultiplier Rectangle
    rectangle)
                               [Int
    cNMasterInt -> Int -> Int
    forall a. Num a => a -> a -> a
    -Int
    1, Int
    cNMasterInt -> Int -> Int
    forall a. Num a => a -> a -> a
    -Int
    2 .. Int
    0]
        rest :: [a] -> [(a, Rectangle)]
        rest :: forall a. [a] -> [(a, Rectangle)]
    rest [a]
    ws = [a] -> [Rectangle] -> [(a, Rectangle)]
    forall a b. [a] -> [b] -> [(a, b)]
    zip [a]
    ws ([Rectangle] -> [(a, Rectangle)])
    -> [Rectangle] -> [(a, Rectangle)]
    forall a b. (a -> b) -> a -> b
    $ (Double -> Int -> Rectangle) -> [Double] -> [Int] -> [Rectangle]
    forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
    zipWith (Rational -> Rational -> Rectangle -> Double -> Int -> Rectangle
    placeSatellite Rational
    cStackRatio Rational
    cMultiplier Rectangle
    rectangle)
                            ((Double -> Double) -> [Double] -> [Double]
    forall a b. (a -> b) -> [a] -> [b]
    map (Double -> Double -> Double
    forall a. Num a => a -> a -> a
    + Double
    cDelta) [Double
    0, Double
    forall a. Floating a => a
    piDouble -> Double -> Double
    forall a. Num a => a -> a -> a
    *Double
    2 Double -> Double -> Double
    forall a. Fractional a => a -> a -> a
    / Int -> Double
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral ([a] -> Int
    forall a. [a] -> Int
    forall (t :: * -> *) a. Foldable t => t a -> Int
    length [a]
    ws) ..])
                            [Int
    0 ..]

    raiseFocus :: [(Window, Rectangle)] -> X [(Window, Rectangle)]
    raiseFocus :: [(Window, Rectangle)] -> X [(Window, Rectangle)]
    raiseFocus [(Window, Rectangle)]
    wrs = do
      Maybe Window
    focused <- (WindowSet -> X (Maybe Window)) -> X (Maybe Window)
    forall a. (WindowSet -> X a) -> X a
    withWindowSet (Maybe Window -> X (Maybe Window)
    forall a. a -> X a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Maybe Window -> X (Maybe Window))
    -> (WindowSet -> Maybe Window) -> WindowSet -> X (Maybe Window)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . WindowSet -> Maybe Window
    forall i l a s sd. StackSet i l a s sd -> Maybe a
    W.peek)
      [(Window, Rectangle)] -> X [(Window, Rectangle)]
    forall a. a -> X a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ([(Window, Rectangle)] -> X [(Window, Rectangle)])
    -> [(Window, Rectangle)] -> X [(Window, Rectangle)]
    forall a b. (a -> b) -> a -> b
    $ case ((Window, Rectangle) -> Bool)
    -> [(Window, Rectangle)] -> Maybe (Window, Rectangle)
    forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
    find ((Maybe Window -> Maybe Window -> Bool
    forall a. Eq a => a -> a -> Bool
    == Maybe Window
    focused) (Maybe Window -> Bool)
    -> ((Window, Rectangle) -> Maybe Window)
    -> (Window, Rectangle)
    -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Window -> Maybe Window
    forall a. a -> Maybe a
    Just (Window -> Maybe Window)
    -> ((Window, Rectangle) -> Window)
    -> (Window, Rectangle)
    -> Maybe Window
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Window, Rectangle) -> Window
    forall a b. (a, b) -> a
    fst) [(Window, Rectangle)]
    wrs of
                 Just (Window, Rectangle)
    x  -> (Window, Rectangle)
    x (Window, Rectangle)
    -> [(Window, Rectangle)] -> [(Window, Rectangle)]
    forall a. a -> [a] -> [a]
    : (Window, Rectangle)
    -> [(Window, Rectangle)] -> [(Window, Rectangle)]
    forall a. Eq a => a -> [a] -> [a]
    delete (Window, Rectangle)
    x [(Window, Rectangle)]
    wrs
                 Maybe (Window, Rectangle)
    Nothing -> [(Window, Rectangle)]
    wrs

    placeCenter :: Rational -> Rational -> Rectangle -> Int -> Rectangle
    placeCenter :: Rational -> Rational -> Rectangle -> Int -> Rectangle
    placeCenter Rational
    ratio Rational
    multiplier (Rectangle Position
    x Position
    y Dimension
    width Dimension
    height) Int
    n = Position -> Position -> Dimension -> Dimension -> Rectangle
    Rectangle Position
    x' Position
    y' Dimension
    width' Dimension
    height'
      where
        m :: Rational
    m = Rational
    ratio Rational -> Rational -> Rational
    forall a. Num a => a -> a -> a
    * Rational
    multiplier Rational -> Int -> Rational
    forall a b. (Num a, Integral b) => a -> b -> a
    ^ Int
    n
        width' :: Dimension
    width' = Rational -> Dimension
    forall b. Integral b => Rational -> b
    forall a b. (RealFrac a, Integral b) => a -> b
    round (Rational
    m Rational -> Rational -> Rational
    forall a. Num a => a -> a -> a
    * Dimension -> Rational
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Dimension
    width)
        height' :: Dimension
    height' = Rational -> Dimension
    forall b. Integral b => Rational -> b
    forall a b. (RealFrac a, Integral b) => a -> b
    round (Rational
    m Rational -> Rational -> Rational
    forall a. Num a => a -> a -> a
    * Dimension -> Rational
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Dimension
    height)
        x' :: Position
    x' = Position
    x Position -> Position -> Position
    forall a. Num a => a -> a -> a
    + Dimension -> Position
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Dimension
    width Dimension -> Dimension -> Dimension
    forall a. Num a => a -> a -> a
    - Dimension
    width') Position -> Position -> Position
    forall a. Integral a => a -> a -> a
    `div` Position
    2
        y' :: Position
    y' = Position
    y Position -> Position -> Position
    forall a. Num a => a -> a -> a
    + Dimension -> Position
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Dimension
    height Dimension -> Dimension -> Dimension
    forall a. Num a => a -> a -> a
    - Dimension
    height') Position -> Position -> Position
    forall a. Integral a => a -> a -> a
    `div` Position
    2

    placeSatellite :: Rational -> Rational -> Rectangle -> Double -> Int -> Rectangle
    placeSatellite :: Rational -> Rational -> Rectangle -> Double -> Int -> Rectangle
    placeSatellite Rational
    ratio Rational
    multiplier (Rectangle Position
    x Position
    y Dimension
    width Dimension
    height) Double
    alpha Int
    n =
        Position -> Position -> Dimension -> Dimension -> Rectangle
    Rectangle Position
    x' Position
    y' Dimension
    width' Dimension
    height'
      where
        m :: Rational
    m = Rational
    ratio Rational -> Rational -> Rational
    forall a. Num a => a -> a -> a
    * Rational
    multiplier Rational -> Int -> Rational
    forall a b. (Num a, Integral b) => a -> b -> a
    ^ Int
    n
        x' :: Position
    x' = Position
    x Position -> Position -> Position
    forall a. Num a => a -> a -> a
    + Double -> Position
    forall b. Integral b => Double -> b
    forall a b. (RealFrac a, Integral b) => a -> b
    round (Double
    rx Double -> Double -> Double
    forall a. Num a => a -> a -> a
    + Double
    rx Double -> Double -> Double
    forall a. Num a => a -> a -> a
    * Double -> Double
    forall a. Floating a => a -> a
    cos Double
    alpha)
        y' :: Position
    y' = Position
    y Position -> Position -> Position
    forall a. Num a => a -> a -> a
    + Double -> Position
    forall b. Integral b => Double -> b
    forall a b. (RealFrac a, Integral b) => a -> b
    round (Double
    ry Double -> Double -> Double
    forall a. Num a => a -> a -> a
    + Double
    ry Double -> Double -> Double
    forall a. Num a => a -> a -> a
    * Double -> Double
    forall a. Floating a => a -> a
    sin Double
    alpha)
        rx :: Double
    rx = Dimension -> Double
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Dimension
    width Dimension -> Dimension -> Dimension
    forall a. Num a => a -> a -> a
    - Dimension
    width') Double -> Double -> Double
    forall a. Fractional a => a -> a -> a
    / Double
    2
        ry :: Double
    ry = Dimension -> Double
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Dimension
    height Dimension -> Dimension -> Dimension
    forall a. Num a => a -> a -> a
    - Dimension
    height') Double -> Double -> Double
    forall a. Fractional a => a -> a -> a
    / Double
    2
        width' :: Dimension
    width' = Rational -> Dimension
    forall b. Integral b => Rational -> b
    forall a b. (RealFrac a, Integral b) => a -> b
    round (Dimension -> Rational
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Dimension
    width Rational -> Rational -> Rational
    forall a. Num a => a -> a -> a
    * Rational
    m)
        height' :: Dimension
    height' = Rational -> Dimension
    forall b. Integral b => Rational -> b
    forall a b. (RealFrac a, Integral b) => a -> b
    round (Dimension -> Rational
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Dimension
    height Rational -> Rational -> Rational
    forall a. Num a => a -> a -> a
    * Rational
    m)