{-# 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 = forall a. a -> Maybe a -> a
fromMaybe forall (f :: * -> *) a. (Additive f, Num a) => Point f a
origin forall a b. (a -> b) -> a -> b
$ 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 = forall n a.
(n ~ N a, Traced a, Num n) =>
Point (V a) n -> V a n -> a -> Maybe (Point (V a) n)
traceP (forall (v :: * -> *) n b m.
(Additive v, Num n) =>
Subdiagram b v n m -> Point v n
location Subdiagram b v n m
s) (forall (f :: * -> *) a. (Functor f, Num a) => f a -> f a
negated v n
v) Subdiagram b v n m
s