packages feed

diagrams-core 0.2 → 0.3

raw patch · 9 files changed

+334/−137 lines, 9 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Graphics.Rendering.Diagrams: class IsName n
- Graphics.Rendering.Diagrams.Core: instance [overlap ok] HasLinearMap v => Backend () v
- Graphics.Rendering.Diagrams.Core: instance [overlap ok] Monoid (Render () v)
- Graphics.Rendering.Diagrams.Names: IName :: Integer -> AName
- Graphics.Rendering.Diagrams.Names: SName :: String -> AName
- Graphics.Rendering.Diagrams.Names: class IsName n
- Graphics.Rendering.Diagrams.Names: instance [overlap ok] IsName Int
- Graphics.Rendering.Diagrams.Names: instance [overlap ok] IsName Integer
- Graphics.Rendering.Diagrams.Names: instance [overlap ok] IsName Name
- Graphics.Rendering.Diagrams.Names: instance [overlap ok] IsName String
- Graphics.Rendering.Diagrams.Names: instance [overlap ok] VectorSpace v => HasOrigin (NameMap v)
- Graphics.Rendering.Diagrams.Transform: instance HasLinearMap v => Transformable (NameMap v)
- Graphics.Rendering.Diagrams.UDTree: applyU :: (Monoid u, Action d u) => u -> UDTree u d a -> UDTree u d a
+ Graphics.Rendering.Diagrams: (.>) :: (Atomic a1, Atomic a2) => a1 -> a2 -> Name
+ Graphics.Rendering.Diagrams: TransInv :: t -> TransInv t
+ Graphics.Rendering.Diagrams: boundaryFrom :: Boundable a => Point (V a) -> V a -> a -> Point (V a)
+ Graphics.Rendering.Diagrams: boundaryV :: Boundable a => V a -> a -> V a
+ Graphics.Rendering.Diagrams: class (Typeable a, Ord a, Show a) => Atomic a
+ Graphics.Rendering.Diagrams: data AName
+ Graphics.Rendering.Diagrams: fromNamesB :: Atomic a => [(a, (Point v, Bounds v))] -> NameMap v
+ Graphics.Rendering.Diagrams: newtype TransInv t
+ Graphics.Rendering.Diagrams: toAName :: Atomic a => a -> AName
+ Graphics.Rendering.Diagrams: unTransInv :: TransInv t -> t
+ Graphics.Rendering.Diagrams: withAName :: (Atomic a, AdditiveGroup (Scalar v), Floating (Scalar v), InnerSpace v, HasLinearMap v) => a -> (Point v -> AnnDiagram b v m -> AnnDiagram b v m) -> AnnDiagram b v m -> AnnDiagram b v m
+ Graphics.Rendering.Diagrams: withANameB :: (Atomic a, AdditiveGroup (Scalar v), Floating (Scalar v), InnerSpace v, HasLinearMap v) => a -> (Point v -> Bounds v -> AnnDiagram b v m -> AnnDiagram b v m) -> AnnDiagram b v m -> AnnDiagram b v m
+ Graphics.Rendering.Diagrams: withNameB :: (AdditiveGroup (Scalar v), Floating (Scalar v), InnerSpace v, HasLinearMap v) => Name -> (Point v -> Bounds v -> AnnDiagram b v m -> AnnDiagram b v m) -> AnnDiagram b v m -> AnnDiagram b v m
+ Graphics.Rendering.Diagrams.Bounds: boundaryFrom :: Boundable a => Point (V a) -> V a -> a -> Point (V a)
+ Graphics.Rendering.Diagrams.Bounds: boundaryV :: Boundable a => V a -> a -> V a
+ Graphics.Rendering.Diagrams.Bounds: instance Show (Bounds v)
+ Graphics.Rendering.Diagrams.Core: withAName :: (Atomic a, AdditiveGroup (Scalar v), Floating (Scalar v), InnerSpace v, HasLinearMap v) => a -> (Point v -> AnnDiagram b v m -> AnnDiagram b v m) -> AnnDiagram b v m -> AnnDiagram b v m
+ Graphics.Rendering.Diagrams.Core: withANameB :: (Atomic a, AdditiveGroup (Scalar v), Floating (Scalar v), InnerSpace v, HasLinearMap v) => a -> (Point v -> Bounds v -> AnnDiagram b v m -> AnnDiagram b v m) -> AnnDiagram b v m -> AnnDiagram b v m
+ Graphics.Rendering.Diagrams.Core: withNameB :: (AdditiveGroup (Scalar v), Floating (Scalar v), InnerSpace v, HasLinearMap v) => Name -> (Point v -> Bounds v -> AnnDiagram b v m -> AnnDiagram b v m) -> AnnDiagram b v m -> AnnDiagram b v m
+ Graphics.Rendering.Diagrams.Monoids: Deletable :: Int -> m -> Int -> Deletable m
+ Graphics.Rendering.Diagrams.Monoids: data Deletable m
+ Graphics.Rendering.Diagrams.Monoids: deleteL :: Monoid m => Deletable m
+ Graphics.Rendering.Diagrams.Monoids: deleteR :: Monoid m => Deletable m
+ Graphics.Rendering.Diagrams.Monoids: instance Functor Deletable
+ Graphics.Rendering.Diagrams.Monoids: instance Monoid m => Monoid (Deletable m)
+ Graphics.Rendering.Diagrams.Monoids: toDeletable :: m -> Deletable m
+ Graphics.Rendering.Diagrams.Monoids: unDelete :: Deletable m -> m
+ Graphics.Rendering.Diagrams.Names: (.>) :: (Atomic a1, Atomic a2) => a1 -> a2 -> Name
+ Graphics.Rendering.Diagrams.Names: AName :: a -> AName
+ Graphics.Rendering.Diagrams.Names: class (Typeable a, Ord a, Show a) => Atomic a
+ Graphics.Rendering.Diagrams.Names: fromNamesB :: Atomic a => [(a, (Point v, Bounds v))] -> NameMap v
+ Graphics.Rendering.Diagrams.Names: instance [overlap ok] (AdditiveGroup (Scalar v), Fractional (Scalar v), InnerSpace v) => HasOrigin (NameMap v)
+ Graphics.Rendering.Diagrams.Names: instance [overlap ok] (AdditiveGroup (Scalar v), InnerSpace v, Floating (Scalar v), HasLinearMap v) => Transformable (NameMap v)
+ Graphics.Rendering.Diagrams.Names: instance [overlap ok] (Atomic a, Atomic b) => Atomic (a, b)
+ Graphics.Rendering.Diagrams.Names: instance [overlap ok] (Atomic a, Atomic b, Atomic c) => Atomic (a, b, c)
+ Graphics.Rendering.Diagrams.Names: instance [overlap ok] Atomic ()
+ Graphics.Rendering.Diagrams.Names: instance [overlap ok] Atomic AName
+ Graphics.Rendering.Diagrams.Names: instance [overlap ok] Atomic Bool
+ Graphics.Rendering.Diagrams.Names: instance [overlap ok] Atomic Char
+ Graphics.Rendering.Diagrams.Names: instance [overlap ok] Atomic Double
+ Graphics.Rendering.Diagrams.Names: instance [overlap ok] Atomic Float
+ Graphics.Rendering.Diagrams.Names: instance [overlap ok] Atomic Int
+ Graphics.Rendering.Diagrams.Names: instance [overlap ok] Atomic Integer
+ Graphics.Rendering.Diagrams.Names: instance [overlap ok] Atomic String
+ Graphics.Rendering.Diagrams.Names: instance [overlap ok] Atomic a => Atomic [a]
+ Graphics.Rendering.Diagrams.Names: instance [overlap ok] Show v => Show (NameMap v)
+ Graphics.Rendering.Diagrams.Names: instance [overlap ok] Typeable AName
+ Graphics.Rendering.Diagrams.Names: toAName :: Atomic a => a -> AName
+ Graphics.Rendering.Diagrams.Transform: TransInv :: t -> TransInv t
+ Graphics.Rendering.Diagrams.Transform: instance HasLinearMap v => HasOrigin (Transformation v)
+ Graphics.Rendering.Diagrams.Transform: instance HasLinearMap v => Transformable (Transformation v)
+ Graphics.Rendering.Diagrams.Transform: instance Monoid t => Monoid (TransInv t)
+ Graphics.Rendering.Diagrams.Transform: instance Show t => Show (TransInv t)
+ Graphics.Rendering.Diagrams.Transform: instance Transformable m => Transformable (Deletable m)
+ Graphics.Rendering.Diagrams.Transform: instance Transformable t => Transformable (TransInv t)
+ Graphics.Rendering.Diagrams.Transform: instance VectorSpace (V t) => HasOrigin (TransInv t)
+ Graphics.Rendering.Diagrams.Transform: newtype TransInv t
+ Graphics.Rendering.Diagrams.Transform: unTransInv :: TransInv t -> t
+ Graphics.Rendering.Diagrams.UDTree: applyUpost :: (Monoid u, Action d u) => u -> UDTree u d a -> UDTree u d a
+ Graphics.Rendering.Diagrams.UDTree: applyUpre :: (Monoid u, Action d u) => u -> UDTree u d a -> UDTree u d a
- Graphics.Rendering.Diagrams: (|>) :: (Qualifiable a, IsName n) => n -> a -> a
+ Graphics.Rendering.Diagrams: (|>) :: (Qualifiable q, Atomic a) => a -> q -> q
- Graphics.Rendering.Diagrams: (||>) :: (IsName n, IsName m) => n -> m -> Name
+ Graphics.Rendering.Diagrams: (||>) :: Qualifiable q => Name -> q -> q
- Graphics.Rendering.Diagrams: class Qualifiable a
+ Graphics.Rendering.Diagrams: class Qualifiable q
- Graphics.Rendering.Diagrams: fromNames :: IsName n => [(n, Point v)] -> NameMap v
+ Graphics.Rendering.Diagrams: fromNames :: (AdditiveGroup (Scalar v), Ord (Scalar v), Atomic a) => [(a, Point v)] -> NameMap v
- Graphics.Rendering.Diagrams: lookupN :: IsName n => n -> NameMap v -> Maybe [Point v]
+ Graphics.Rendering.Diagrams: lookupN :: Name -> NameMap v -> Maybe [(Point v, Bounds v)]
- Graphics.Rendering.Diagrams: namePoint :: (IsName n, HasLinearMap v, InnerSpace v, OrderedField (Scalar v), Monoid m) => (AnnDiagram b v m -> Point v) -> n -> AnnDiagram b v m -> AnnDiagram b v m
+ Graphics.Rendering.Diagrams: namePoint :: (Atomic n, HasLinearMap v, InnerSpace v, OrderedField (Scalar v), Monoid m) => (AnnDiagram b v m -> (Point v, Bounds v)) -> n -> AnnDiagram b v m -> AnnDiagram b v m
- Graphics.Rendering.Diagrams: named :: (IsName n, HasLinearMap v, InnerSpace v, OrderedField (Scalar v), Monoid m) => n -> AnnDiagram b v m -> AnnDiagram b v m
+ Graphics.Rendering.Diagrams: named :: (Atomic n, HasLinearMap v, InnerSpace v, OrderedField (Scalar v), Monoid m) => n -> AnnDiagram b v m -> AnnDiagram b v m
- Graphics.Rendering.Diagrams: names :: HasLinearMap v => AnnDiagram b v m -> NameMap v
+ Graphics.Rendering.Diagrams: names :: (AdditiveGroup (Scalar v), Floating (Scalar v), InnerSpace v, HasLinearMap v) => AnnDiagram b v m -> NameMap v
- Graphics.Rendering.Diagrams: rememberAs :: Name -> Point v -> NameMap v -> NameMap v
+ Graphics.Rendering.Diagrams: rememberAs :: Name -> Point v -> Bounds v -> NameMap v -> NameMap v
- Graphics.Rendering.Diagrams: toName :: IsName n => n -> Name
+ Graphics.Rendering.Diagrams: toName :: Atomic a => a -> Name
- Graphics.Rendering.Diagrams: withName :: HasLinearMap v => Name -> (Point v -> AnnDiagram b v m -> AnnDiagram b v m) -> AnnDiagram b v m -> AnnDiagram b v m
+ Graphics.Rendering.Diagrams: withName :: (AdditiveGroup (Scalar v), Floating (Scalar v), InnerSpace v, HasLinearMap v) => Name -> (Point v -> AnnDiagram b v m -> AnnDiagram b v m) -> AnnDiagram b v m -> AnnDiagram b v m
- Graphics.Rendering.Diagrams.Core: namePoint :: (IsName n, HasLinearMap v, InnerSpace v, OrderedField (Scalar v), Monoid m) => (AnnDiagram b v m -> Point v) -> n -> AnnDiagram b v m -> AnnDiagram b v m
+ Graphics.Rendering.Diagrams.Core: namePoint :: (Atomic n, HasLinearMap v, InnerSpace v, OrderedField (Scalar v), Monoid m) => (AnnDiagram b v m -> (Point v, Bounds v)) -> n -> AnnDiagram b v m -> AnnDiagram b v m
- Graphics.Rendering.Diagrams.Core: named :: (IsName n, HasLinearMap v, InnerSpace v, OrderedField (Scalar v), Monoid m) => n -> AnnDiagram b v m -> AnnDiagram b v m
+ Graphics.Rendering.Diagrams.Core: named :: (Atomic n, HasLinearMap v, InnerSpace v, OrderedField (Scalar v), Monoid m) => n -> AnnDiagram b v m -> AnnDiagram b v m
- Graphics.Rendering.Diagrams.Core: names :: HasLinearMap v => AnnDiagram b v m -> NameMap v
+ Graphics.Rendering.Diagrams.Core: names :: (AdditiveGroup (Scalar v), Floating (Scalar v), InnerSpace v, HasLinearMap v) => AnnDiagram b v m -> NameMap v
- Graphics.Rendering.Diagrams.Core: type UpAnnots v m = Forgetful (Bounds v) ::: (NameMap v ::: (Query v m ::: Nil))
+ Graphics.Rendering.Diagrams.Core: type UpAnnots v m = Deletable (Bounds v) ::: (NameMap v ::: (Query v m ::: Nil))
- Graphics.Rendering.Diagrams.Core: withName :: HasLinearMap v => Name -> (Point v -> AnnDiagram b v m -> AnnDiagram b v m) -> AnnDiagram b v m -> AnnDiagram b v m
+ Graphics.Rendering.Diagrams.Core: withName :: (AdditiveGroup (Scalar v), Floating (Scalar v), InnerSpace v, HasLinearMap v) => Name -> (Point v -> AnnDiagram b v m -> AnnDiagram b v m) -> AnnDiagram b v m -> AnnDiagram b v m
- Graphics.Rendering.Diagrams.Names: (|>) :: (Qualifiable a, IsName n) => n -> a -> a
+ Graphics.Rendering.Diagrams.Names: (|>) :: (Qualifiable q, Atomic a) => a -> q -> q
- Graphics.Rendering.Diagrams.Names: (||>) :: (IsName n, IsName m) => n -> m -> Name
+ Graphics.Rendering.Diagrams.Names: (||>) :: Qualifiable q => Name -> q -> q
- Graphics.Rendering.Diagrams.Names: NameMap :: (Map Name [Point v]) -> NameMap v
+ Graphics.Rendering.Diagrams.Names: NameMap :: (Map Name [(Point v, TransInv (Bounds v))]) -> NameMap v
- Graphics.Rendering.Diagrams.Names: class Qualifiable a
+ Graphics.Rendering.Diagrams.Names: class Qualifiable q
- Graphics.Rendering.Diagrams.Names: fromNames :: IsName n => [(n, Point v)] -> NameMap v
+ Graphics.Rendering.Diagrams.Names: fromNames :: (AdditiveGroup (Scalar v), Ord (Scalar v), Atomic a) => [(a, Point v)] -> NameMap v
- Graphics.Rendering.Diagrams.Names: lookupN :: IsName n => n -> NameMap v -> Maybe [Point v]
+ Graphics.Rendering.Diagrams.Names: lookupN :: Name -> NameMap v -> Maybe [(Point v, Bounds v)]
- Graphics.Rendering.Diagrams.Names: rememberAs :: Name -> Point v -> NameMap v -> NameMap v
+ Graphics.Rendering.Diagrams.Names: rememberAs :: Name -> Point v -> Bounds v -> NameMap v -> NameMap v
- Graphics.Rendering.Diagrams.Names: toName :: IsName n => n -> Name
+ Graphics.Rendering.Diagrams.Names: toName :: Atomic a => a -> Name

Files

CHANGES view
@@ -10,3 +10,11 @@   * add HasStyle, Boundable, and HasOrigin instances for lists   * add a "trivial backend"   * transformable attributes++0.3: 18 June 2011+  * big overhaul of name maps:+    - allow arbitrary types as atomic names+    - carry along bounding functions as well as names in NameMaps+    - additional functions for querying information associated with names+  * fix for issue #34 (fix behavior of setBounds)+  * Transformable and HasOrigin instances for Transformations
diagrams-core.cabal view
@@ -1,5 +1,5 @@ Name:                diagrams-core-Version:             0.2+Version:             0.3 Synopsis:            Core libraries for diagrams EDSL Description:         The core modules underlying diagrams,                       an embedded domain-specific language @@ -8,7 +8,7 @@ License:             BSD3 License-file:        LICENSE Author:              Brent Yorgey-Maintainer:          byorgey@cis.upenn.edu+Maintainer:          diagrams-discuss@googlegroups.com Category:            Graphics Build-type:          Simple Cabal-version:       >=1.6
src/Graphics/Rendering/Diagrams.hs view
@@ -53,11 +53,17 @@         , Transformable(..) +         -- ** Translational invariance++       , TransInv(..)+          -- * Names -       , Name, IsName(..), Qualifiable(..), (||>)+       , Atomic(..), AName+       , Name, toName+       , Qualifiable(..), (.>), (||>)        , NameMap-       , fromNames+       , fromNames, fromNamesB        , rememberAs         , lookupN@@ -75,7 +81,7 @@         , Bounds(..)        , Boundable(..)-       , boundary+       , boundaryV, boundary, boundaryFrom        , diameter, radius           -- * Things with local origins@@ -96,7 +102,9 @@        , prims        , bounds, names, query, sample -       , named, namePoint, withName+       , named, namePoint+       , withName, withAName+       , withNameB, withANameB         , freeze, setBounds @@ -125,5 +133,3 @@ import Graphics.Rendering.Diagrams.Names import Graphics.Rendering.Diagrams.Style import Graphics.Rendering.Diagrams.Core--
src/Graphics/Rendering/Diagrams/Bounds.hs view
@@ -28,7 +28,7 @@          -- * Utility functions        , diameter        , radius-       , boundary+       , boundaryV, boundary, boundaryFrom           -- * Miscellaneous        , OrderedField@@ -40,6 +40,7 @@ import Graphics.Rendering.Diagrams.HasOrigin  import Data.VectorSpace+import Data.AffineSpace ((.+^))  import Data.Monoid import Control.Applicative ((<$>), (<*>))@@ -91,6 +92,9 @@          => HasOrigin (Bounds v) where   moveOriginTo (P u) (Bounds f) = Bounds $ \v -> f v ^-^ ((u ^/ (v <.> v)) <.> v) +instance Show (Bounds v) where+  show _ = "<bounds>"+ ------------------------------------------------------------ --  Transforming bounding regions  ------------------------- ------------------------------------------------------------@@ -139,9 +143,25 @@ --  Computing with bounds ------------------------------------------------------------ --- | Compute the point along the boundary in the given direction.+-- | Compute the vector from the local origin to a separating+-- hyperplan in the given direction.+boundaryV :: Boundable a => V a -> a -> V a+boundaryV v a = appBounds (getBounds a) v *^ v++-- | Compute the point on the boundary in the given direction.+--   Caution: this point is only valid in the local vector space of+--   the @Boundable@ object.  If you want to compute boundary points+--   of things which are subparts of a larger diagram (and hence+--   embedded within a different vector space), you must use+--   'boundaryFrom' instead. boundary :: Boundable a => V a -> a -> Point (V a)-boundary v a = P $ appBounds (getBounds a) v *^ v+boundary v a = P $ boundaryV v a++-- | @boundaryFrom o v a@ computes the point along the boundary of @a@+--   in the direction of @v@, assuming that @a@'s local origin is+--   located at the point @o@ of the vector space we care about.+boundaryFrom :: Boundable a => Point (V a) -> V a -> a -> Point (V a)+boundaryFrom o v a = o .+^ boundaryV v a  -- | Compute the diameter of a boundable object along a particular --   vector.
src/Graphics/Rendering/Diagrams/Core.hs view
@@ -60,7 +60,8 @@          -- *** Names        , named        , namePoint-       , withName+       , withName, withAName+       , withNameB, withANameB           -- *** Other        , freeze@@ -101,7 +102,7 @@  import Data.Maybe (listToMaybe) import Data.Monoid-import Control.Arrow (second)+import Control.Arrow (second, (&&&))  import Data.Typeable @@ -124,7 +125,7 @@ --   * name/point associations (see "Graphics.Rendering.Diagrams.Names") -- --   * query functions (see "Graphics.Rendering.Diagrams.Query")-type UpAnnots v m = Forgetful (Bounds v) ::: NameMap v ::: Query v m ::: Nil+type UpAnnots v m = Deletable (Bounds v) ::: NameMap v ::: Query v m ::: Nil  -- | Monoidal annotations which travel down the diagram tree, --   i.e. which accumulate along each path to a leaf (and which can@@ -168,40 +169,71 @@ -- | Get the bounds of a diagram. bounds :: (OrderedField (Scalar v), InnerSpace v, HasLinearMap v)        => AnnDiagram b v m -> Bounds v-bounds = unForget . getU' . unAD+bounds = unDelete . getU' . unAD  -- | Replace the bounds of a diagram.-setBounds :: (OrderedField (Scalar v), InnerSpace v, HasLinearMap v, Monoid m)+setBounds :: forall b v m. (OrderedField (Scalar v), InnerSpace v, HasLinearMap v, Monoid m)           => Bounds v -> AnnDiagram b v m -> AnnDiagram b v m-setBounds = inAD . applyU . inj . Forgetful+setBounds b = inAD ( applyUpre (inj . toDeletable $ b)+                   . applyUpre (inj (deleteL :: Deletable (Bounds v)))+                   . applyUpost (inj (deleteR :: Deletable (Bounds v)))+                   )  -- | Get the name map of a diagram.-names :: HasLinearMap v => AnnDiagram b v m -> NameMap v+names :: (AdditiveGroup (Scalar v), Floating (Scalar v), InnerSpace v, HasLinearMap v)+       => AnnDiagram b v m -> NameMap v names = getU' . unAD --- | Attach a name to (the local origin of) a diagram.+-- | Attach an atomic name to (the local origin of) a diagram. named :: forall v b n m.-         ( IsName n+         ( Atomic n          , HasLinearMap v, InnerSpace v, OrderedField (Scalar v), Monoid m)       => n -> AnnDiagram b v m -> AnnDiagram b v m-named = namePoint (const origin)+named = namePoint (const origin &&& bounds) --- | Attach a name to the given point in this diagram.+-- | Attach an atomic name to a certain point and bounding function,+--   computed from the given diagram. namePoint :: forall v b n m.-         ( IsName n+         ( Atomic n          , HasLinearMap v, InnerSpace v, OrderedField (Scalar v), Monoid m)-      => (AnnDiagram b v m -> Point v) -> n -> AnnDiagram b v m -> AnnDiagram b v m-namePoint p n d = inAD (applyU . inj $ fromNames [(n,p d)]) d+      => (AnnDiagram b v m -> (Point v, Bounds v)) -> n -> AnnDiagram b v m -> AnnDiagram b v m+namePoint p n d = inAD (applyUpre . inj $ fromNamesB [(n,p d)]) d  -- | Given a name and a diagram transformation indexed by a point, --   perform the transformation using the first point associated with---   the name, or perform the identity transformation if the name does---   not exist.-withName :: HasLinearMap v+--   (some qualification of) the name, or perform the identity+--   transformation if the name does not exist.+withName :: ( AdditiveGroup (Scalar v), Floating (Scalar v)+            , InnerSpace v, HasLinearMap v)          => Name -> (Point v -> AnnDiagram b v m -> AnnDiagram b v m)          -> AnnDiagram b v m -> AnnDiagram b v m-withName n f d = maybe id f (lookupN n (names d) >>= listToMaybe) d+withName n f d = maybe id (f . fst) (lookupN n (names d) >>= listToMaybe) d +-- | Like 'withName', but taking an atomic name as an argument.+withAName :: ( Atomic a, AdditiveGroup (Scalar v), Floating (Scalar v)+             , InnerSpace v, HasLinearMap v)+          => a -> (Point v -> AnnDiagram b v m -> AnnDiagram b v m)+          -> AnnDiagram b v m -> AnnDiagram b v m+withAName = withName . toName++-- | Given a name and a diagram transformation indexed by a point and+--   a bounding function, perform the transformation using the first+--   (point, bounding function) pair associated with (some+--   qualification of) the name, or perform the identity+--   transformation if the name does not exist.+withNameB :: ( AdditiveGroup (Scalar v), Floating (Scalar v)+             , InnerSpace v, HasLinearMap v)+          => Name -> (Point v -> Bounds v -> AnnDiagram b v m -> AnnDiagram b v m)+          -> AnnDiagram b v m -> AnnDiagram b v m+withNameB n f d = maybe id (uncurry f) (lookupN n (names d) >>= listToMaybe) d++-- | Like 'withNameB', but taking an atomic name as an argument.+withANameB :: ( Atomic a, AdditiveGroup (Scalar v), Floating (Scalar v)+              , InnerSpace v, HasLinearMap v)+           => a -> (Point v -> Bounds v -> AnnDiagram b v m -> AnnDiagram b v m)+           -> AnnDiagram b v m -> AnnDiagram b v m+withANameB a = withNameB . toName $ a+ -- | Get the query function associated with a diagram. query :: (HasLinearMap v, Monoid m) => AnnDiagram b v m -> Query v m query = getU' . unAD@@ -213,7 +245,7 @@ -- | Create a diagram from a single primitive, along with a bounding --   region, name map, and query function. mkAD :: Prim b v -> Bounds v -> NameMap v -> Query v m -> AnnDiagram b v m-mkAD p b n a = AD $ leaf (Normal b ::: n ::: a ::: Nil) p+mkAD p b n a = AD $ leaf (toDeletable b ::: n ::: a ::: Nil) p  ------------------------------------------------------------ --  Instances@@ -420,7 +452,8 @@   -- | 'adjustDia' allows the backend to make adjustments to the final   --   diagram (e.g. to adjust the size based on the options) before   --   rendering it.  A default implementation is provided which makes-  --   no adjustments.+  --   no adjustments.  See the diagrams-lib package for other useful+  --   implementations.   adjustDia :: Monoid m => b -> Options b v -> AnnDiagram b v m -> AnnDiagram b v m   adjustDia _ _ d = d @@ -446,21 +479,6 @@               = withStyle b s t1 (render b (transform (t1 <> t2) p))    -- See Note [backend token]---- | The "trivial backend" which does nothing.  Useful for fixing the---   type of diagrams whose rendering behavior we really don't care---   about (e.g. diagrams we are just going to use for bounding other---   diagrams, etc.)-instance HasLinearMap v => Backend () v where-  data Render  () v = UnitRender-  type Result  () v = ()-  data Options () v = UnitOptions-  withStyle _ _ _ _ = UnitRender-  doRender _ _ _    = ()--instance Monoid (Render () v) where-  mempty  = UnitRender-  mappend = const (const UnitRender)  -- | A class for backends which support rendering multiple diagrams, --   e.g. to a multi-page pdf or something similar.
src/Graphics/Rendering/Diagrams/Monoids.hs view
@@ -33,6 +33,8 @@         , Forgetful(..), unForget, forget +       , Deletable(..), unDelete, toDeletable, deleteL, deleteR+          -- * Applicative monoids         , AM(..), inAM2@@ -127,10 +129,14 @@ ------------------------------------------------------------  -- $forget--- Sometimes we want to be able to "forget" some information.  In--- particular, we can introduce special @Forgetful@ values which cause--- anything to their right to be forgotten.+-- Sometimes we want to be able to "forget" some information.  We+-- define two monoid transformers that allow forgetting information.+-- @Forgetful@ introduces special values which cause anything to their+-- right to be forgotten.  @Deletable@ introduces special "left and+-- right bracket" elements which cause everything inside them to be+-- forgotten. + -- | A value of type @Forgetful m@ is either a \"normal\" value of --   type @m@, which combines normally with other normal values, or a --   \"forgetful\" value, which combines normally with other values to@@ -166,6 +172,57 @@   act (Forgetful m) n = act m n  type instance V (Forgetful m) = V m++-- | If @m@ is a 'Monoid', then @Deletable m@ (intuitively speaking)+--   adds two distinguished new elements L and R, such that an+--   occurrence of L \"deletes\" everything from it to the next R. For+--   example,+--+--   > abcLdefRgh == abcgh+--+--   This is all you really need to know to /use/ @Deletable m@+--   values; to understand the actual implementation, read on.+--+--   To properly deal with nesting and associativity we need to be+--   able to assign meanings to things like @LL@, @RL@, and so on. (We+--   cannot just define, say, @LL == L@, since then @(LL)R == LR ==+--   id@ but @L(LR) == Lid == L@.)  Formally, elements of @Deletable+--   m@ are triples of the form (r, m, l) representing words @R^r m+--   L^l@.  When combining two triples (r1, m1, l1) and (r2, m2, l2)+--   there are three cases:+--+--   * If l1 == r2 then the Ls from the left and Rs from the right+--     exactly cancel, and we are left with (r1, m1 \<\> m2, l2).+--+--   * If l1 < r2 then all of the Ls cancel with some of the Rs, but+--     m1 is still inside the remaining Rs and is deleted, yielding (r1+--     + r2 - l1, m2, l2)+--+--   * The remaining case is symmetric with the second.++data Deletable m = Deletable Int m Int+  deriving Functor++type instance V (Deletable m) = V m++unDelete :: Deletable m -> m+unDelete (Deletable _ m _) = m++instance Monoid m => Monoid (Deletable m) where+  mempty = Deletable 0 mempty 0+  (Deletable r1 m1 l1) `mappend` (Deletable r2 m2 l2)+    | l1 == r2  = Deletable r1 (m1 `mappend` m2) l2+    | l1 <  r2  = Deletable (r1 + r2 - l1) m2 l2+    | otherwise = Deletable r1 m1 (l2 + l1 - r2)++toDeletable :: m -> Deletable m+toDeletable m = Deletable 0 m 0++deleteL :: Monoid m => Deletable m+deleteL = Deletable 0 mempty 1++deleteR :: Monoid m => Deletable m+deleteR = Deletable 1 mempty 0  ------------------------------------------------------------ --  Applicative monoids
src/Graphics/Rendering/Diagrams/Names.hs view
@@ -1,9 +1,14 @@ {-# LANGUAGE TypeSynonymInstances            , FlexibleInstances+           , FlexibleContexts            , TypeFamilies            , GeneralizedNewtypeDeriving            , MultiParamTypeClasses            , OverlappingInstances+           , TupleSections+           , GADTs+           , DeriveDataTypeable+           , UndecidableInstances   #-} ----------------------------------------------------------------------------- -- |@@ -19,17 +24,22 @@  module Graphics.Rendering.Diagrams.Names        (-- * Names+        -- ** Atomic names+         Atomic(..)+       , AName(..) -         AName(..), Name(..), IsName(..)+        -- ** Names+       , Name(..), toName -       , Qualifiable(..), (||>)+        -- ** Qualifiable+       , Qualifiable(..), (.>), (||>)           -- * Name maps         , NameMap(..)           -- ** Constructing name maps-       , fromNames+       , fromNames, fromNamesB        , rememberAs           -- ** Searching within name maps@@ -40,125 +50,164 @@ import Graphics.Rendering.Diagrams.Monoids import Graphics.Rendering.Diagrams.HasOrigin import Graphics.Rendering.Diagrams.Points+import Graphics.Rendering.Diagrams.Bounds+import Graphics.Rendering.Diagrams.Transform  import Data.VectorSpace  import Data.List (intercalate, isSuffixOf) import qualified Data.Map as M import Data.Monoid-import Control.Arrow ((***))+import Control.Arrow ((***), second) import Control.Monad (mplus) +import Data.Typeable+ ------------------------------------------------------------ --  Names  ------------------------------------------------- ------------------------------------------------------------ --- | An atomic name is either a number or a string.  Numeric names are---   provided for convenience in naming lists of things, such as a row---   of ten squares, or the vertices of a path.-data AName = IName Integer-           | SName String-  deriving Ord+-- | @Atomic@ types are those which can be used as names.  They must+--   support 'Typeable' (to facilitate extracting them from+--   existential wrappers), 'Ord' (for comparison and efficient+--   storage) and 'Show'.+class (Typeable a, Ord a, Show a) => Atomic a where+  toAName :: a -> AName+  toAName = AName --- | Note that equality on names does not distinguish between integers---   and their @String@ representations.+instance Atomic ()+instance Atomic Bool+instance Atomic Char+instance Atomic Int+instance Atomic Float+instance Atomic Double+instance Atomic Integer+instance Atomic String+instance Atomic a => Atomic [a]+instance (Atomic a, Atomic b) => Atomic (a,b)+instance (Atomic a, Atomic b, Atomic c) => Atomic (a,b,c)++-- | Atomic names.  @AName@ is just an existential wrapper around+--   'Atomic' values.+data AName where+  AName :: Atomic a => a -> AName+  deriving (Typeable)++instance Atomic AName where+  toAName = id+ instance Eq AName where-  IName i1 == IName i2 = i1 == i2-  SName s1 == SName s2 = s1 == s2-  IName i  == SName s  = show i == s-  SName s  == IName i  = s == show i+  (AName a1) == (AName a2) =+    case cast a2 of+      Nothing  -> False+      Just a2' -> a1 == a2' +instance Ord AName where+  (AName a1) `compare` (AName a2) =+    case cast a2 of+      Nothing  -> (show $ typeOf a1) `compare` (show $ typeOf a2)+      Just a2' -> a1 `compare` a2'+ instance Show AName where-  show (IName i) = show i-  show (SName s) = s+  show (AName a) = show a  -- | A (qualified) name is a (possibly empty) sequence of atomic names.---   Atomic names can be either numbers or arbitrary strings.  Numeric---   names are provided for convenience in naming lists of things,---   such as a row of ten squares, or the vertices of a path. newtype Name = Name [AName]   deriving (Eq, Ord, Monoid)  instance Show Name where-  show (Name ns) = intercalate "." $ map show ns---- | Instaces of 'IsName' are things which can be converted to names.-class IsName n where-  toName :: n -> Name--instance IsName String where-  toName = Name . (:[]) . SName--instance IsName Int where-  toName = Name . (:[]) . IName . fromIntegral--instance IsName Integer where-  toName = Name . (:[]) . IName+  show (Name ns) = intercalate " |> " $ map show ns -instance IsName Name where-  toName = id+-- | Convert an atomic name to a name.+toName :: Atomic a => a -> Name+toName = Name . (:[]) . toAName  -- | Instances of 'Qualifiable' are things which can be qualified by---   prefixing them with a name.-class Qualifiable a where+--   prefixing them with an atomic name.+class Qualifiable q where   -- | Qualify with the given name.-  (|>) :: IsName n => n -> a -> a+  (|>) :: Atomic a => a -> q -> q --- | Names can be qualified by prefixing them with other names.+-- | Of course, names can be qualified. instance Qualifiable Name where-  n1 |> n2 = toName n1 `mappend` n2+  a |> (Name as) = Name (toAName a : as)  -- | Convenient operator for writing complete names in the form @a1 |>---   a2 |> a3 ||> a4@.  In particular, @n1 ||> n2@ is equivalent to---   @n1 |> toName n2@.-(||>) :: (IsName n, IsName m) => n -> m -> Name-n1 ||> n2 = n1 |> toName n2+--   a2 |> a3 ||> a4@.  In particular, @a1 .> a2@ is equivalent to+--   @a1 |> toName a2@.+(.>) :: (Atomic a1, Atomic a2) => a1 -> a2 -> Name+a1 .> a2 = a1 |> toName a2  infixr 2 |>-infixr 2 ||>+infixr 2 .> +-- | Qualify by an entire qualified name.  @(a1 |> a2 .> a3) ||> q@ is+--   equivalent to @a1 |> a2 |> a3 |> q@.+(||>) :: Qualifiable q => Name -> q -> q+Name as ||> q = foldr (|>) q as+ ------------------------------------------------------------ --  Name maps  --------------------------------------------- ------------------------------------------------------------ --- | A 'NameMap' is a map from names to points, possibly with---   multiple points associated with each name.-newtype NameMap v = NameMap (M.Map Name [Point v])--- Note, in some sense it would be nicer to use Sets of points instead--- of a list, but then we would have to put Ord constraints on v+-- | A 'NameMap' is a map associating names to pairs of points (local+--   origins) and bounding functions.  There can be multiple (point,+--   bounding function) pairs associated with each name.+newtype NameMap v = NameMap (M.Map Name [(Point v, TransInv (Bounds v))])+  deriving (Show)++-- Note, in some sense it would be nicer to use Sets instead of a+-- list, but then we would have to put Ord constraints on v -- everywhere. =P +-- Note also that we wrap the bounds with TransInv.  This is because+-- the base point of each bounding function should be thought of as+-- the paired Point, *not* as the origin of the current vector space.+-- In other words, the point gets translated "for both of them".+ type instance V (NameMap v) = v  -- | 'NameMap's form a monoid with the empty map as the identity, and --   map union as the binary operation.  No information is ever lost: --   if two maps have the same name in their domain, the resulting map---   will associate that name to the union of the two sets of points+--   will associate that name to the concatenation of the information --   associated with that name. instance Monoid (NameMap v) where   mempty = NameMap M.empty   (NameMap s1) `mappend` (NameMap s2) = NameMap $ M.unionWith (++) s1 s2 -instance VectorSpace v => HasOrigin (NameMap v) where-  moveOriginTo p (NameMap m) = NameMap $ M.map (map (moveOriginTo p)) m+instance (AdditiveGroup (Scalar v), Fractional (Scalar v), InnerSpace v)+      => HasOrigin (NameMap v) where+  moveOriginTo p (NameMap m) = NameMap $ M.map (map (moveOriginTo p *** moveOriginTo p)) m --- | 'NameMap's are qualifiable: if @ns@ is a 'NameMap', then @n |>+instance (AdditiveGroup (Scalar v), InnerSpace v, Floating (Scalar v), HasLinearMap v)+  => Transformable (NameMap v) where+  transform t (NameMap ns) = NameMap $ M.map (map (papply t *** transform t)) ns++-- | 'NameMap's are qualifiable: if @ns@ is a 'NameMap', then @a |> --   ns@ is the same 'NameMap' except with every name qualified by---   @n@.+--   @a@. instance Qualifiable (NameMap v) where-  n |> (NameMap names) = NameMap $ M.mapKeys (n |>) names+  a |> (NameMap names) = NameMap $ M.mapKeys (a |>) names --- | Construct a 'NameMap' from a list of (name, point) pairs.-fromNames :: IsName n => [(n, Point v)] -> NameMap v-fromNames = NameMap . M.fromList . map (toName *** (:[]))+-- | Construct a 'NameMap' from a list of (name, point) pairs.  The+--   bounding functions will be empty.+fromNames :: (AdditiveGroup (Scalar v), Ord (Scalar v), Atomic a)+          => [(a, Point v)] -> NameMap v+fromNames = NameMap . M.fromList . map (toName *** ((:[]) . (,mempty))) --- | Give a name to a point.-rememberAs :: Name -> Point v -> NameMap v -> NameMap v-rememberAs n p (NameMap names) = NameMap $ M.insertWith (++) n [p] names+-- | Construct a 'NameMap' from a list of associations between names+--   and (point, bounds) pairs.+fromNamesB :: Atomic a => [(a, (Point v, Bounds v))] -> NameMap v+fromNamesB = NameMap . M.fromList . map (toName *** (return . second TransInv)) +-- | Give a name to a point and bounding function.+rememberAs :: Name -> Point v -> Bounds v -> NameMap v -> NameMap v+rememberAs n p b (NameMap names) = NameMap $ M.insertWith (++) n [(p,TransInv b)] names+ -- | A name acts on a name map by qualifying every name in it. instance Action Name (NameMap v) where-  act = (|>)+  act = (||>)  -- | Names don't act on anything else. instance Action Name a@@ -167,14 +216,14 @@ -- Searching in name maps.  -- | Look for the given name in a name map, returning a list of points---   associated with that name.  If no names match the given name---   exactly, return all the points associated with names of which the---   given name is a suffix.-lookupN :: IsName n => n -> NameMap v -> Maybe [Point v]+--   and bounding regions associated with that name.  If no names+--   match the given name exactly, return all the points associated+--   with names of which the given name is a suffix.+lookupN :: Name -> NameMap v -> Maybe [(Point v, Bounds v)] lookupN n (NameMap m)-  = M.lookup n' m `mplus`-    (flatten . filter ((n' `nameSuffixOf`) . fst) . M.assocs $ m)-  where n' = toName n-        (Name n1) `nameSuffixOf` (Name n2) = n1 `isSuffixOf` n2+  = (fmap . map . second) unTransInv+    (M.lookup n m `mplus`+    (flatten . filter ((n `nameSuffixOf`) . fst) . M.assocs $ m))+  where (Name n1) `nameSuffixOf` (Name n2) = n1 `isSuffixOf` n2         flatten [] = Nothing         flatten xs = Just . concatMap snd $ xs
src/Graphics/Rendering/Diagrams/Transform.hs view
@@ -4,6 +4,7 @@            , UndecidableInstances            , TypeFamilies            , MultiParamTypeClasses+           , GeneralizedNewtypeDeriving   #-}  -----------------------------------------------------------------------------@@ -41,6 +42,10 @@        , HasLinearMap        , Transformable(..) +         -- * Translational invariance++       , TransInv(..)+          -- * Vector space independent transformations          -- | Most transformations are specific to a particular vector          --   space, but a few can be defined generically over any@@ -53,6 +58,7 @@  import Data.AdditiveGroup import Data.VectorSpace+import Data.AffineSpace ((.-.)) import Data.LinearMap import Data.Basis import Data.MemoTrie@@ -64,8 +70,8 @@ import Graphics.Rendering.Diagrams.Monoids import Graphics.Rendering.Diagrams.V import Graphics.Rendering.Diagrams.Points-import Graphics.Rendering.Diagrams.Names import Graphics.Rendering.Diagrams.Util+import Graphics.Rendering.Diagrams.HasOrigin  ------------------------------------------------------------ --  Transformations  ---------------------------------------@@ -107,6 +113,8 @@ --   translation component. data Transformation v = Transformation (v :-: v) (v :-: v) v +type instance V (Transformation v) = v+ -- | Invert a transformation. inv :: HasLinearMap v => Transformation v -> Transformation v inv (Transformation t t' v) = Transformation (linv t) (linv t')@@ -164,6 +172,12 @@   -- | Apply a transformation to an object.   transform :: Transformation (V t) -> t -> t +instance HasLinearMap v => Transformable (Transformation v) where+  transform t1 t2 = t1 <> t2++instance HasLinearMap v => HasOrigin (Transformation v) where+  moveOriginTo p = translate (origin .-. p)+ instance Transformable t => Transformable [t] where   transform = map . transform @@ -173,14 +187,33 @@ instance Transformable t => Transformable (M.Map k t) where   transform = M.map . transform -instance HasLinearMap v => Transformable (NameMap v) where-  transform t (NameMap ns) = NameMap $ M.map (map (papply t)) ns- instance HasLinearMap v => Transformable (Point v) where   transform = papply  instance Transformable m => Transformable (Forgetful m) where   transform = fmap . transform++instance Transformable m => Transformable (Deletable m) where+  transform = fmap . transform++------------------------------------------------------------+--  Translational invariance  ------------------------------+------------------------------------------------------------++-- | @TransInv@ is a wrapper which makes a transformable type+--   translationally invariant; the translational component of+--   transformations will no longer affect things wrapped in+--   @TransInv@.+newtype TransInv t = TransInv { unTransInv :: t }+  deriving (Show, Monoid)++type instance V (TransInv t) = V t++instance VectorSpace (V t) => HasOrigin (TransInv t) where+  moveOriginTo = const id++instance Transformable t => Transformable (TransInv t) where+  transform tr (TransInv t) = TransInv (translate (negateV (transl tr)) . transform tr $ t)  ------------------------------------------------------------ --  Generic transformations  -------------------------------
src/Graphics/Rendering/Diagrams/UDTree.hs view
@@ -23,7 +23,7 @@        , leaf, branchD, branch           -- * Modifying UD-trees-       , applyD, applyU, mapU+       , applyD, applyUpre, applyUpost, mapU           -- * Accessors and destructors        , getU, getU', foldUD, flatten@@ -49,13 +49,13 @@ --     all the @d@ annotations along the path from the root to the leaf --     node. -----   * The @u@ annotation at an internal node is equal to @v---     ``mappend`` (mconcat us)@ for some value @v@ (possibly---     'mempty'), where @us@ is the list (in left-right order) of the---     @u@ annotations on the immediate child nodes of the given node.---     Intuitively, we are \"caching\" the @mconcat@ of @u@---     annotations from the leaves up, except that at any point we may---     insert \"extra\" information.+--   * The @u@ annotation at an internal node is equal to @v1+--     ``mappend`` (mconcat us) ``mappend`` v2@ for some values @v1@+--     and @v2@ (possibly 'mempty'), where @us@ is the list (in+--     left-right order) of the @u@ annotations on the immediate child+--     nodes of the given node.  Intuitively, we are \"caching\" the+--     @mconcat@ of @u@ annotations from the leaves up, except that at+--     any point we may insert \"extra\" information. -- --   In addition, @d@ may have an /action/ on @u@ (see the 'Action' --   type class, defined in "Graphics.Rendering.Diagrams.Monoids"), in@@ -115,9 +115,15 @@  -- | Add a @u@ annotation to the root, combining it (on the left) with --   the existing @u@ annotation.-applyU :: (Monoid u, Action d u) => u -> UDTree u d a -> UDTree u d a-applyU u' (Leaf u a) = Leaf (u' <> u) a-applyU u' b          = Branch (u' <> getU b) [] [b]+applyUpre :: (Monoid u, Action d u) => u -> UDTree u d a -> UDTree u d a+applyUpre u' (Leaf u a) = Leaf (u' <> u) a+applyUpre u' b          = Branch (u' <> getU b) [] [b]++-- | Add a @u@ annotation to the root, combining it (on the right) with+--   the existing @u@ annotation.+applyUpost :: (Monoid u, Action d u) => u -> UDTree u d a -> UDTree u d a+applyUpost u' (Leaf u a) = Leaf (u <> u') a+applyUpost u' b          = Branch (getU b <> u') [] [b]  -- | Map a function over all the @u@ annotations.  The function must --   be a monoid homomorphism, and must commute with the action of @d@