{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# OPTIONS_GHC -fno-warn-incomplete-patterns #-}
module Diagrams.CubicSpline (
cubicSpline,
BSpline,
bspline,
) where
import Control.Lens (view)
import Data.List.NonEmpty (NonEmpty (..))
import Diagrams.CubicSpline.NonSingleton (NonSingleton (..))
import Diagrams.Core
import Diagrams.CubicSpline.Boehm
import Diagrams.CubicSpline.Internal
import Diagrams.Located (Located, at, mapLoc)
import Diagrams.Segment
import Diagrams.Trail
import Diagrams.TrailLike (TrailLike (..))
import Linear.Affine
import Linear.Metric
cubicSpline :: (V t ~ v, N t ~ n, TrailLike t, Fractional (v n)) => Bool -> [Point v n] -> t
cubicSpline :: forall t (v :: * -> *) n.
(V t ~ v, N t ~ n, TrailLike t, Fractional (v n)) =>
Bool -> [Point v n] -> t
cubicSpline Bool
closed [] = Located (Trail v n) -> t
Located (Trail (V t) (N t)) -> t
forall t. TrailLike t => Located (Trail (V t) (N t)) -> t
trailLike (Located (Trail v n) -> t)
-> (Located (Trail' Line v n) -> Located (Trail v n))
-> Located (Trail' Line v n)
-> t
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bool -> Located (Trail' Line v n) -> Located (Trail v n)
forall (v :: * -> *) n.
(Metric v, OrderedField n) =>
Bool -> Located (Trail' Line v n) -> Located (Trail v n)
closeIf Bool
closed (Located (Trail' Line v n) -> t) -> Located (Trail' Line v n) -> t
forall a b. (a -> b) -> a -> b
$ Trail' Line v n
forall (v :: * -> *) n.
(Metric v, OrderedField n) =>
Trail' Line v n
emptyLine Trail' Line v n
-> Point (V (Trail' Line v n)) (N (Trail' Line v n))
-> Located (Trail' Line v n)
forall a. a -> Point (V a) (N a) -> Located a
`at` Point v n
Point (V (Trail' Line v n)) (N (Trail' Line v n))
forall (f :: * -> *) a. (Additive f, Num a) => Point f a
origin
cubicSpline Bool
closed [Point v n
p] = Located (Trail v n) -> t
Located (Trail (V t) (N t)) -> t
forall t. TrailLike t => Located (Trail (V t) (N t)) -> t
trailLike (Located (Trail v n) -> t)
-> (Located (Trail' Line v n) -> Located (Trail v n))
-> Located (Trail' Line v n)
-> t
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bool -> Located (Trail' Line v n) -> Located (Trail v n)
forall (v :: * -> *) n.
(Metric v, OrderedField n) =>
Bool -> Located (Trail' Line v n) -> Located (Trail v n)
closeIf Bool
closed (Located (Trail' Line v n) -> t) -> Located (Trail' Line v n) -> t
forall a b. (a -> b) -> a -> b
$ Trail' Line v n
forall (v :: * -> *) n.
(Metric v, OrderedField n) =>
Trail' Line v n
emptyLine Trail' Line v n
-> Point (V (Trail' Line v n)) (N (Trail' Line v n))
-> Located (Trail' Line v n)
forall a. a -> Point (V a) (N a) -> Located a
`at` Point v n
Point (V (Trail' Line v n)) (N (Trail' Line v n))
p
cubicSpline Bool
closed (Point v n
p1 : Point v n
p2 : [Point v n]
ps) = [[v n]] -> t
flattenBeziers ([[v n]] -> t)
-> (NonSingleton (Point v n) -> [[v n]])
-> NonSingleton (Point v n)
-> t
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([v n] -> [v n]) -> [[v n]] -> [[v n]]
forall a b. (a -> b) -> [a] -> [b]
map [v n] -> [v n]
forall {a}. Fractional a => [a] -> [a]
f ([[v n]] -> [[v n]])
-> (NonSingleton (Point v n) -> [[v n]])
-> NonSingleton (Point v n)
-> [[v n]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bool -> NonSingleton (v n) -> [[v n]]
forall a. Fractional a => Bool -> NonSingleton a -> [[a]]
solveCubicSplineCoefficients Bool
closed (NonSingleton (v n) -> [[v n]])
-> (NonSingleton (Point v n) -> NonSingleton (v n))
-> NonSingleton (Point v n)
-> [[v n]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Point v n -> v n)
-> NonSingleton (Point v n) -> NonSingleton (v n)
forall a b. (a -> b) -> NonSingleton a -> NonSingleton b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Getting (v n) (Point v n) (v n) -> Point v n -> v n
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting (v n) (Point v n) (v n)
forall (f1 :: * -> *) a (g :: * -> *) b (f2 :: * -> *).
Functor f2 =>
(f1 a -> f2 (g b)) -> Point f1 a -> f2 (Point g b)
lensP) (NonSingleton (Point v n) -> t) -> NonSingleton (Point v n) -> t
forall a b. (a -> b) -> a -> b
$ (Point v n
p1 Point v n -> NonEmpty (Point v n) -> NonSingleton (Point v n)
forall a. a -> NonEmpty a -> NonSingleton a
:|| (Point v n
p2 Point v n -> [Point v n] -> NonEmpty (Point v n)
forall a. a -> [a] -> NonEmpty a
:| [Point v n]
ps))
where
f :: [a] -> [a]
f [a
a, a
b, a
c, a
d] = [a
a, (a
3 a -> a -> a
forall a. Num a => a -> a -> a
* a
a a -> a -> a
forall a. Num a => a -> a -> a
+ a
b) a -> a -> a
forall a. Fractional a => a -> a -> a
/ a
3, (a
3 a -> a -> a
forall a. Num a => a -> a -> a
* a
a a -> a -> a
forall a. Num a => a -> a -> a
+ a
2 a -> a -> a
forall a. Num a => a -> a -> a
* a
b a -> a -> a
forall a. Num a => a -> a -> a
+ a
c) a -> a -> a
forall a. Fractional a => a -> a -> a
/ a
3, a
a a -> a -> a
forall a. Num a => a -> a -> a
+ a
b a -> a -> a
forall a. Num a => a -> a -> a
+ a
c a -> a -> a
forall a. Num a => a -> a -> a
+ a
d]
flattenBeziers :: [[v n]] -> t
flattenBeziers bs :: [[v n]]
bs@((v n
b : [v n]
_) : [[v n]]
_) =
Located (Trail v n) -> t
Located (Trail (V t) (N t)) -> t
forall t. TrailLike t => Located (Trail (V t) (N t)) -> t
trailLike (Located (Trail v n) -> t)
-> (Located (Trail' Line v n) -> Located (Trail v n))
-> Located (Trail' Line v n)
-> t
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bool -> Located (Trail' Line v n) -> Located (Trail v n)
forall (v :: * -> *) n.
(Metric v, OrderedField n) =>
Bool -> Located (Trail' Line v n) -> Located (Trail v n)
closeIf Bool
closed (Located (Trail' Line v n) -> t) -> Located (Trail' Line v n) -> t
forall a b. (a -> b) -> a -> b
$ [Segment Closed v n] -> Trail' Line v n
forall (v :: * -> *) n.
(Metric v, OrderedField n) =>
[Segment Closed v n] -> Trail' Line v n
lineFromSegments (([v n] -> Segment Closed v n) -> [[v n]] -> [Segment Closed v n]
forall a b. (a -> b) -> [a] -> [b]
map [v n] -> Segment Closed v n
forall {v :: * -> *} {n}. Num (v n) => [v n] -> Segment Closed v n
bez [[v n]]
bs) Trail' Line v n
-> Point (V (Trail' Line v n)) (N (Trail' Line v n))
-> Located (Trail' Line v n)
forall a. a -> Point (V a) (N a) -> Located a
`at` v n -> Point v n
forall (f :: * -> *) a. f a -> Point f a
P v n
b
bez :: [v n] -> Segment Closed v n
bez [v n
a, v n
b, v n
c, v n
d] = v n -> v n -> v n -> Segment Closed v n
forall (v :: * -> *) n. v n -> v n -> v n -> Segment Closed v n
bezier3 (v n
b v n -> v n -> v n
forall a. Num a => a -> a -> a
- v n
a) (v n
c v n -> v n -> v n
forall a. Num a => a -> a -> a
- v n
a) (v n
d v n -> v n -> v n
forall a. Num a => a -> a -> a
- v n
a)
closeIf ::
(Metric v, OrderedField n) =>
Bool -> Located (Trail' Line v n) -> Located (Trail v n)
closeIf :: forall (v :: * -> *) n.
(Metric v, OrderedField n) =>
Bool -> Located (Trail' Line v n) -> Located (Trail v n)
closeIf Bool
c = (Trail' Line v n -> Trail v n)
-> Located (Trail' Line v n) -> Located (Trail v n)
forall a b. SameSpace a b => (a -> b) -> Located a -> Located b
mapLoc (if Bool
c then Trail' Loop v n -> Trail v n
forall (v :: * -> *) n. Trail' Loop v n -> Trail v n
wrapLoop (Trail' Loop v n -> Trail v n)
-> (Trail' Line v n -> Trail' Loop v n)
-> Trail' Line v n
-> Trail v n
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Trail' Line v n -> Trail' Loop v n
forall (v :: * -> *) n.
(Metric v, OrderedField n) =>
Trail' Line v n -> Trail' Loop v n
glueLine else Trail' Line v n -> Trail v n
forall (v :: * -> *) n. Trail' Line v n -> Trail v n
wrapLine)