diagrams-lib-1.4: src/Diagrams/Query.hs
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE MultiParamTypeClasses #-}
-----------------------------------------------------------------------------
-- |
-- Module : Diagrams.Query
-- Copyright : (c) 2013 diagrams-lib team (see LICENSE)
-- License : BSD-style (see LICENSE)
-- Maintainer : diagrams-discuss@googlegroups.com
--
-- A query is a function that maps points in a vector space to values
-- in some monoid. Queries naturally form a monoid, with two queries
-- being combined pointwise.
--
-----------------------------------------------------------------------------
module Diagrams.Query
( -- * Queries
Query(..)
, HasQuery (..)
, sample
, inquire
-- ** Queries on diagrams
, query
, value
, resetValue
, clearValue
) where
import Data.Monoid
import Diagrams.Core
-- | Types which can answer a 'Query' about points inside the geometric
-- object.
--
-- If @t@ and @m@ are both a 'Semigroup's, 'getQuery' should satisfy
--
-- @
-- 'getQuery' (t1 <> t2) = 'getQuery' t1 <> 'getQuery' t2
-- @
class HasQuery t m | t -> m where
-- | Extract the query of an object.
getQuery :: t -> Query (V t) (N t) m
instance HasQuery (Query v n m) m where
getQuery = id
instance Monoid m => HasQuery (QDiagram b v n m) m where
getQuery = query
-- | Test if a point is not equal to 'mempty'.
--
-- @
-- 'inquire' :: 'QDiagram' b v n 'Any' -> 'Point' v n -> 'Bool'
-- 'inquire' :: 'Query' v n 'Any' -> 'Point' v n -> 'Bool'
-- 'inquire' :: 'Diagrams.BoundingBox.BoundingBox' v n -> 'Point' v n -> 'Bool'
-- @
inquire :: HasQuery t Any => t -> Point (V t) (N t) -> Bool
inquire t = getAny . sample t
-- | Sample a diagram's query function at a given point.
--
-- @
-- 'sample' :: 'QDiagram' b v n m -> 'Point' v n -> m
-- 'sample' :: 'Query' v n m -> 'Point' v n -> m
-- 'sample' :: 'Diagrams.BoundingBox.BoundingBox' v n -> 'Point' v n -> 'Any'
-- 'sample' :: 'Diagrams.Path.Path' 'V2' 'Double' -> 'Point' v n -> 'Diagrams.TwoD.Path.Crossings'
-- @
sample :: HasQuery t m => t -> Point (V t) (N t) -> m
sample = runQuery . getQuery
-- | Set the query value for 'True' points in a diagram (/i.e./ points
-- \"inquire\" the diagram); 'False' points will be set to 'mempty'.
value :: Monoid m => m -> QDiagram b v n Any -> QDiagram b v n m
value m = fmap fromAny
where fromAny (Any True) = m
fromAny (Any False) = mempty
-- | Reset the query values of a diagram to @True@/@False@: any values
-- equal to 'mempty' are set to 'False'; any other values are set to
-- 'True'.
resetValue :: (Eq m, Monoid m) => QDiagram b v n m -> QDiagram b v n Any
resetValue = fmap toAny
where toAny m | m == mempty = Any False
| otherwise = Any True
-- | Set all the query values of a diagram to 'False'.
clearValue :: QDiagram b v n m -> QDiagram b v n Any
clearValue = fmap (const (Any False))