-
Notifications
You must be signed in to change notification settings - Fork 43
Commit
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,8 +25,11 @@ | |
----------------------------------------------------------------------------- | ||
|
||
module Diagrams.Core.Trace | ||
( -- * Traces | ||
Trace(Trace) | ||
( -- * SortedList | ||
SortedList(SortedList) | ||
|
||
-- * Traces | ||
, Trace(Trace) | ||
|
||
, appTrace | ||
, mkTrace | ||
|
@@ -47,20 +50,40 @@ module Diagrams.Core.Trace | |
|
||
import Control.Applicative | ||
import Control.Lens | ||
import Data.List (insert) | ||
import qualified Data.Map as M | ||
import Data.Semigroup | ||
import qualified Data.Set as S | ||
|
||
import Data.AffineSpace | ||
import Data.Monoid.Inf | ||
import Data.VectorSpace | ||
|
||
import Diagrams.Core.HasOrigin | ||
import Diagrams.Core.Points | ||
import Diagrams.Core.Transform | ||
import Diagrams.Core.V | ||
|
||
------------------------------------------------------------ | ||
-- SortedList ------------------------------------------------- | ||
------------------------------------------------------------ | ||
|
||
newtype SortedList a = SortedList [a] | ||
|
||
instance Wrapped [a] [a] (SortedList a) (SortedList a) | ||
where wrapped = iso SortedList $ \(SortedList x) -> x | ||
|
||
instance Ord a => Semigroup (SortedList a) where | ||
sl0 <> sl1 = SortedList $ merge (view unwrapped sl0) (view unwrapped sl1) | ||
where | ||
merge xList@(x:xs) yList@(y:ys) = | ||
if x <= y then x : merge xs yList else y : merge xList ys | ||
merge xList@(_:_) [] = xList | ||
merge [] yList@(_:_) = yList | ||
merge [] [] = [] | ||
|
||
instance Ord a => Monoid (SortedList a) where | ||
mappend = (<>) | ||
mempty = SortedList [] | ||
|
||
------------------------------------------------------------ | ||
-- Trace ------------------------------------------------- | ||
------------------------------------------------------------ | ||
|
@@ -82,32 +105,37 @@ import Diagrams.Core.V | |
-- scalar is @s@, the distance from the base point to the | ||
-- intersection is given by @s * magnitude v@. | ||
|
||
newtype Trace v = Trace { appTrace :: Point v -> v -> [PosInf (Scalar v)] } | ||
newtype Trace v = Trace { appTrace :: Point v -> v -> SortedList (Scalar v) } | ||
|
||
instance (Scalar v ~ s, Scalar v' ~ s', s ~ s') => | ||
Wrapped | ||
(Point v -> v -> [PosInf s]) | ||
(Point v' -> v' -> [PosInf s']) | ||
(Point v -> v -> SortedList s) | ||
(Point v' -> v' -> SortedList s') | ||
(Trace v) (Trace v') | ||
where wrapped = iso Trace appTrace | ||
|
||
mkTrace :: (Point v -> v -> [PosInf (Scalar v)]) -> Trace v | ||
mkTrace :: (Point v -> v -> SortedList (Scalar v)) -> Trace v | ||
mkTrace = Trace | ||
|
||
-- | 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 Ord (Scalar v) => Semigroup (Trace v) where | ||
ts1 <> ts2 = mkTrace tr | ||
where | ||
tr p v = foldr insert (appTrace ts1 p v) (appTrace ts2 p v) | ||
|
||
--instance Ord (Scalar v) => Semigroup (Trace v) where | ||
-- ts1 <> ts2 = mkTrace tr | ||
-- where | ||
-- tr p v = foldr insert (appTrace ts1 p v) (appTrace ts2 p v) | ||
|
||
deriving instance (Ord (Scalar v)) =>Semigroup (Trace v) | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
jeffreyrosenbluth
Author
Member
|
||
|
||
|
||
-- | The identity for the 'Monoid' instance is the constantly infinite | ||
-- trace. | ||
This comment has been minimized.
Sorry, something went wrong.
byorgey
Member
|
||
instance Ord (Scalar v) => Monoid (Trace v) where | ||
mappend = (<>) | ||
mempty = mkTrace $ \_ _ -> [mempty] | ||
deriving instance (Ord (Scalar v)) => Monoid (Trace v) | ||
--instance Ord (Scalar v) => Monoid (Trace v) where | ||
-- mappend = (<>) | ||
-- mempty = mkTrace $ \_ _ -> [] | ||
|
||
type instance V (Trace v) = v | ||
|
||
|
@@ -170,9 +198,9 @@ instance (Traced b) => Traced (S.Set b) where | |
-- given object in either the given direction or the opposite direction. | ||
-- Return @Nothing@ if there is no intersection. | ||
traceV :: Traced a => Point (V a) -> V a -> a -> Maybe (V a) | ||
traceV p v a = case head $ ((getTrace a)^.unwrapping Trace) p v of | ||
Finite s -> Just (s *^ v) | ||
Infinity -> Nothing | ||
traceV p v a = case view unwrapped $ ((getTrace a)^.unwrapping Trace) p v of | ||
(s:_) -> Just (s *^ v) | ||
[] -> Nothing | ||
|
||
-- | Given a base point and direction, compute the closest point on | ||
-- the boundary of the given object in the direction or its opposite. | ||
|
@@ -194,26 +222,18 @@ maxTraceP p v a = (p .+^) <$> maxTraceV p v a | |
-- but not in the opposite direction like `getTrace`. I.e. only return | ||
-- positive traces. | ||
getRayTrace :: (Traced a, Num (Scalar (V a))) => a -> Trace (V a) | ||
getRayTrace a = Trace tr | ||
where | ||
scalars [] = [] | ||
scalars (Infinity : xs) = scalars xs | ||
scalars (Finite x : xs) = x : scalars xs | ||
tr p v = let | ||
ts = ((getTrace a)^.unwrapping Trace) p v | ||
ps = filter (>= 0) (scalars ts) | ||
in case ps of | ||
[] -> [Infinity] | ||
qs -> map Finite qs | ||
getRayTrace a = Trace $ \p v -> | ||
SortedList $ filter (>= 0) (view unwrapped | ||
$ (((getTrace a)^.unwrapping Trace) p v)) | ||
|
||
-- | Compute the vector from the given point to the boundary of the | ||
-- given object in the given direction, or @Nothing@ if there is no | ||
-- intersection. Only positive scale muliples of the direction are returned | ||
rayTraceV :: (Traced a, Num (Scalar (V a))) | ||
=> Point (V a) -> V a -> a -> Maybe (V a) | ||
rayTraceV p v a = case head $ ((getRayTrace a)^.unwrapping Trace) p v of | ||
Finite s -> Just (s *^ v) | ||
Infinity -> Nothing | ||
rayTraceV p v a = case view unwrapped $ ((getRayTrace a)^.unwrapping Trace) p v of | ||
(s:_) -> Just (s *^ v) | ||
[] -> Nothing | ||
|
||
-- | Given a base point and direction, compute the closest point on | ||
-- the boundary of the given object, or @Nothing@ if there is no | ||
|
@@ -227,9 +247,9 @@ rayTraceP p v a = (p .+^) <$> rayTraceV p v a | |
maxRayTraceV :: (Traced a, Num (Scalar (V a))) | ||
=> Point (V a) -> V a -> a -> Maybe (V a) | ||
maxRayTraceV p v a = | ||
case last $ ((getRayTrace a)^.unwrapping Trace) p v of | ||
Finite s -> Just (s *^ v) | ||
Infinity -> Nothing | ||
case view unwrapped $ ((getRayTrace a)^.unwrapping Trace) p v of | ||
[] -> Nothing | ||
xs -> Just ((last xs) *^ v) | ||
|
||
-- | Like 'rayTraceP', but computes the *furthest* point on the boundary | ||
-- instead of the closest. | ||
|
I think it should be possible to attach this
deriving
clause directly to the definition ofTrace
.