module Linear.NURBS.Types (
Weight(..), weightPoint, weightValue, ofWeight, weight, wpoint,
Span(..), spanStart, spanEnd,
KnotData(..), knotData, knotDataAt, knotDataSpan,
NURBS(..), nurbsPoints, nurbsKnot, nurbsKnoti, nurbsDegree
) where
import Prelude.Unicode
import Control.Lens
import Linear.Vector hiding (basis)
import Linear.Affine
import Linear.Metric
data Weight f a = Weight { _weightPoint ∷ f a, _weightValue ∷ a } deriving (Eq, Ord, Read, Show)
makeLenses ''Weight
ofWeight ∷ Additive f ⇒ f a → a → Weight f a
pt `ofWeight` w = Weight pt w
weight ∷ (Additive f, Fractional a) ⇒ Lens' (Weight f a) a
weight = lens fromw tow where
fromw (Weight _ w) = w
tow (Weight pt w) w' = Weight ((w' / w) *^ pt) w'
wpoint ∷ (Additive f, Additive g, Fractional a) ⇒ Lens (Weight f a) (Weight g a) (f a) (g a)
wpoint = lens fromw tow where
fromw (Weight pt w) = (1.0 / w) *^ pt
tow (Weight _ w) pt' = Weight (w *^ pt') w
instance Functor f ⇒ Functor (Weight f) where
fmap f (Weight pt w) = Weight (fmap f pt) (f w)
instance Traversable f ⇒ Traversable (Weight f) where
traverse f (Weight pt w) = Weight <$> traverse f pt <*> f w
instance Additive f ⇒ Additive (Weight f) where
zero = Weight zero 0
Weight lx lw ^+^ Weight rx rw = Weight (lx ^+^ rx) (lw + rw)
Weight lx lw ^-^ Weight rx rw = Weight (lx ^-^ rx) (lw rw)
lerp a (Weight lx lw) (Weight rx rw) = Weight (lerp a lx rx) (a * lw + (1 a) * rw)
liftU2 f (Weight lx lw) (Weight rx rw) = Weight (liftU2 f lx rx) (f lw rw)
liftI2 f (Weight lx lw) (Weight rx rw) = Weight (liftI2 f lx rx) (f lw rw)
instance Affine f ⇒ Affine (Weight f) where
type Diff (Weight f) = Weight (Diff f)
Weight lx lw .-. Weight rx rw = Weight (lx .-. rx) (lw rw)
Weight lx lw .+^ Weight x w = Weight (lx .+^ x) (lw + w)
Weight lx lw .-^ Weight x w = Weight (lx .-^ x) (lw w)
instance Foldable f ⇒ Foldable (Weight f) where
foldMap f (Weight x w) = foldMap f x `mappend` f w
instance Metric f ⇒ Metric (Weight f) where
dot (Weight lx lw) (Weight rx rw) = dot lx rx + lw * rw
data Span a = Span {
_spanStart ∷ a,
_spanEnd ∷ a }
deriving (Eq, Ord, Read)
makeLenses ''Span
instance Functor Span where
fmap f (Span s e) = Span (f s) (f e)
instance Foldable Span where
foldMap f (Span s e) = f s `mappend` f e
instance Traversable Span where
traverse f (Span s e) = Span <$> f s <*> f e
instance Show a ⇒ Show (Span a) where
show (Span s e) = show (s, e)
data KnotData a = KnotData {
_knotDataAt ∷ a,
_knotDataSpan ∷ Span a,
_knotData ∷ [(Span a, a)] }
deriving (Eq, Ord, Read, Show)
makeLenses ''KnotData
data NURBS f a = NURBS {
_nurbsPoints ∷ [Weight f a],
_nurbsKnot ∷ [a],
_nurbsDegree ∷ Int }
deriving (Eq, Ord, Read, Show)
makeLenses ''NURBS
instance Functor f ⇒ Functor (NURBS f) where
fmap f (NURBS pts k d) = NURBS (map (fmap f) pts) (map f k) d
instance Foldable f ⇒ Foldable (NURBS f) where
foldMap f (NURBS pts k _) = mconcat (map (foldMap f) pts) `mappend` mconcat (map f k)
nurbsKnoti ∷ Lens' (NURBS f a) [a]
nurbsKnoti = lens fromn ton where
fromn (NURBS wpts k d)
| length k ≡ succ (length wpts) = k
| otherwise = drop d $ reverse $ drop d $ reverse k
ton (NURBS wpts k d) k'
| length k ≡ succ (length wpts) = NURBS wpts k' d
| otherwise = NURBS wpts (replicate d (k' ^?! _head) ++ k' ++ replicate d (k' ^?! _last)) d