module Diagrams.Align
(
Alignable(..)
, alignBy'Default
, envelopeBoundary
, traceBoundary
, align
, snug
, centerV, center
, snugBy
, snugCenterV, snugCenter
) where
import Diagrams.Core
import Diagrams.Util (applyAll)
import Data.AffineSpace (alerp, (.-.))
import Data.VectorSpace
import Data.Maybe (fromMaybe)
import Data.Ord (comparing)
import qualified Data.Map as M
import qualified Data.Set as S
import qualified Data.Foldable as F
class Alignable a where
alignBy' :: ( HasOrigin a, AdditiveGroup (V a), Num (Scalar (V a))
, Fractional (Scalar (V a)))
=> (V a -> a -> Point (V a)) -> V a -> Scalar (V a) -> a -> a
alignBy' = alignBy'Default
defaultBoundary :: V a -> a -> Point (V a)
alignBy :: (HasOrigin a, Num (Scalar (V a)), Fractional (Scalar (V a)))
=> V a -> Scalar (V a) -> a -> a
alignBy = alignBy' defaultBoundary
alignBy'Default :: ( HasOrigin a, AdditiveGroup (V a), Num (Scalar (V a))
, Fractional (Scalar (V a)))
=> (V a -> a -> Point (V a)) -> V a -> Scalar (V a) -> a -> a
alignBy'Default boundary v d a = moveOriginTo (alerp (boundary (negateV v) a)
(boundary v a)
((d + 1) / 2)) a
envelopeBoundary :: Enveloped a => V a -> a -> Point (V a)
envelopeBoundary = envelopeP
traceBoundary :: Traced a => V a -> a -> Point (V a)
traceBoundary v a = fromMaybe origin (maxTraceP origin v a)
combineBoundaries
:: (F.Foldable f, InnerSpace (V a), Ord (Scalar (V a)))
=> (V a -> a -> Point (V a)) -> (V a -> f a -> Point (V a))
combineBoundaries b v fa
= b v $ F.maximumBy (comparing (magnitudeSq . (.-. origin) . b v)) fa
instance (InnerSpace v, OrderedField (Scalar v)) => Alignable (Envelope v) where
defaultBoundary = envelopeBoundary
instance (InnerSpace v, OrderedField (Scalar v)) => Alignable (Trace v) where
defaultBoundary = traceBoundary
instance (InnerSpace (V b), Ord (Scalar (V b)), Alignable b)
=> Alignable [b] where
defaultBoundary = combineBoundaries defaultBoundary
instance (InnerSpace (V b), Ord (Scalar (V b)), Alignable b)
=> Alignable (S.Set b) where
defaultBoundary = combineBoundaries defaultBoundary
instance (InnerSpace (V b), Ord (Scalar (V b)), Alignable b)
=> Alignable (M.Map k b) where
defaultBoundary = combineBoundaries defaultBoundary
instance ( HasLinearMap v, InnerSpace v, OrderedField (Scalar v)
, Monoid' m
) => Alignable (QDiagram b v m) where
defaultBoundary = envelopeBoundary
instance (HasOrigin a, Alignable a) => Alignable (b -> a) where
alignBy v d f b = alignBy v d (f b)
defaultBoundary _ _ = origin
align :: ( Alignable a, HasOrigin a, Num (Scalar (V a))
, Fractional (Scalar (V a))) => V a -> a -> a
align v = alignBy v 1
snugBy :: (Alignable a, Traced a, HasOrigin a, Num (Scalar (V a)), Fractional (Scalar (V a)))
=> V a -> Scalar (V a) -> a -> a
snugBy = alignBy' traceBoundary
snug :: (Fractional (Scalar (V a)), Alignable a, Traced a, HasOrigin a)
=> V a -> a -> a
snug v = snugBy v 1
centerV :: ( Alignable a, HasOrigin a, Num (Scalar (V a))
, Fractional (Scalar (V a))) => V a -> a -> a
centerV v = alignBy v 0
center :: ( HasLinearMap (V a), Alignable a, HasOrigin a, Num (Scalar (V a)),
Fractional (Scalar (V a))) => a -> a
center d = applyAll fs d
where
fs = map centerV basis
snugCenterV
:: (Fractional (Scalar (V a)), Alignable a, Traced a, HasOrigin a)
=> V a -> a -> a
snugCenterV v = (alignBy' traceBoundary) v 0
snugCenter :: ( HasLinearMap (V a), Alignable a, HasOrigin a, Num (Scalar (V a)),
Fractional (Scalar (V a)), Traced a) => a -> a
snugCenter d = applyAll fs d
where
fs = map snugCenterV basis