diagrams-core-1.1.0.3: Core libraries for diagrams EDSL

Copyright(c) 2012 diagrams-core team (see LICENSE)
LicenseBSD-style (see LICENSE)
Maintainerdiagrams-discuss@googlegroups.com
Safe HaskellNone
LanguageHaskell2010

Diagrams.Core.Trace

Contents

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

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

Ord a => Monoid (SortedList a)

SortedList forms a monoid with merge and the empty list.

Ord a => Semigroup (SortedList a)

SortedList forms a semigroup with merge as composition.

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 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 

Fields

appTrace :: Point v -> v -> SortedList (Scalar v)
 

Instances

Action Name (Trace v) 
Show (Trace v) 
Ord (Scalar v) => Monoid (Trace v) 
Ord (Scalar v) => Semigroup (Trace v) 
Wrapped (Trace v) 
VectorSpace v => HasOrigin (Trace v) 
HasLinearMap v => Transformable (Trace v) 
(Ord (Scalar v), VectorSpace v) => Traced (Trace v) 
Rewrapped (Trace v) (Trace v') 
type Unwrapped (Trace v) = Point v -> v -> SortedList (Scalar v) 
type V (Trace v) = v 

mkTrace :: (Point v -> v -> SortedList (Scalar v)) -> Trace v Source

Traced class

class (Ord (Scalar (V a)), VectorSpace (V a)) => Traced a where Source

Traced abstracts over things which have a trace.

Methods

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

Compute the trace of an object.

Instances

Traced b => Traced [b] 
Traced b => Traced (Set b) 
(Ord (Scalar v), VectorSpace v) => Traced (Point v)

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).

Traced t => Traced (TransInv t) 
(Ord (Scalar v), VectorSpace v) => Traced (Trace v) 
(Traced a, Traced b, (~) * (V a) (V b)) => Traced (a, b) 
Traced b => Traced (Map k b) 
(OrderedField (Scalar v), HasLinearMap v, InnerSpace v, Semigroup m) => Traced (Subdiagram b v m) 
(HasLinearMap v, VectorSpace v, Ord (Scalar v), InnerSpace v, Semigroup m, Fractional (Scalar v), Floating (Scalar v)) => Traced (QDiagram b v m) 

Computing with traces

traceV :: Traced a => Point (V a) -> V a -> a -> Maybe (V a) 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 :: Traced a => Point (V a) -> V a -> a -> Maybe (Point (V a)) 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 :: Traced a => Point (V a) -> V a -> a -> Maybe (V a) 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 :: Traced a => Point (V a) -> V a -> a -> Maybe (Point (V a)) 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 :: (Traced a, Num (Scalar (V a))) => a -> Trace (V a) 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 :: (Traced a, Num (Scalar (V a))) => Point (V a) -> V a -> a -> Maybe (V a) 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 :: (Traced a, Num (Scalar (V a))) => Point (V a) -> V a -> a -> Maybe (Point (V a)) 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 :: (Traced a, Num (Scalar (V a))) => Point (V a) -> V a -> a -> Maybe (V a) Source

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

maxRayTraceP :: (Traced a, Num (Scalar (V a))) => Point (V a) -> V a -> a -> Maybe (Point (V a)) Source

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