    {-# LANGUAGE ConstraintKinds #-}
    {-# LANGUAGE FlexibleContexts #-}
    {-# LANGUAGE MonoLocalBinds   #-}

    {-# OPTIONS_GHC -fno-warn-unused-imports #-}
      -- for Data.Semigroup

    -----------------------------------------------------------------------------
    -- |
    -- Module      :  Diagrams.Trace
    -- Copyright   :  (c) 2013 diagrams-lib team (see LICENSE)
    -- License     :  BSD-style (see LICENSE)
    -- Maintainer  :  diagrams-discuss@googlegroups.com
    --
    -- \"Traces\", aka embedded raytracers, for finding points on the edge
    -- of a diagram.  See "Diagrams.Core.Trace" for internal
    -- implementation details.
    --
    -----------------------------------------------------------------------------

    module Diagrams.Trace
        ( -- * Types
          Trace, Traced

          -- * Diagram traces
        , trace, setTrace, withTrace

          -- * Querying traces
        , traceV, traceP, maxTraceV, maxTraceP

          -- * Subdiagram traces
        , boundaryFrom, boundaryFromMay

        ) where

    import           Diagrams.Core        (OrderedField, Point, Subdiagram, location,
                                           origin, setTrace, trace)
    import           Diagrams.Core.Trace

    import           Data.Maybe
    import           Data.Semigroup
    import           Diagrams.Combinators (withTrace)

    import           Linear.Metric
    import           Linear.Vector

    -- | Compute the furthest point on the boundary of a subdiagram,
    --   beginning from the location (local origin) of the subdiagram and
    --   moving in the direction of the given vector.  If there is no such
    --   point, the origin is returned; see also 'boundaryFromMay'.
    boundaryFrom :: (OrderedField n, Metric v, Semigroup m)
                  => Subdiagram b v n m -> v n -> Point v n
    boundaryFrom :: forall n (v :: * -> *) m b.
    (OrderedField n, Metric v, Semigroup m) =>
    Subdiagram b v n m -> v n -> Point v n
    boundaryFrom Subdiagram b v n m
    s v n
    v = Point v n -> Maybe (Point v n) -> Point v n
    forall a. a -> Maybe a -> a
    fromMaybe Point v n
    forall (f :: * -> *) a. (Additive f, Num a) => Point f a
    origin (Maybe (Point v n) -> Point v n) -> Maybe (Point v n) -> Point v n
    forall a b. (a -> b) -> a -> b
    $ Subdiagram b v n m -> v n -> Maybe (Point v n)
    forall (v :: * -> *) n m b.
    (Metric v, OrderedField n, Semigroup m) =>
    Subdiagram b v n m -> v n -> Maybe (Point v n)
    boundaryFromMay Subdiagram b v n m
    s v n
    v

    -- | Compute the furthest point on the boundary of a subdiagram,
    --   beginning from the location (local origin) of the subdiagram and
    --   moving in the direction of the given vector, or @Nothing@ if
    --   there is no such point.
    boundaryFromMay :: (Metric v, OrderedField n, Semigroup m)
                    => Subdiagram b v n m -> v n -> Maybe (Point v n)
    boundaryFromMay :: forall (v :: * -> *) n m b.
    (Metric v, OrderedField n, Semigroup m) =>
    Subdiagram b v n m -> v n -> Maybe (Point v n)
    boundaryFromMay Subdiagram b v n m
    s v n
    v = Point (V (Subdiagram b v n m)) n
    -> V (Subdiagram b v n m) n
    -> Subdiagram b v n m
    -> Maybe (Point (V (Subdiagram b v n m)) n)
    forall n a.
    (n ~ N a, Traced a, Num n) =>
    Point (V a) n -> V a n -> a -> Maybe (Point (V a) n)
    traceP (Subdiagram b v n m -> Point v n
    forall (v :: * -> *) n b m.
    (Additive v, Num n) =>
    Subdiagram b v n m -> Point v n
    location Subdiagram b v n m
    s) (v n -> v n
    forall (f :: * -> *) a. (Functor f, Num a) => f a -> f a
    negated v n
    v) Subdiagram b v n m
    s