diagrams-lib-1.4.2.3: Embedded domain-specific language for declarative graphics

Diagrams.Envelope

Description

"Envelopes", aka functional bounding regions. See Diagrams.Core.Envelope for internal implementation details.

Synopsis

# Types

data Envelope (v :: Type -> Type) n #

Every diagram comes equipped with an envelope. What is an envelope?

Consider first the idea of a bounding box. A bounding box expresses the distance to a bounding plane in every direction parallel to an axis. That is, a bounding box can be thought of as the intersection of a collection of half-planes, two perpendicular to each axis.

More generally, the intersection of half-planes in every direction would give a tight "bounding region", or convex hull. However, representing such a thing intensionally would be impossible; hence bounding boxes are often used as an approximation.

An envelope is an extensional representation of such a "bounding region". Instead of storing some sort of direct representation, we store a function which takes a direction as input and gives a distance to a bounding half-plane as output. The important point is that envelopes can be composed, and transformed by any affine transformation.

Formally, given a vector v, the envelope computes a scalar s such that

• for every point u inside the diagram, if the projection of (u - origin) onto v is s' *^ v, then s' <= s.
• s is the smallest such scalar.

There is also a special "empty envelope".

The idea for envelopes came from Sebastian Setzer; see http://byorgey.wordpress.com/2009/10/28/collecting-attributes/#comment-2030. See also Brent Yorgey, Monoids: Theme and Variations, published in the 2012 Haskell Symposium: http://ozark.hendrix.edu/~yorgey/pub/monoid-pearl.pdf; video: http://www.youtube.com/watch?v=X-8NCkD2vOw.

Instances
 Show (Envelope v n) Instance detailsDefined in Diagrams.Core.Envelope MethodsshowsPrec :: Int -> Envelope v n -> ShowS #show :: Envelope v n -> String #showList :: [Envelope v n] -> ShowS # Ord n => Semigroup (Envelope v n) Envelopes form a semigroup with pointwise maximum as composition. Hence, if e1 is the envelope for diagram d1, and e2 is the envelope for d2, then e1 mappend e2 is the envelope for d1 atop d2. Instance detailsDefined in Diagrams.Core.Envelope Methods(<>) :: Envelope v n -> Envelope v n -> Envelope v n #sconcat :: NonEmpty (Envelope v n) -> Envelope v n #stimes :: Integral b => b -> Envelope v n -> Envelope v n # Ord n => Monoid (Envelope v n) The special empty envelope is the identity for the Monoid instance. Instance detailsDefined in Diagrams.Core.Envelope Methodsmempty :: Envelope v n #mappend :: Envelope v n -> Envelope v n -> Envelope v n #mconcat :: [Envelope v n] -> Envelope v n # (Metric v, OrderedField n) => Juxtaposable (Envelope v n) Instance detailsDefined in Diagrams.Core.Juxtapose Methodsjuxtapose :: Vn (Envelope v n) -> Envelope v n -> Envelope v n -> Envelope v n # (Metric v, OrderedField n) => Enveloped (Envelope v n) Instance detailsDefined in Diagrams.Core.Envelope MethodsgetEnvelope :: Envelope v n -> Envelope (V (Envelope v n)) (N (Envelope v n)) # (Metric v, Floating n) => Transformable (Envelope v n) Instance detailsDefined in Diagrams.Core.Envelope Methodstransform :: Transformation (V (Envelope v n)) (N (Envelope v n)) -> Envelope v n -> Envelope v n # (Metric v, Fractional n) => HasOrigin (Envelope v n) The local origin of an envelope is the point with respect to which bounding queries are made, i.e. the point from which the input vectors are taken to originate. Instance detailsDefined in Diagrams.Core.Envelope MethodsmoveOriginTo :: Point (V (Envelope v n)) (N (Envelope v n)) -> Envelope v n -> Envelope v n # Wrapped (Envelope v n) Instance detailsDefined in Diagrams.Core.Envelope Associated Typestype Unwrapped (Envelope v n) :: Type # Methods_Wrapped' :: Iso' (Envelope v n) (Unwrapped (Envelope v n)) # (Metric v, OrderedField n) => Alignable (Envelope v n) # Instance detailsDefined in Diagrams.Align MethodsalignBy' :: (InSpace v0 n0 (Envelope v n), Fractional n0, HasOrigin (Envelope v n)) => (v0 n0 -> Envelope v n -> Point v0 n0) -> v0 n0 -> n0 -> Envelope v n -> Envelope v n #defaultBoundary :: (V (Envelope v n) ~ v0, N (Envelope v n) ~ n0) => v0 n0 -> Envelope v n -> Point v0 n0 #alignBy :: (InSpace v0 n0 (Envelope v n), Fractional n0, HasOrigin (Envelope v n)) => v0 n0 -> n0 -> Envelope v n -> Envelope v n # Rewrapped (Envelope v n) (Envelope v' n') Instance detailsDefined in Diagrams.Core.Envelope type V (Envelope v n) Instance detailsDefined in Diagrams.Core.Envelope type V (Envelope v n) = v type N (Envelope v n) Instance detailsDefined in Diagrams.Core.Envelope type N (Envelope v n) = n type Unwrapped (Envelope v n) Instance detailsDefined in Diagrams.Core.Envelope type Unwrapped (Envelope v n) = Option (v n -> Max n)

class (Metric (V a), OrderedField (N a)) => Enveloped a #

Enveloped abstracts over things which have an envelope.

Minimal complete definition

getEnvelope

Instances
 Enveloped b => Enveloped [b] Instance detailsDefined in Diagrams.Core.Envelope MethodsgetEnvelope :: [b] -> Envelope (V [b]) (N [b]) # Enveloped b => Enveloped (Set b) Instance detailsDefined in Diagrams.Core.Envelope MethodsgetEnvelope :: Set b -> Envelope (V (Set b)) (N (Set b)) # Enveloped t => Enveloped (TransInv t) Instance detailsDefined in Diagrams.Core.Envelope MethodsgetEnvelope :: TransInv t -> Envelope (V (TransInv t)) (N (TransInv t)) # RealFloat n => Enveloped (CSG n) # The Envelope for an Intersection or Difference is simply the Envelope of the Union. This is wrong but easy to implement. Instance detailsDefined in Diagrams.ThreeD.Shapes MethodsgetEnvelope :: CSG n -> Envelope (V (CSG n)) (N (CSG n)) # (OrderedField n, RealFloat n) => Enveloped (Frustum n) # Instance detailsDefined in Diagrams.ThreeD.Shapes MethodsgetEnvelope :: Frustum n -> Envelope (V (Frustum n)) (N (Frustum n)) # OrderedField n => Enveloped (Box n) # Instance detailsDefined in Diagrams.ThreeD.Shapes MethodsgetEnvelope :: Box n -> Envelope (V (Box n)) (N (Box n)) # # Instance detailsDefined in Diagrams.ThreeD.Shapes MethodsgetEnvelope :: Ellipsoid n -> Envelope (V (Ellipsoid n)) (N (Ellipsoid n)) # Enveloped a => Enveloped (Located a) # The envelope of a Located a is the envelope of the a, translated to the location. Instance detailsDefined in Diagrams.Located MethodsgetEnvelope :: Located a -> Envelope (V (Located a)) (N (Located a)) # (Enveloped a, Enveloped b, V a ~ V b, N a ~ N b) => Enveloped (a, b) Instance detailsDefined in Diagrams.Core.Envelope MethodsgetEnvelope :: (a, b) -> Envelope (V (a, b)) (N (a, b)) # Enveloped b => Enveloped (Map k b) Instance detailsDefined in Diagrams.Core.Envelope MethodsgetEnvelope :: Map k b -> Envelope (V (Map k b)) (N (Map k b)) # (Metric v, OrderedField n) => Enveloped (Envelope v n) Instance detailsDefined in Diagrams.Core.Envelope MethodsgetEnvelope :: Envelope v n -> Envelope (V (Envelope v n)) (N (Envelope v n)) # (OrderedField n, Metric v) => Enveloped (Point v n) Instance detailsDefined in Diagrams.Core.Envelope MethodsgetEnvelope :: Point v n -> Envelope (V (Point v n)) (N (Point v n)) # (Metric v, OrderedField n) => Enveloped (FixedSegment v n) # Instance detailsDefined in Diagrams.Segment MethodsgetEnvelope :: FixedSegment v n -> Envelope (V (FixedSegment v n)) (N (FixedSegment v n)) # (Metric v, OrderedField n) => Enveloped (Trail v n) # Instance detailsDefined in Diagrams.Trail MethodsgetEnvelope :: Trail v n -> Envelope (V (Trail v n)) (N (Trail v n)) # (Metric v, OrderedField n) => Enveloped (Path v n) # Instance detailsDefined in Diagrams.Path MethodsgetEnvelope :: Path v n -> Envelope (V (Path v n)) (N (Path v n)) # (Metric v, Traversable v, OrderedField n) => Enveloped (BoundingBox v n) # Instance detailsDefined in Diagrams.BoundingBox MethodsgetEnvelope :: BoundingBox v n -> Envelope (V (BoundingBox v n)) (N (BoundingBox v n)) # (Metric v, OrderedField n) => Enveloped (Segment Closed v n) # The envelope for a segment is based at the segment's start. Instance detailsDefined in Diagrams.Segment MethodsgetEnvelope :: Segment Closed v n -> Envelope (V (Segment Closed v n)) (N (Segment Closed v n)) # (Metric v, OrderedField n) => Enveloped (Trail' l v n) # The envelope for a trail is based at the trail's start. Instance detailsDefined in Diagrams.Trail MethodsgetEnvelope :: Trail' l v n -> Envelope (V (Trail' l v n)) (N (Trail' l v n)) # (Metric v, OrderedField n, Monoid' m) => Enveloped (QDiagram b v n m) Instance detailsDefined in Diagrams.Core.Types MethodsgetEnvelope :: QDiagram b v n m -> Envelope (V (QDiagram b v n m)) (N (QDiagram b v n m)) # (OrderedField n, Metric v, Monoid' m) => Enveloped (Subdiagram b v n m) Instance detailsDefined in Diagrams.Core.Types MethodsgetEnvelope :: Subdiagram b v n m -> Envelope (V (Subdiagram b v n m)) (N (Subdiagram b v n m)) #

# Diagram envelopes

envelope :: (OrderedField n, Metric v, Monoid' m) => Lens' (QDiagram b v n m) (Envelope v n) #

Lens onto the Envelope of a QDiagram.

setEnvelope :: (OrderedField n, Metric v, Monoid' m) => Envelope v n -> QDiagram b v n m -> QDiagram b v n m #

Replace the envelope of a diagram.

withEnvelope :: (InSpace v n a, Monoid' m, Enveloped a) => a -> QDiagram b v n m -> QDiagram b v n m #

Use the envelope from some object as the envelope for a diagram, in place of the diagram's default envelope. sqNewEnv =
circle 1 # fc green
|||
(    c # dashingG [0.1,0.1] 0 # lc white
<> square 2 # withEnvelope (c :: D V2 Double) # fc blue
)
c = circle 0.8
withEnvelopeEx = sqNewEnv # centerXY # pad 1.5

phantom :: (InSpace v n a, Monoid' m, Enveloped a, Traced a) => a -> QDiagram b v n m #

phantom x produces a "phantom" diagram, which has the same envelope and trace as x but produces no output.

pad :: (Metric v, OrderedField n, Monoid' m) => n -> QDiagram b v n m -> QDiagram b v n m #

pad s "pads" a diagram, expanding its envelope by a factor of s (factors between 0 and 1 can be used to shrink the envelope). Note that the envelope will expand with respect to the local origin, so if the origin is not centered the padding may appear "uneven". If this is not desired, the origin can be centered (using, e.g., centerXY for 2D diagrams) before applying pad.

extrudeEnvelope :: (Metric v, OrderedField n, Monoid' m) => v n -> QDiagram b v n m -> QDiagram b v n m #

extrudeEnvelope v d asymmetrically "extrudes" the envelope of a diagram in the given direction. All parts of the envelope within 90 degrees of this direction are modified, offset outwards by the magnitude of the vector.

This works by offsetting the envelope distance proportionally to the cosine of the difference in angle, and leaving it unchanged when this factor is negative.

intrudeEnvelope :: (Metric v, OrderedField n, Monoid' m) => v n -> QDiagram b v n m -> QDiagram b v n m #

intrudeEnvelope v d asymmetrically "intrudes" the envelope of a diagram away from the given direction. All parts of the envelope within 90 degrees of this direction are modified, offset inwards by the magnitude of the vector.

Note that this could create strange inverted envelopes, where  diameter v d < 0 .

# Querying envelopes

envelopeVMay :: Enveloped a => Vn a -> a -> Maybe (Vn a) #

Compute the vector from the local origin to a separating hyperplane in the given direction, or Nothing for the empty envelope.

envelopeV :: Enveloped a => Vn a -> a -> Vn a #

Compute the vector from the local origin to a separating hyperplane in the given direction. Returns the zero vector for the empty envelope.

envelopePMay :: (V a ~ v, N a ~ n, Enveloped a) => v n -> a -> Maybe (Point v n) #

Compute the point on a separating hyperplane in the given direction, or Nothing for the empty envelope.

envelopeP :: (V a ~ v, N a ~ n, Enveloped a) => v n -> a -> Point v n #

Compute the point on a separating hyperplane in the given direction. Returns the origin for the empty envelope.

diameter :: (V a ~ v, N a ~ n, Enveloped a) => v n -> a -> n #

Compute the diameter of a enveloped object along a particular vector. Returns zero for the empty envelope.

radius :: (V a ~ v, N a ~ n, Enveloped a) => v n -> a -> n #

Compute the "radius" (1/2 the diameter) of an enveloped object along a particular vector.