{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE ConstrainedClassMethods #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}
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.Maybe (fromMaybe)
import Data.Ord (comparing)
import Data.Traversable
import Prelude
import qualified Data.Foldable as F
import qualified Data.Map as M
import qualified Data.Set as S
import Linear.Affine
import Linear.Metric
import Linear.Vector
class Alignable a where
alignBy' :: (InSpace v n a, Fractional n, HasOrigin a)
=> (v n -> a -> Point v n) -> v n -> n -> a -> a
alignBy' = (v n -> a -> Point v n) -> v n -> n -> a -> a
forall (v :: * -> *) n a.
(InSpace v n a, Fractional n, HasOrigin a) =>
(v n -> a -> Point v n) -> v n -> n -> a -> a
alignBy'Default
defaultBoundary :: (V a ~ v, N a ~ n) => v n -> a -> Point v n
alignBy :: (InSpace v n a, Fractional n, HasOrigin a)
=> v n -> n -> a -> a
alignBy = (v n -> a -> Point v n) -> v n -> n -> a -> a
forall a (v :: * -> *) n.
(Alignable a, InSpace v n a, Fractional n, HasOrigin a) =>
(v n -> a -> Point v n) -> v n -> n -> a -> a
alignBy' v n -> a -> Point v n
forall a (v :: * -> *) n.
(Alignable a, V a ~ v, N a ~ n) =>
v n -> a -> Point v n
defaultBoundary
alignBy'Default :: (InSpace v n a, Fractional n, HasOrigin a)
=> (v n -> a -> Point v n) -> v n -> n -> a -> a
alignBy'Default :: (v n -> a -> Point v n) -> v n -> n -> a -> a
alignBy'Default v n -> a -> Point v n
boundary v n
v n
d a
a = Point (V a) (N a) -> a -> a
forall t. HasOrigin t => Point (V t) (N t) -> t -> t
moveOriginTo (n -> Point v n -> Point v n -> Point v n
forall (f :: * -> *) a.
(Additive f, Num a) =>
a -> f a -> f a -> f a
lerp ((n
d n -> n -> n
forall a. Num a => a -> a -> a
+ n
1) n -> n -> n
forall a. Fractional a => a -> a -> a
/ n
2)
(v n -> a -> Point v n
boundary v n
v a
a)
(v n -> a -> Point v n
boundary (v n -> v n
forall (f :: * -> *) a. (Functor f, Num a) => f a -> f a
negated v n
v) a
a)
) a
a
{-# ANN alignBy'Default ("HLint: ignore Use camelCase" :: String) #-}
envelopeBoundary :: (V a ~ v, N a ~ n, Enveloped a) => v n -> a -> Point v n
envelopeBoundary :: v n -> a -> Point v n
envelopeBoundary = v n -> a -> Point v n
forall a (v :: * -> *) n.
(V a ~ v, N a ~ n, Enveloped a) =>
v n -> a -> Point v n
envelopeP
traceBoundary :: (V a ~ v, N a ~ n, Num n, Traced a) => v n -> a -> Point v n
traceBoundary :: v n -> a -> Point v n
traceBoundary v n
v a
a = Point v n -> Maybe (Point v n) -> Point v n
forall a. a -> Maybe a -> a
fromMaybe Point v n
forall (f :: * -> *) a. (Additive f, Num a) => Point f a
origin (Point (V a) n -> V a n -> a -> Maybe (Point (V a) n)
forall n a.
(n ~ N a, Num n, Traced a) =>
Point (V a) n -> V a n -> a -> Maybe (Point (V a) n)
maxTraceP Point (V a) n
forall (f :: * -> *) a. (Additive f, Num a) => Point f a
origin v n
V a n
v a
a)
combineBoundaries
:: (InSpace v n a, Metric v, Ord n, F.Foldable f)
=> (v n -> a -> Point v n) -> v n -> f a -> Point v n
combineBoundaries :: (v n -> a -> Point v n) -> v n -> f a -> Point v n
combineBoundaries v n -> a -> Point v n
b v n
v f a
fa
= v n -> a -> Point v n
b v n
v (a -> Point v n) -> a -> Point v n
forall a b. (a -> b) -> a -> b
$ (a -> a -> Ordering) -> f a -> a
forall (t :: * -> *) a.
Foldable t =>
(a -> a -> Ordering) -> t a -> a
F.maximumBy ((a -> n) -> a -> a -> Ordering
forall a b. Ord a => (b -> a) -> b -> b -> Ordering
comparing (v n -> v n -> n
forall (f :: * -> *) a. (Metric f, Num a) => f a -> f a -> a
dot v n
v (v n -> n) -> (a -> v n) -> a -> n
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Point v n -> Point v n -> Diff (Point v) n
forall (p :: * -> *) a. (Affine p, Num a) => p a -> p a -> Diff p a
.-.Point v n
forall (f :: * -> *) a. (Additive f, Num a) => Point f a
origin) (Point v n -> v n) -> (a -> Point v n) -> a -> v n
forall b c a. (b -> c) -> (a -> b) -> a -> c
. v n -> a -> Point v n
b v n
v)) f a
fa
instance (Metric v, OrderedField n) => Alignable (Envelope v n) where
defaultBoundary :: v n -> Envelope v n -> Point v n
defaultBoundary = v n -> Envelope v n -> Point v n
forall a (v :: * -> *) n.
(V a ~ v, N a ~ n, Enveloped a) =>
v n -> a -> Point v n
envelopeBoundary
instance (Metric v, OrderedField n) => Alignable (Trace v n) where
defaultBoundary :: v n -> Trace v n -> Point v n
defaultBoundary = v n -> Trace v n -> Point v n
forall a (v :: * -> *) n.
(V a ~ v, N a ~ n, Num n, Traced a) =>
v n -> a -> Point v n
traceBoundary
instance (V b ~ v, N b ~ n, Metric v, OrderedField n, Alignable b) => Alignable [b] where
defaultBoundary :: v n -> [b] -> Point v n
defaultBoundary = (v n -> b -> Point v n) -> v n -> [b] -> Point v n
forall (v :: * -> *) n a (f :: * -> *).
(InSpace v n a, Metric v, Ord n, Foldable f) =>
(v n -> a -> Point v n) -> v n -> f a -> Point v n
combineBoundaries v n -> b -> Point v n
forall a (v :: * -> *) n.
(Alignable a, V a ~ v, N a ~ n) =>
v n -> a -> Point v n
defaultBoundary
instance (V b ~ v, N b ~ n, Metric v, OrderedField n, Alignable b)
=> Alignable (S.Set b) where
defaultBoundary :: v n -> Set b -> Point v n
defaultBoundary = (v n -> b -> Point v n) -> v n -> Set b -> Point v n
forall (v :: * -> *) n a (f :: * -> *).
(InSpace v n a, Metric v, Ord n, Foldable f) =>
(v n -> a -> Point v n) -> v n -> f a -> Point v n
combineBoundaries v n -> b -> Point v n
forall a (v :: * -> *) n.
(Alignable a, V a ~ v, N a ~ n) =>
v n -> a -> Point v n
defaultBoundary
instance (V b ~ v, N b ~ n, Metric v, OrderedField n, Alignable b)
=> Alignable (M.Map k b) where
defaultBoundary :: v n -> Map k b -> Point v n
defaultBoundary = (v n -> b -> Point v n) -> v n -> Map k b -> Point v n
forall (v :: * -> *) n a (f :: * -> *).
(InSpace v n a, Metric v, Ord n, Foldable f) =>
(v n -> a -> Point v n) -> v n -> f a -> Point v n
combineBoundaries v n -> b -> Point v n
forall a (v :: * -> *) n.
(Alignable a, V a ~ v, N a ~ n) =>
v n -> a -> Point v n
defaultBoundary
instance (Metric v, OrderedField n, Monoid' m)
=> Alignable (QDiagram b v n m) where
defaultBoundary :: v n -> QDiagram b v n m -> Point v n
defaultBoundary = v n -> QDiagram b v n m -> Point v n
forall a (v :: * -> *) n.
(V a ~ v, N a ~ n, Enveloped a) =>
v n -> a -> Point v n
envelopeBoundary
instance (InSpace v n a, HasOrigin a, Alignable a) => Alignable (b -> a) where
alignBy :: v n -> n -> (b -> a) -> b -> a
alignBy v n
v n
d b -> a
f b
b = v n -> n -> a -> a
forall a (v :: * -> *) n.
(Alignable a, InSpace v n a, Fractional n, HasOrigin a) =>
v n -> n -> a -> a
alignBy v n
v n
d (b -> a
f b
b)
defaultBoundary :: v n -> (b -> a) -> Point v n
defaultBoundary v n
_ b -> a
_ = Point v n
forall (f :: * -> *) a. (Additive f, Num a) => Point f a
origin
align :: (InSpace v n a, Fractional n, Alignable a, HasOrigin a) => v n -> a -> a
align :: v n -> a -> a
align v n
v = v n -> n -> a -> a
forall a (v :: * -> *) n.
(Alignable a, InSpace v n a, Fractional n, HasOrigin a) =>
v n -> n -> a -> a
alignBy v n
v n
1
snugBy :: (InSpace v n a, Fractional n, Alignable a, Traced a, HasOrigin a)
=> v n -> n -> a -> a
snugBy :: v n -> n -> a -> a
snugBy = (v n -> a -> Point v n) -> v n -> n -> a -> a
forall a (v :: * -> *) n.
(Alignable a, InSpace v n a, Fractional n, HasOrigin a) =>
(v n -> a -> Point v n) -> v n -> n -> a -> a
alignBy' v n -> a -> Point v n
forall a (v :: * -> *) n.
(V a ~ v, N a ~ n, Num n, Traced a) =>
v n -> a -> Point v n
traceBoundary
snug :: (InSpace v n a, Fractional n, Alignable a, Traced a, HasOrigin a)
=> v n -> a -> a
snug :: v n -> a -> a
snug v n
v = 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
v n
1
centerV :: (InSpace v n a, Fractional n, Alignable a, HasOrigin a) => v n -> a -> a
centerV :: v n -> a -> a
centerV v n
v = v n -> n -> a -> a
forall a (v :: * -> *) n.
(Alignable a, InSpace v n a, Fractional n, HasOrigin a) =>
v n -> n -> a -> a
alignBy v n
v n
0
center :: (InSpace v n a, Fractional n, Traversable v, Alignable a, HasOrigin a) => a -> a
center :: a -> a
center = [a -> a] -> a -> a
forall a. [a -> a] -> a -> a
applyAll [a -> a]
fs
where
fs :: [a -> a]
fs = (V a (N a) -> a -> a) -> [V a (N a)] -> [a -> a]
forall a b. (a -> b) -> [a] -> [b]
map V a (N a) -> a -> a
forall (v :: * -> *) n a.
(InSpace v n a, Fractional n, Alignable a, HasOrigin a) =>
v n -> a -> a
centerV [V a (N a)]
forall (t :: * -> *) a. (Additive t, Traversable t, Num a) => [t a]
basis
snugCenterV
:: (InSpace v n a, Fractional n, Alignable a, Traced a, HasOrigin a)
=> v n -> a -> a
snugCenterV :: v n -> a -> a
snugCenterV v n
v = (v n -> a -> Point v n) -> v n -> n -> a -> a
forall a (v :: * -> *) n.
(Alignable a, InSpace v n a, Fractional n, HasOrigin a) =>
(v n -> a -> Point v n) -> v n -> n -> a -> a
alignBy' v n -> a -> Point v n
forall a (v :: * -> *) n.
(V a ~ v, N a ~ n, Num n, Traced a) =>
v n -> a -> Point v n
traceBoundary v n
v n
0
snugCenter :: (InSpace v n a, Traversable v, Fractional n, Alignable a, HasOrigin a, Traced a)
=> a -> a
snugCenter :: a -> a
snugCenter = [a -> a] -> a -> a
forall a. [a -> a] -> a -> a
applyAll [a -> a]
fs
where
fs :: [a -> a]
fs = (V a (N a) -> a -> a) -> [V a (N a)] -> [a -> a]
forall a b. (a -> b) -> [a] -> [b]
map V a (N a) -> a -> a
forall (v :: * -> *) n a.
(InSpace v n a, Fractional n, Alignable a, Traced a,
HasOrigin a) =>
v n -> a -> a
snugCenterV [V a (N a)]
forall (t :: * -> *) a. (Additive t, Traversable t, Num a) => [t a]
basis
{-# ANN module ("HLint: ignore Use camelCase" :: String) #-}