diagrams-core-1.5.1.1: Core libraries for diagrams EDSL

Copyright | (c) 2012-2015 diagrams-core team (see LICENSE)
License | BSD-style (see LICENSE)
Maintainer | diagrams-discuss@googlegroups.com
Safe Haskell | None
Language | Haskell2010

Diagrams.Core.Trace

Contents

- SortedList
- Traces
- Traced class
- Computing with traces

Description

`diagrams-core` defines the core library of primitives forming the basis of an embedded domain-specific language for describing and rendering diagrams.

The `Trace` module defines a data type and type class for "traces", aka functional boundaries, essentially corresponding to embedding a raytracer with each diagram.

Synopsis

- data SortedList a
- mkSortedList :: Ord a => [a] -> SortedList a
- getSortedList :: SortedList a -> [a]
- onSortedList :: Ord b => ([a] -> [b]) -> SortedList a -> SortedList b
- unsafeOnSortedList :: ([a] -> [b]) -> SortedList a -> SortedList b
- newtype Trace (v :: Type -> Type) n = Trace (Point v n -> v n -> SortedList n)
- appTrace :: Trace v n -> Point v n -> v n -> SortedList n
- mkTrace :: (Point v n -> v n -> SortedList n) -> Trace v n
- class (Additive (V a), Ord (N a)) => Traced a where
  - getTrace :: a -> Trace (V a) (N a)
- traceV :: (n ~ N a, Num n, Traced a) => Point (V a) n -> V a n -> a -> Maybe (V a n)
- traceP :: (n ~ N a, Traced a, Num n) => Point (V a) n -> V a n -> a -> Maybe (Point (V a) n)
- maxTraceV :: (n ~ N a, Num n, Traced a) => Point (V a) n -> V a n -> a -> Maybe (V a n)
- maxTraceP :: (n ~ N a, Num n, Traced a) => Point (V a) n -> V a n -> a -> Maybe (Point (V a) n)
- getRayTrace :: (n ~ N a, Traced a, Num n) => a -> Trace (V a) n
- rayTraceV :: (n ~ N a, Traced a, Num n) => Point (V a) n -> V a n -> a -> Maybe (V a n)
- rayTraceP :: (n ~ N a, Traced a, Num n) => Point (V a) n -> V a n -> a -> Maybe (Point (V a) n)
- maxRayTraceV :: (n ~ N a, Traced a, Num n) => Point (V a) n -> V a n -> a -> Maybe (V a n)
- maxRayTraceP :: (n ~ N a, Traced a, Num n) => Point (V a) n -> V a n -> a -> Maybe (Point (V a) n)

# SortedList

data SortedList a Source #

A newtype wrapper around a list which maintains the invariant that the list is sorted. The constructor is not exported; use the smart constructor `mkSortedList` (which sorts the given list) instead.

#### Instances

Instances details

Ord a => Monoid (SortedList a) Source # | `SortedList` forms a monoid with `merge` and the empty list.
Instance details Defined in Diagrams.Core.Trace Methods mempty :: SortedList a Source # mappend :: SortedList a -> SortedList a -> SortedList a Source # mconcat :: [SortedList a] -> SortedList a Source #
Ord a => Semigroup (SortedList a) Source # | `SortedList` forms a semigroup with `merge` as composition.
Instance details Defined in Diagrams.Core.Trace Methods (<>) :: SortedList a -> SortedList a -> SortedList a Source # sconcat :: NonEmpty (SortedList a) -> SortedList a Source # stimes :: Integral b => b -> SortedList a -> SortedList a Source #

mkSortedList :: Ord a => [a] -> SortedList a Source #

A smart constructor for the `SortedList` type, which sorts the input to ensure the `SortedList` invariant.

getSortedList :: SortedList a -> [a] Source #

Project the (guaranteed sorted) list out of a `SortedList` wrapper.

onSortedList :: Ord b => ([a] -> [b]) -> SortedList a -> SortedList b Source #

Apply a list function to a `SortedList`. The function need not result in a sorted list; the result will be sorted before being rewrapped as a `SortedList`.

unsafeOnSortedList :: ([a] -> [b]) -> SortedList a -> SortedList b Source #

Apply an order-preserving list function to a `SortedList`. No sorts or checks are done.

# Traces

newtype Trace (v :: Type -> Type) n Source #

Every diagram comes equipped with a trace. Intuitively, the trace for a diagram is like a raytracer: given a line (represented as a base point and a direction vector), the trace computes a sorted list of signed distances from the base point to all intersections of the line with the boundary of the diagram.

Note that the outputs are not absolute distances, but multipliers relative to the input vector. That is, if the base point is `p` and direction vector is `v`, and one of the output scalars is `s`, then there is an intersection at the point `p .+^ (s *^ v)`.

Constructors

Trace (Point v n -> v n -> SortedList n) |

#### Instances

Instances details

Action Name (Trace v n) Source # |
Instance details Defined in Diagrams.Core.Types Methods act :: Name -> Trace v n -> Trace v n Source #
(Additive v, Num n) => HasOrigin (Trace v n) Source # |
Instance details Defined in Diagrams.Core.Trace Methods moveOriginTo :: Point (V (Trace v n)) (N (Trace v n)) -> Trace v n -> Trace v n Source #
(Additive v, Ord n) => Traced (Trace v n) Source # |
Instance details Defined in Diagrams.Core.Trace Methods getTrace :: Trace v n -> Trace (V (Trace v n)) (N (Trace v n)) Source #
(Additive v, Num n) => Transformable (Trace v n) Source # |
Instance details Defined in Diagrams.Core.Trace Methods transform :: Transformation (V (Trace v n)) (N (Trace v n)) -> Trace v n -> Trace v n Source #
Ord n => Monoid (Trace v n) Source # |
Instance details Defined in Diagrams.Core.Trace Methods mempty :: Trace v n Source # mappend :: Trace v n -> Trace v n -> Trace v n Source # mconcat :: [Trace v n] -> Trace v n Source #
Ord n => Semigroup (Trace v n) Source # | Traces form a semigroup with pointwise minimum as composition. Hence, if `t1` is the trace for diagram `d1`, and `e2` is the trace for `d2`, then `e1 `mappend` e2` is the trace for `d1 `atop` d2`.
Instance details Defined in Diagrams.Core.Trace Methods (<>) :: Trace v n -> Trace v n -> Trace v n Source # sconcat :: NonEmpty (Trace v n) -> Trace v n Source # stimes :: Integral b => b -> Trace v n -> Trace v n Source #
Show (Trace v n) Source # |
Instance details Defined in Diagrams.Core.Trace Methods showsPrec :: Int -> Trace v n -> ShowS Source # show :: Trace v n -> String Source # showList :: [Trace v n] -> ShowS Source #
Wrapped (Trace v n) Source # |

Instance details

Defined in Diagrams.Core.Trace

Associated Types

type Unwrapped (Trace v n) |
Instance details Defined in Diagrams.Core.Trace type Unwrapped (Trace v n) = Point v n -> v n -> SortedList n

Methods

_Wrapped' :: Iso' (Trace v n) (Unwrapped (Trace v n)) Source #

Rewrapped (Trace v n) (Trace v' n') Source # |
Instance details Defined in Diagrams.Core.Trace
type N (Trace v n) Source # |
Instance details Defined in Diagrams.Core.Trace type N (Trace v n) = n
type V (Trace v n) Source # |
Instance details Defined in Diagrams.Core.Trace type V (Trace v n) = v
type Unwrapped (Trace v n) Source # |
Instance details Defined in Diagrams.Core.Trace type Unwrapped (Trace v n) = Point v n -> v n -> SortedList n

appTrace :: Trace v n -> Point v n -> v n -> SortedList n Source #

mkTrace :: (Point v n -> v n -> SortedList n) -> Trace v n Source #

# Traced class

class (Additive (V a), Ord (N a)) => Traced a where Source #

`Traced` abstracts over things which have a trace.

Methods

getTrace :: a -> Trace (V a) (N a) Source #

Compute the trace of an object.

#### Instances

Instances details

Traced b => Traced (Set b) Source # |
Instance details Defined in Diagrams.Core.Trace Methods getTrace :: Set b -> Trace (V (Set b)) (N (Set b)) Source #
Traced t => Traced (TransInv t) Source # |
Instance details Defined in Diagrams.Core.Trace Methods getTrace :: TransInv t -> Trace (V (TransInv t)) (N (TransInv t)) Source #
Traced b => Traced [b] Source # |
Instance details Defined in Diagrams.Core.Trace Methods getTrace :: [b] -> Trace (V [b]) (N [b]) Source #
Traced b => Traced (Map k b) Source # |
Instance details Defined in Diagrams.Core.Trace Methods getTrace :: Map k b -> Trace (V (Map k b)) (N (Map k b)) Source #
(Additive v, Ord n) => Traced (Trace v n) Source # |
Instance details Defined in Diagrams.Core.Trace Methods getTrace :: Trace v n -> Trace (V (Trace v n)) (N (Trace v n)) Source #

(Additive v, Ord n) => Traced (Point v n) Source #

The trace of a single point is the empty trace, i.e. the one which returns no intersection points for every query. Arguably it should return a single finite distance for vectors aimed directly at the given point, but due to floating-point inaccuracy this is problematic. Note that the envelope for a single point is not the empty envelope (see Diagrams.Core.Envelope).

Instance details Defined in Diagrams.Core.Trace Methods getTrace :: Point v n -> Trace (V (Point v n)) (N (Point v n)) Source #
(Traced a, Traced b, SameSpace a b) => Traced (a, b) Source # |
Instance details Defined in Diagrams.Core.Trace Methods getTrace :: (a, b) -> Trace (V (a, b)) (N (a, b)) Source #
(Metric v, OrderedField n, Semigroup m) => Traced (QDiagram b v n m) Source # |
Instance details Defined in Diagrams.Core.Types Methods getTrace :: QDiagram b v n m -> Trace (V (QDiagram b v n m)) (N (QDiagram b v n m)) Source #
(OrderedField n, Metric v, Semigroup m) => Traced (Subdiagram b v n m) Source # |
Instance details Defined in Diagrams.Core.Types Methods getTrace :: Subdiagram b v n m -> Trace (V (Subdiagram b v n m)) (N (Subdiagram b v n m)) Source #

# Computing with traces

traceV :: (n ~ N a, Num n, Traced a) => Point (V a) n -> V a n -> a -> Maybe (V a n) Source #

Compute the vector from the given point `p` to the "smallest" boundary intersection along the given vector `v`. The "smallest" boundary intersection is defined as the one given by `p .+^ (s *^ v)` for the smallest (most negative) value of `s`. Return `Nothing` if there is no intersection. See also `traceP`.

See also `rayTraceV` which uses the smallest positive intersection, which is often more intuitive behavior.

traceP :: (n ~ N a, Traced a, Num n) => Point (V a) n -> V a n -> a -> Maybe (Point (V a) n) Source #

Compute the "smallest" boundary point along the line determined by the given point `p` and vector `v`. The "smallest" boundary point is defined as the one given by `p .+^ (s *^ v)` for the smallest (most negative) value of `s`. Return `Nothing` if there is no such boundary point. See also `traceV`.

See also `rayTraceP` which uses the smallest positive intersection, which is often more intuitive behavior.

maxTraceV :: (n ~ N a, Num n, Traced a) => Point (V a) n -> V a n -> a -> Maybe (V a n) Source #

Like `traceV`, but computes a vector to the "largest" boundary point instead of the smallest. (Note, however, the "largest" boundary point may still be in the opposite direction from the given vector, if all the boundary points are, as in the third example shown below.)

maxTraceP :: (n ~ N a, Num n, Traced a) => Point (V a) n -> V a n -> a -> Maybe (Point (V a) n) Source #

Like `traceP`, but computes the "largest" boundary point instead of the smallest. (Note, however, the "largest" boundary point may still be in the opposite direction from the given vector, if all the boundary points are.)

getRayTrace :: (n ~ N a, Traced a, Num n) => a -> Trace (V a) n Source #

Get a modified `Trace` for an object which only returns positive boundary points, i.e. those boundary points given by a positive scalar multiple of the direction vector. Note, this property will be destroyed if the resulting `Trace` is translated at all.

rayTraceV :: (n ~ N a, Traced a, Num n) => Point (V a) n -> V a n -> a -> Maybe (V a n) Source #

Compute the vector from the given point to the closest boundary point of the given object in the given direction, or `Nothing` if there is no such boundary point (as in the third example below). Note that unlike `traceV`, only positive boundary points are considered, i.e. boundary points corresponding to a positive scalar multiple of the direction vector. This is intuitively the "usual" behavior of a raytracer, which only considers intersections "in front of" the camera. Compare the second example diagram below with the second example shown for `traceV`.

rayTraceP :: (n ~ N a, Traced a, Num n) => Point (V a) n -> V a n -> a -> Maybe (Point (V a) n) Source #

Compute the boundary point on an object which is closest to the given base point in the given direction, or `Nothing` if there is no such boundary point. Note that unlike `traceP`, only positive boundary points are considered, i.e. boundary points corresponding to a positive scalar multiple of the direction vector. This is intuitively the "usual" behavior of a raytracer, which only considers intersection points "in front of" the camera.

maxRayTraceV :: (n ~ N a, Traced a, Num n) => Point (V a) n -> V a n -> a -> Maybe (V a n) Source #

Like `rayTraceV`, but computes a vector to the "largest" boundary point instead of the smallest. Considers only positive boundary points.

maxRayTraceP :: (n ~ N a, Traced a, Num n) => Point (V a) n -> V a n -> a -> Maybe (Point (V a) n) Source #

Like `rayTraceP`, but computes the "largest" boundary point instead of the smallest. Considers only positive boundary points.