    {-# LANGUAGE ConstraintKinds #-}
    {-# LANGUAGE TypeFamilies    #-}
    {-# LANGUAGE TypeOperators   #-}

    -----------------------------------------------------------------------------
    -- |
    -- Module      :  Diagrams.ThreeD.Align
    -- Copyright   :  (c) 2013 diagrams-lib team (see LICENSE)
    -- License     :  BSD-style (see LICENSE)
    -- Maintainer  :  diagrams-discuss@googlegroups.com
    --
    -- Alignment combinators specialized for three dimensions.  See
    -- "Diagrams.Align" for more general alignment combinators.
    --
    -- The basic idea is that alignment is achieved by moving diagrams'
    -- local origins relative to their envelopes or traces (or some other
    -- sort of boundary).  For example, to align several diagrams along
    -- their tops, we first move their local origins to the upper edge of
    -- their boundary (using e.g. @map 'alignZMax'@), and then put them
    -- together with their local origins along a line (using e.g. 'cat'
    -- from "Diagrams.Combinators").
    --
    -----------------------------------------------------------------------------

    module Diagrams.ThreeD.Align
        ( -- * Absolute alignment
          -- ** Align by envelope
          alignXMin, alignXMax, alignYMin, alignYMax, alignZMin, alignZMax

          -- ** Align by trace
        , snugXMin, snugXMax, snugYMin, snugYMax, snugZMin, snugZMax

          -- * Relative alignment
        , alignX, snugX, alignY, snugY, alignZ, snugZ

          -- * Centering
        , centerX, centerY, centerZ
        , centerXY, centerXZ, centerYZ, centerXYZ
        , snugCenterX, snugCenterY, snugCenterZ
        , snugCenterXY, snugCenterXZ, snugCenterYZ, snugCenterXYZ

        ) where

    import           Diagrams.Core

    import           Diagrams.Align
    import           Diagrams.ThreeD.Types
    import           Diagrams.ThreeD.Vector
    import           Diagrams.TwoD.Align

    -- | Translate the diagram along unitX so that all points have
    --   positive x-values.
    alignXMin :: (InSpace v n a, R1 v, Fractional n, Alignable a, HasOrigin a) => a -> a
    alignXMin :: forall (v :: * -> *) n a.
    (InSpace v n a, R1 v, Fractional n, Alignable a, HasOrigin a) =>
    a -> a
    alignXMin = v n -> a -> a
    forall (v :: * -> *) n a.
    (InSpace v n a, Fractional n, Alignable a, HasOrigin a) =>
    v n -> a -> a
    align v n
    forall (v :: * -> *) n. (R1 v, Additive v, Num n) => v n
    unit_X

    snugXMin :: (InSpace v n a, R1 v, Fractional n, Alignable a, HasOrigin a, Traced a) => a -> a
    snugXMin :: forall (v :: * -> *) n a.
    (InSpace v n a, R1 v, Fractional n, Alignable a, HasOrigin a,
     Traced a) =>
    a -> a
    snugXMin = v n -> a -> a
    forall (v :: * -> *) n a.
    (InSpace v n a, Fractional n, Alignable a, Traced a,
     HasOrigin a) =>
    v n -> a -> a
    snug v n
    forall (v :: * -> *) n. (R1 v, Additive v, Num n) => v n
    unit_X

    -- | Translate the diagram along unitX so that all points have
    -- negative x-values.
    alignXMax :: (InSpace v n a, R1 v, Fractional n, Alignable a, HasOrigin a) => a -> a
    alignXMax :: forall (v :: * -> *) n a.
    (InSpace v n a, R1 v, Fractional n, Alignable a, HasOrigin a) =>
    a -> a
    alignXMax = v n -> a -> a
    forall (v :: * -> *) n a.
    (InSpace v n a, Fractional n, Alignable a, HasOrigin a) =>
    v n -> a -> a
    align v n
    forall (v :: * -> *) n. (R1 v, Additive v, Num n) => v n
    unitX

    snugXMax :: (InSpace v n a, R1 v, Fractional n, Alignable a, HasOrigin a, Traced a) => a -> a
    snugXMax :: forall (v :: * -> *) n a.
    (InSpace v n a, R1 v, Fractional n, Alignable a, HasOrigin a,
     Traced a) =>
    a -> a
    snugXMax = v n -> a -> a
    forall (v :: * -> *) n a.
    (InSpace v n a, Fractional n, Alignable a, Traced a,
     HasOrigin a) =>
    v n -> a -> a
    snug v n
    forall (v :: * -> *) n. (R1 v, Additive v, Num n) => v n
    unitX

    -- | Translate the diagram along unitY so that all points have
    --   positive y-values.
    alignYMin :: (InSpace v n a, R2 v, Fractional n, Alignable a, HasOrigin a) => a -> a
    alignYMin :: forall (v :: * -> *) n a.
    (InSpace v n a, R2 v, Fractional n, Alignable a, HasOrigin a) =>
    a -> a
    alignYMin = v n -> a -> a
    forall (v :: * -> *) n a.
    (InSpace v n a, Fractional n, Alignable a, HasOrigin a) =>
    v n -> a -> a
    align v n
    forall (v :: * -> *) n. (R2 v, Additive v, Num n) => v n
    unit_Y

    snugYMin :: (InSpace v n a, R2 v, Fractional n, Alignable a, HasOrigin a, Traced a) => a -> a
    snugYMin :: forall (v :: * -> *) n a.
    (InSpace v n a, R2 v, Fractional n, Alignable a, HasOrigin a,
     Traced a) =>
    a -> a
    snugYMin = v n -> a -> a
    forall (v :: * -> *) n a.
    (InSpace v n a, Fractional n, Alignable a, Traced a,
     HasOrigin a) =>
    v n -> a -> a
    snug v n
    forall (v :: * -> *) n. (R2 v, Additive v, Num n) => v n
    unit_Y

    -- | Translate the diagram along unitY so that all points have
    -- negative y-values.
    alignYMax :: (InSpace v n a, R2 v, Fractional n, Alignable a, HasOrigin a) => a -> a
    alignYMax :: forall (v :: * -> *) n a.
    (InSpace v n a, R2 v, Fractional n, Alignable a, HasOrigin a) =>
    a -> a
    alignYMax = v n -> a -> a
    forall (v :: * -> *) n a.
    (InSpace v n a, Fractional n, Alignable a, HasOrigin a) =>
    v n -> a -> a
    align v n
    forall (v :: * -> *) n. (R2 v, Additive v, Num n) => v n
    unitY

    snugYMax :: (InSpace v n a, R2 v, Fractional n, Alignable a, HasOrigin a, Traced a) => a -> a
    snugYMax :: forall (v :: * -> *) n a.
    (InSpace v n a, R2 v, Fractional n, Alignable a, HasOrigin a,
     Traced a) =>
    a -> a
    snugYMax = v n -> a -> a
    forall (v :: * -> *) n a.
    (InSpace v n a, Fractional n, Alignable a, Traced a,
     HasOrigin a) =>
    v n -> a -> a
    snug v n
    forall (v :: * -> *) n. (R2 v, Additive v, Num n) => v n
    unitY

    -- | Translate the diagram along unitZ so that all points have
    --   positive z-values.
    alignZMin :: (InSpace v n a, R3 v, Fractional n, Alignable a, HasOrigin a) => a -> a
    alignZMin :: forall (v :: * -> *) n a.
    (InSpace v n a, R3 v, Fractional n, Alignable a, HasOrigin a) =>
    a -> a
    alignZMin = v n -> a -> a
    forall (v :: * -> *) n a.
    (InSpace v n a, Fractional n, Alignable a, HasOrigin a) =>
    v n -> a -> a
    align v n
    forall (v :: * -> *) n. (R3 v, Additive v, Num n) => v n
    unit_Z

    snugZMin :: (InSpace v n a, R3 v, Fractional n, Alignable a, HasOrigin a, Traced a) => a -> a
    snugZMin :: forall (v :: * -> *) n a.
    (InSpace v n a, R3 v, Fractional n, Alignable a, HasOrigin a,
     Traced a) =>
    a -> a
    snugZMin = v n -> a -> a
    forall (v :: * -> *) n a.
    (InSpace v n a, Fractional n, Alignable a, Traced a,
     HasOrigin a) =>
    v n -> a -> a
    snug v n
    forall (v :: * -> *) n. (R3 v, Additive v, Num n) => v n
    unit_Z

    -- | Translate the diagram along unitZ so that all points have
    -- negative z-values.
    alignZMax :: (InSpace v n a, R3 v, Fractional n, Alignable a, HasOrigin a) => a -> a
    alignZMax :: forall (v :: * -> *) n a.
    (InSpace v n a, R3 v, Fractional n, Alignable a, HasOrigin a) =>
    a -> a
    alignZMax = v n -> a -> a
    forall (v :: * -> *) n a.
    (InSpace v n a, Fractional n, Alignable a, HasOrigin a) =>
    v n -> a -> a
    align v n
    forall (v :: * -> *) n. (R3 v, Additive v, Num n) => v n
    unitZ

    snugZMax :: (InSpace v n a, R3 v, Fractional n, Alignable a, HasOrigin a, Traced a) => a -> a
    snugZMax :: forall (v :: * -> *) n a.
    (InSpace v n a, R3 v, Fractional n, Alignable a, HasOrigin a,
     Traced a) =>
    a -> a
    snugZMax = v n -> a -> a
    forall (v :: * -> *) n a.
    (InSpace v n a, Fractional n, Alignable a, Traced a,
     HasOrigin a) =>
    v n -> a -> a
    snug v n
    forall (v :: * -> *) n. (R3 v, Additive v, Num n) => v n
    unitZ

    -- | Like 'alignX', but moving the local origin in the Z direction, with an
    --   argument of @1@ corresponding to the top edge and @(-1)@ corresponding
    --   to the bottom edge.
    alignZ :: (InSpace v n a, R3 v, Fractional n, Alignable a, HasOrigin a) => n -> a -> a
    alignZ :: forall (v :: * -> *) n a.
    (InSpace v n a, R3 v, Fractional n, Alignable a, HasOrigin a) =>
    n -> a -> a
    alignZ = v n -> n -> a -> a
    forall a (v :: * -> *) n.
    (Alignable a, InSpace v n a, Fractional n, HasOrigin a) =>
    v n -> n -> a -> a
    forall (v :: * -> *) n.
    (InSpace v n a, Fractional n, HasOrigin a) =>
    v n -> n -> a -> a
    alignBy v n
    forall (v :: * -> *) n. (R3 v, Additive v, Num n) => v n
    unitZ

    -- | See the documentation for 'alignZ'.
    snugZ :: (V a ~ v, N a ~ n, Alignable a, Traced a, HasOrigin a,
              R3 v, Fractional n) => n -> a -> a
    snugZ :: forall a (v :: * -> *) n.
    (V a ~ v, N a ~ n, Alignable a, Traced a, HasOrigin a, R3 v,
     Fractional n) =>
    n -> a -> a
    snugZ = v n -> n -> a -> a
    forall (v :: * -> *) n a.
    (InSpace v n a, Fractional n, Alignable a, Traced a,
     HasOrigin a) =>
    v n -> n -> a -> a
    snugBy v n
    forall (v :: * -> *) n. (R3 v, Additive v, Num n) => v n
    unitZ

    -- | Center the local origin along the Z-axis.
    centerZ :: (InSpace v n a, R3 v, Fractional n, Alignable a, HasOrigin a) => a -> a
    centerZ :: forall (v :: * -> *) n a.
    (InSpace v n a, R3 v, Fractional n, Alignable a, HasOrigin a) =>
    a -> a
    centerZ = v n -> n -> a -> a
    forall a (v :: * -> *) n.
    (Alignable a, InSpace v n a, Fractional n, HasOrigin a) =>
    v n -> n -> a -> a
    forall (v :: * -> *) n.
    (InSpace v n a, Fractional n, HasOrigin a) =>
    v n -> n -> a -> a
    alignBy v n
    forall (v :: * -> *) n. (R3 v, Additive v, Num n) => v n
    unitZ n
    0

    snugCenterZ :: (InSpace v n a, R3 v, Fractional n, Alignable a, HasOrigin a, Traced a) => a -> a
    snugCenterZ :: forall (v :: * -> *) n a.
    (InSpace v n a, R3 v, Fractional n, Alignable a, HasOrigin a,
     Traced a) =>
    a -> a
    snugCenterZ = v n -> n -> a -> a
    forall (v :: * -> *) n a.
    (InSpace v n a, Fractional n, Alignable a, Traced a,
     HasOrigin a) =>
    v n -> n -> a -> a
    snugBy v n
    forall (v :: * -> *) n. (R3 v, Additive v, Num n) => v n
    unitZ n
    0

    -- | Center along both the X- and Z-axes.
    centerXZ :: (InSpace v n a, R3 v, Fractional n, Alignable a, HasOrigin a) => a -> a
    centerXZ :: forall (v :: * -> *) n a.
    (InSpace v n a, R3 v, Fractional n, Alignable a, HasOrigin a) =>
    a -> a
    centerXZ = a -> a
    forall (v :: * -> *) n a.
    (InSpace v n a, R1 v, Fractional n, Alignable a, HasOrigin a) =>
    a -> a
    centerX (a -> a) -> (a -> a) -> a -> a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . a -> a
    forall (v :: * -> *) n a.
    (InSpace v n a, R3 v, Fractional n, Alignable a, HasOrigin a) =>
    a -> a
    centerZ

    snugCenterXZ :: (InSpace v n a, R3 v, Fractional n, Alignable a, HasOrigin a, Traced a) => a -> a
    snugCenterXZ :: forall (v :: * -> *) n a.
    (InSpace v n a, R3 v, Fractional n, Alignable a, HasOrigin a,
     Traced a) =>
    a -> a
    snugCenterXZ = a -> a
    forall (v :: * -> *) n a.
    (InSpace v n a, R1 v, Fractional n, Alignable a, Traced a,
     HasOrigin a) =>
    a -> a
    snugCenterX (a -> a) -> (a -> a) -> a -> a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . a -> a
    forall (v :: * -> *) n a.
    (InSpace v n a, R3 v, Fractional n, Alignable a, HasOrigin a,
     Traced a) =>
    a -> a
    snugCenterZ

    -- | Center along both the Y- and Z-axes.
    centerYZ :: (InSpace v n a, R3 v, Fractional n, Alignable a, HasOrigin a) => a -> a
    centerYZ :: forall (v :: * -> *) n a.
    (InSpace v n a, R3 v, Fractional n, Alignable a, HasOrigin a) =>
    a -> a
    centerYZ = a -> a
    forall (v :: * -> *) n a.
    (InSpace v n a, R3 v, Fractional n, Alignable a, HasOrigin a) =>
    a -> a
    centerZ (a -> a) -> (a -> a) -> a -> a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . a -> a
    forall (v :: * -> *) n a.
    (InSpace v n a, R2 v, Fractional n, Alignable a, HasOrigin a) =>
    a -> a
    centerY

    snugCenterYZ :: (InSpace v n a, R3 v, Fractional n, Alignable a, HasOrigin a, Traced a) => a -> a
    snugCenterYZ :: forall (v :: * -> *) n a.
    (InSpace v n a, R3 v, Fractional n, Alignable a, HasOrigin a,
     Traced a) =>
    a -> a
    snugCenterYZ = a -> a
    forall (v :: * -> *) n a.
    (InSpace v n a, R3 v, Fractional n, Alignable a, HasOrigin a,
     Traced a) =>
    a -> a
    snugCenterZ (a -> a) -> (a -> a) -> a -> a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . a -> a
    forall (v :: * -> *) n a.
    (InSpace v n a, R2 v, Fractional n, Alignable a, Traced a,
     HasOrigin a) =>
    a -> a
    snugCenterY

    -- | Center an object in three dimensions.
    centerXYZ :: (InSpace v n a, R3 v, Fractional n, Alignable a, HasOrigin a) => a -> a
    centerXYZ :: forall (v :: * -> *) n a.
    (InSpace v n a, R3 v, Fractional n, Alignable a, HasOrigin a) =>
    a -> a
    centerXYZ = a -> a
    forall (v :: * -> *) n a.
    (InSpace v n a, R1 v, Fractional n, Alignable a, HasOrigin a) =>
    a -> a
    centerX (a -> a) -> (a -> a) -> a -> a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . a -> a
    forall (v :: * -> *) n a.
    (InSpace v n a, R2 v, Fractional n, Alignable a, HasOrigin a) =>
    a -> a
    centerY (a -> a) -> (a -> a) -> a -> a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . a -> a
    forall (v :: * -> *) n a.
    (InSpace v n a, R3 v, Fractional n, Alignable a, HasOrigin a) =>
    a -> a
    centerZ

    snugCenterXYZ :: (InSpace v n a, R3 v, Fractional n, Alignable a, HasOrigin a, Traced a) => a -> a
    snugCenterXYZ :: forall (v :: * -> *) n a.
    (InSpace v n a, R3 v, Fractional n, Alignable a, HasOrigin a,
     Traced a) =>
    a -> a
    snugCenterXYZ = a -> a
    forall (v :: * -> *) n a.
    (InSpace v n a, R1 v, Fractional n, Alignable a, Traced a,
     HasOrigin a) =>
    a -> a
    snugCenterX (a -> a) -> (a -> a) -> a -> a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . a -> a
    forall (v :: * -> *) n a.
    (InSpace v n a, R2 v, Fractional n, Alignable a, Traced a,
     HasOrigin a) =>
    a -> a
    snugCenterY (a -> a) -> (a -> a) -> a -> a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . a -> a
    forall (v :: * -> *) n a.
    (InSpace v n a, R3 v, Fractional n, Alignable a, HasOrigin a,
     Traced a) =>
    a -> a
    snugCenterZ