{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}
module Diagrams.Tangent
(
tangentAtParam
, tangentAtStart
, tangentAtEnd
, normalAtParam
, normalAtStart
, normalAtEnd
, Tangent(..)
)
where
import Diagrams.Core
import Diagrams.Located
import Diagrams.Parametric
import Diagrams.Segment
import Linear.Vector
import Linear.Metric
import Linear.V2
newtype Tangent t = Tangent t
type instance V (Tangent t) = V t
type instance N (Tangent t) = N t
type instance Codomain (Tangent t) = V t
instance DomainBounds t => DomainBounds (Tangent t) where
domainLower (Tangent t) = domainLower t
domainUpper (Tangent t) = domainUpper t
instance Parametric (Tangent t) => Parametric (Tangent (Located t)) where
Tangent l `atParam` p = Tangent (unLoc l) `atParam` p
instance (DomainBounds t, EndValues (Tangent t))
=> EndValues (Tangent (Located t)) where
atStart (Tangent l) = atStart (Tangent (unLoc l))
atEnd (Tangent l) = atEnd (Tangent (unLoc l))
tangentAtParam :: Parametric (Tangent t) => t -> N t -> Vn t
tangentAtParam t p = Tangent t `atParam` p
tangentAtStart :: EndValues (Tangent t) => t -> Vn t
tangentAtStart = atStart . Tangent
tangentAtEnd :: EndValues (Tangent t) => t -> Vn t
tangentAtEnd = atEnd . Tangent
instance (Additive v, Num n)
=> Parametric (Tangent (Segment Closed v n)) where
Tangent (Linear (OffsetClosed v)) `atParam` _ = v
Tangent (Cubic c1 c2 (OffsetClosed x2)) `atParam` p
= (3*(3*p*p-4*p+1))*^c1 ^+^ (3*(2-3*p)*p)*^c2 ^+^ (3*p*p)*^x2
instance (Additive v, Num n)
=> EndValues (Tangent (Segment Closed v n)) where
atStart (Tangent (Linear (OffsetClosed v))) = v
atStart (Tangent (Cubic c1 _ _)) = c1
atEnd (Tangent (Linear (OffsetClosed v))) = v
atEnd (Tangent (Cubic _ c2 (OffsetClosed x2))) = x2 ^-^ c2
instance (Additive v, Num n)
=> Parametric (Tangent (FixedSegment v n)) where
atParam (Tangent fSeg) = atParam $ Tangent (fromFixedSeg fSeg)
instance (Additive v, Num n)
=> EndValues (Tangent (FixedSegment v n)) where
atStart (Tangent fSeg) = atStart $ Tangent (fromFixedSeg fSeg)
atEnd (Tangent fSeg) = atEnd $ Tangent (fromFixedSeg fSeg)
normalAtParam
:: (InSpace V2 n t, Parametric (Tangent t), Floating n)
=> t -> n -> V2 n
normalAtParam t p = normize (t `tangentAtParam` p)
normalAtStart
:: (InSpace V2 n t, EndValues (Tangent t), Floating n)
=> t -> V2 n
normalAtStart = normize . tangentAtStart
normalAtEnd
:: (InSpace V2 n t, EndValues (Tangent t), Floating n)
=> t -> V2 n
normalAtEnd = normize . tangentAtEnd
normize :: Floating n => V2 n -> V2 n
normize = negated . perp . signorm