module Geometry.Bezier
(
Bezier(..)
, bezierLength
, bezierParametric
, bezierArcParametric
, bezierSubdivideEquiparametric
, bezierSubdivideEquidistant
, bezierSubdivideCasteljau
, bezierSmoothen
)
where
import Control.DeepSeq
import Data.Vector (Vector, (!))
import qualified Data.Vector as V
import Geometry.Core
import Geometry.LookupTable.Lookup1
import Numerics.ConvergentRecursion
import Numerics.DifferentialEquation
import Numerics.Integrate
import Numerics.LinearEquationSystem
data Bezier = Bezier !Vec2 !Vec2 !Vec2 !Vec2 deriving (Bezier -> Bezier -> Bool
(Bezier -> Bezier -> Bool)
-> (Bezier -> Bezier -> Bool) -> Eq Bezier
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Bezier -> Bezier -> Bool
== :: Bezier -> Bezier -> Bool
$c/= :: Bezier -> Bezier -> Bool
/= :: Bezier -> Bezier -> Bool
Eq, Eq Bezier
Eq Bezier
-> (Bezier -> Bezier -> Ordering)
-> (Bezier -> Bezier -> Bool)
-> (Bezier -> Bezier -> Bool)
-> (Bezier -> Bezier -> Bool)
-> (Bezier -> Bezier -> Bool)
-> (Bezier -> Bezier -> Bezier)
-> (Bezier -> Bezier -> Bezier)
-> Ord Bezier
Bezier -> Bezier -> Bool
Bezier -> Bezier -> Ordering
Bezier -> Bezier -> Bezier
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: Bezier -> Bezier -> Ordering
compare :: Bezier -> Bezier -> Ordering
$c< :: Bezier -> Bezier -> Bool
< :: Bezier -> Bezier -> Bool
$c<= :: Bezier -> Bezier -> Bool
<= :: Bezier -> Bezier -> Bool
$c> :: Bezier -> Bezier -> Bool
> :: Bezier -> Bezier -> Bool
$c>= :: Bezier -> Bezier -> Bool
>= :: Bezier -> Bezier -> Bool
$cmax :: Bezier -> Bezier -> Bezier
max :: Bezier -> Bezier -> Bezier
$cmin :: Bezier -> Bezier -> Bezier
min :: Bezier -> Bezier -> Bezier
Ord, Int -> Bezier -> ShowS
[Bezier] -> ShowS
Bezier -> String
(Int -> Bezier -> ShowS)
-> (Bezier -> String) -> ([Bezier] -> ShowS) -> Show Bezier
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Bezier -> ShowS
showsPrec :: Int -> Bezier -> ShowS
$cshow :: Bezier -> String
show :: Bezier -> String
$cshowList :: [Bezier] -> ShowS
showList :: [Bezier] -> ShowS
Show)
instance NFData Bezier where rnf :: Bezier -> ()
rnf Bezier
_ = ()
instance Transform Bezier where
transform :: Transformation -> Bezier -> Bezier
transform Transformation
t (Bezier Vec2
a Vec2
b Vec2
c Vec2
d) = Vec2 -> Vec2 -> Vec2 -> Vec2 -> Bezier
Bezier
(Transformation -> Vec2 -> Vec2
forall geo. Transform geo => Transformation -> geo -> geo
transform Transformation
t Vec2
a)
(Transformation -> Vec2 -> Vec2
forall geo. Transform geo => Transformation -> geo -> geo
transform Transformation
t Vec2
b)
(Transformation -> Vec2 -> Vec2
forall geo. Transform geo => Transformation -> geo -> geo
transform Transformation
t Vec2
c)
(Transformation -> Vec2 -> Vec2
forall geo. Transform geo => Transformation -> geo -> geo
transform Transformation
t Vec2
d)
instance HasBoundingBox Bezier where
boundingBox :: Bezier -> BoundingBox
boundingBox bezier :: Bezier
bezier@(Bezier Vec2
start Vec2
_ Vec2
_ Vec2
end) = [Vec2] -> BoundingBox
forall a. HasBoundingBox a => a -> BoundingBox
boundingBox ([Vec2
start, Vec2
end] [Vec2] -> [Vec2] -> [Vec2]
forall a. [a] -> [a] -> [a]
++ [Bezier -> Double -> Vec2
bezierParametric Bezier
bezier Double
t | Double
t <- [Double]
extremalTs])
where
extremalTs :: [Double]
extremalTs = (Double -> Bool) -> [Double] -> [Double]
forall a. (a -> Bool) -> [a] -> [a]
filter (\Double
t -> Double
t Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
>=Double
0 Bool -> Bool -> Bool
&& Double
t Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
<= Double
1) (Bezier -> [Double]
extremalT Bezier
bezier)
extremalT :: Bezier -> [Double]
extremalT (Bezier Vec2
a Vec2
b Vec2
c Vec2
d) = Double -> Double -> Double -> [Double]
forall {a}. (Floating a, Ord a) => a -> a -> a -> [a]
solveQuadratic (Vec2 -> Double
x Vec2
a') (Vec2 -> Double
x Vec2
b') (Vec2 -> Double
x Vec2
c') [Double] -> [Double] -> [Double]
forall a. [a] -> [a] -> [a]
++ Double -> Double -> Double -> [Double]
forall {a}. (Floating a, Ord a) => a -> a -> a -> [a]
solveQuadratic (Vec2 -> Double
y Vec2
a') (Vec2 -> Double
y Vec2
b') (Vec2 -> Double
y Vec2
c')
where
a' :: Vec2
a' = ((-Double
3) Double -> Vec2 -> Vec2
forall v. VectorSpace v => Double -> v -> v
*.Vec2
a) Vec2 -> Vec2 -> Vec2
forall v. VectorSpace v => v -> v -> v
+. (Double
9Double -> Vec2 -> Vec2
forall v. VectorSpace v => Double -> v -> v
*.Vec2
b) Vec2 -> Vec2 -> Vec2
forall v. VectorSpace v => v -> v -> v
-. Double
9Double -> Vec2 -> Vec2
forall v. VectorSpace v => Double -> v -> v
*.Vec2
c Vec2 -> Vec2 -> Vec2
forall v. VectorSpace v => v -> v -> v
+. Double
3Double -> Vec2 -> Vec2
forall v. VectorSpace v => Double -> v -> v
*.Vec2
d
b' :: Vec2
b' = Double
6Double -> Vec2 -> Vec2
forall v. VectorSpace v => Double -> v -> v
*.Vec2
a Vec2 -> Vec2 -> Vec2
forall v. VectorSpace v => v -> v -> v
-. Double
12Double -> Vec2 -> Vec2
forall v. VectorSpace v => Double -> v -> v
*.Vec2
b Vec2 -> Vec2 -> Vec2
forall v. VectorSpace v => v -> v -> v
+. Double
6Double -> Vec2 -> Vec2
forall v. VectorSpace v => Double -> v -> v
*.Vec2
c
c' :: Vec2
c' = (-Double
3)Double -> Vec2 -> Vec2
forall v. VectorSpace v => Double -> v -> v
*.Vec2
a Vec2 -> Vec2 -> Vec2
forall v. VectorSpace v => v -> v -> v
+. Double
3Double -> Vec2 -> Vec2
forall v. VectorSpace v => Double -> v -> v
*.Vec2
b
x :: Vec2 -> Double
x (Vec2 Double
x' Double
_) = Double
x'
y :: Vec2 -> Double
y (Vec2 Double
_ Double
y') = Double
y'
solveQuadratic :: a -> a -> a -> [a]
solveQuadratic a
a a
b a
c = case a -> a -> Ordering
forall a. Ord a => a -> a -> Ordering
compare a
discriminant a
0 of
Ordering
LT -> []
Ordering
EQ -> [-a
ba -> a -> a
forall a. Fractional a => a -> a -> a
/(a
2a -> a -> a
forall a. Num a => a -> a -> a
*a
a)]
Ordering
GT -> [ (-a
b a -> a -> a
forall a. Num a => a -> a -> a
+ a -> a
forall a. Floating a => a -> a
sqrt a
discriminant) a -> a -> a
forall a. Fractional a => a -> a -> a
/ (a
2a -> a -> a
forall a. Num a => a -> a -> a
*a
a), (-a
b a -> a -> a
forall a. Num a => a -> a -> a
- a -> a
forall a. Floating a => a -> a
sqrt a
discriminant) a -> a -> a
forall a. Fractional a => a -> a -> a
/ (a
2a -> a -> a
forall a. Num a => a -> a -> a
*a
a)]
where
discriminant :: a
discriminant = a
ba -> Integer -> a
forall a b. (Num a, Integral b) => a -> b -> a
^Integer
2 a -> a -> a
forall a. Num a => a -> a -> a
- a
4 a -> a -> a
forall a. Num a => a -> a -> a
* a
a a -> a -> a
forall a. Num a => a -> a -> a
* a
c
bezierParametric
:: Bezier
-> Double
-> Vec2
bezierParametric :: Bezier -> Double -> Vec2
bezierParametric (Bezier Vec2
a Vec2
b Vec2
c Vec2
d) Double
t
= (Double
1Double -> Double -> Double
forall a. Num a => a -> a -> a
-Double
t)Double -> Integer -> Double
forall a b. (Num a, Integral b) => a -> b -> a
^Integer
3 Double -> Vec2 -> Vec2
forall v. VectorSpace v => Double -> v -> v
*. Vec2
a
Vec2 -> Vec2 -> Vec2
forall v. VectorSpace v => v -> v -> v
+. Double
3Double -> Double -> Double
forall a. Num a => a -> a -> a
*(Double
1Double -> Double -> Double
forall a. Num a => a -> a -> a
-Double
t)Double -> Integer -> Double
forall a b. (Num a, Integral b) => a -> b -> a
^Integer
2Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
t Double -> Vec2 -> Vec2
forall v. VectorSpace v => Double -> v -> v
*. Vec2
b
Vec2 -> Vec2 -> Vec2
forall v. VectorSpace v => v -> v -> v
+. Double
3Double -> Double -> Double
forall a. Num a => a -> a -> a
*(Double
1Double -> Double -> Double
forall a. Num a => a -> a -> a
-Double
t) Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
tDouble -> Integer -> Double
forall a b. (Num a, Integral b) => a -> b -> a
^Integer
2 Double -> Vec2 -> Vec2
forall v. VectorSpace v => Double -> v -> v
*. Vec2
c
Vec2 -> Vec2 -> Vec2
forall v. VectorSpace v => v -> v -> v
+. Double
tDouble -> Integer -> Double
forall a b. (Num a, Integral b) => a -> b -> a
^Integer
3 Double -> Vec2 -> Vec2
forall v. VectorSpace v => Double -> v -> v
*. Vec2
d
bezierParametric'
:: Bezier
-> Double
-> Vec2
bezierParametric' :: Bezier -> Double -> Vec2
bezierParametric' (Bezier Vec2
a Vec2
b Vec2
c Vec2
d) Double
t
= (-Double
3Double -> Double -> Double
forall a. Num a => a -> a -> a
*(Double
1Double -> Double -> Double
forall a. Num a => a -> a -> a
-Double
t)Double -> Integer -> Double
forall a b. (Num a, Integral b) => a -> b -> a
^Integer
2) Double -> Vec2 -> Vec2
forall v. VectorSpace v => Double -> v -> v
*. Vec2
a
Vec2 -> Vec2 -> Vec2
forall v. VectorSpace v => v -> v -> v
+. (Double
3Double -> Double -> Double
forall a. Num a => a -> a -> a
+Double
tDouble -> Double -> Double
forall a. Num a => a -> a -> a
*(-Double
12Double -> Double -> Double
forall a. Num a => a -> a -> a
+Double
9Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
t)) Double -> Vec2 -> Vec2
forall v. VectorSpace v => Double -> v -> v
*. Vec2
b
Vec2 -> Vec2 -> Vec2
forall v. VectorSpace v => v -> v -> v
+. ((Double
6Double -> Double -> Double
forall a. Num a => a -> a -> a
-Double
9Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
t)Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
t) Double -> Vec2 -> Vec2
forall v. VectorSpace v => Double -> v -> v
*. Vec2
c
Vec2 -> Vec2 -> Vec2
forall v. VectorSpace v => v -> v -> v
+. (Double
3Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
tDouble -> Integer -> Double
forall a b. (Num a, Integral b) => a -> b -> a
^Integer
2) Double -> Vec2 -> Vec2
forall v. VectorSpace v => Double -> v -> v
*. Vec2
d
_bezierParametric''
:: Bezier
-> Double
-> Vec2
_bezierParametric'' :: Bezier -> Double -> Vec2
_bezierParametric'' (Bezier Vec2
a Vec2
b Vec2
c Vec2
d) Double
t
= (Double
6Double -> Double -> Double
forall a. Num a => a -> a -> a
-Double
6Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
t) Double -> Vec2 -> Vec2
forall v. VectorSpace v => Double -> v -> v
*. Vec2
a
Vec2 -> Vec2 -> Vec2
forall v. VectorSpace v => v -> v -> v
+. (-Double
12Double -> Double -> Double
forall a. Num a => a -> a -> a
+Double
18Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
t) Double -> Vec2 -> Vec2
forall v. VectorSpace v => Double -> v -> v
*. Vec2
b
Vec2 -> Vec2 -> Vec2
forall v. VectorSpace v => v -> v -> v
+. (Double
6Double -> Double -> Double
forall a. Num a => a -> a -> a
-Double
18Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
t) Double -> Vec2 -> Vec2
forall v. VectorSpace v => Double -> v -> v
*. Vec2
c
Vec2 -> Vec2 -> Vec2
forall v. VectorSpace v => v -> v -> v
+. (Double
6Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
t) Double -> Vec2 -> Vec2
forall v. VectorSpace v => Double -> v -> v
*. Vec2
d
bezierLength
:: Bezier
-> Double
bezierLength :: Bezier -> Double
bezierLength Bezier
bezier = (Int -> Double) -> Double -> Double
retryExponentiallyUntilPrecision ((Double -> Double) -> Double -> Double -> Int -> Double
forall a. Fractional a => (a -> a) -> a -> a -> Int -> a
integrateSimpson13 Double -> Double
f Double
0 Double
1) Double
1e-6
where
f :: Double -> Double
f Double
t = Vec2 -> Double
norm (Bezier -> Double -> Vec2
bezierParametric' Bezier
bezier Double
t)
bezierSubdivideEquiparametric
:: Int
-> Bezier
-> [Vec2]
bezierSubdivideEquiparametric :: Int -> Bezier -> [Vec2]
bezierSubdivideEquiparametric Int
n Bezier
bz = (Double -> Vec2) -> [Double] -> [Vec2]
forall a b. (a -> b) -> [a] -> [b]
map (Bezier -> Double -> Vec2
bezierParametric Bezier
bz) [Double]
points
where
points :: [Double]
points = (Int -> Double) -> [Int] -> [Double]
forall a b. (a -> b) -> [a] -> [b]
map (\Int
x -> Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
x Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1)) [Int
0..Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1]
bezierSubdivideEquidistant
:: Int
-> Bezier
-> [Vec2]
bezierSubdivideEquidistant :: Int -> Bezier -> [Vec2]
bezierSubdivideEquidistant Int
n Bezier
bz = (Double -> Vec2) -> [Double] -> [Vec2]
forall a b. (a -> b) -> [a] -> [b]
map Double -> Vec2
bezier [Double]
distances
where
bezier :: Double -> Vec2
bezier = Bezier -> Double -> Double -> Vec2
bezierArcParametric_ode Bezier
bz (Double
len Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
2Double -> Integer -> Double
forall a b. (Num a, Integral b) => a -> b -> a
^Integer
10)
len :: Double
len = Bezier -> Double
bezierLength Bezier
bz
distances :: [Double]
distances :: [Double]
distances = [Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
i Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
lenDouble -> Double -> Double
forall a. Fractional a => a -> a -> a
/Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1) | Int
i <- [Int
0..Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1]]
bezierArcParametric
:: Bezier
-> Double
-> Double
-> Vec2
bezierArcParametric :: Bezier -> Double -> Double -> Vec2
bezierArcParametric = Bezier -> Double -> Double -> Vec2
bezierArcParametric_ode
bezierArcParametric_ode
:: Bezier
-> Double
-> Double
-> Vec2
bezierArcParametric_ode :: Bezier -> Double -> Double -> Vec2
bezierArcParametric_ode Bezier
bz Double
ds
= let lut :: LookupTable1 Double Double
lut = Bezier -> Double -> LookupTable1 Double Double
s_to_t_lut_ode Bezier
bz Double
ds
in \Double
s -> let t :: Double
t = LookupTable1 Double Double -> Double -> Double
lookupInterpolated LookupTable1 Double Double
lut Double
s
in Bezier -> Double -> Vec2
bezierParametric Bezier
bz Double
t
s_to_t_lut_ode
:: Bezier
-> Double
-> LookupTable1 Double Double
s_to_t_lut_ode :: Bezier -> Double -> LookupTable1 Double Double
s_to_t_lut_ode Bezier
bz Double
ds = Vector (Double, Double) -> LookupTable1 Double Double
forall a b. Vector (a, b) -> LookupTable1 a b
LookupTable1 ([(Double, Double)] -> Vector (Double, Double)
forall {a}. [(a, Double)] -> Vector (a, Double)
sol_to_vec [(Double, Double)]
sol)
where
sol_to_vec :: [(a, Double)] -> Vector (a, Double)
sol_to_vec = [(a, Double)] -> Vector (a, Double)
forall a. [a] -> Vector a
V.fromList ([(a, Double)] -> Vector (a, Double))
-> ([(a, Double)] -> [(a, Double)])
-> [(a, Double)]
-> Vector (a, Double)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((a, Double) -> Bool) -> [(a, Double)] -> [(a, Double)]
forall a. (a -> Bool) -> [a] -> [a]
takeWhile (\(a
_s, Double
t) -> Double
t Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
<= Double
1)
sol :: [(Double, Double)]
sol = (Double -> Double -> Double)
-> Double -> Double -> Double -> [(Double, Double)]
forall vec.
VectorSpace vec =>
(Double -> vec -> vec)
-> vec -> Double -> Double -> [(Double, vec)]
rungeKuttaConstantStep Double -> Double -> Double
forall {p}. p -> Double -> Double
dt_ds Double
t0 Double
s0 Double
ds
dt_ds :: p -> Double -> Double
dt_ds p
_s Double
t = Double
1 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Vec2 -> Double
norm (Bezier -> Double -> Vec2
bezierParametric' Bezier
bz Double
t)
t0 :: Double
t0 = Double
0
s0 :: Double
s0 = Double
0
bezierSubdivideCasteljau :: Double -> Bezier -> [Vec2]
bezierSubdivideCasteljau :: Double -> Bezier -> [Vec2]
bezierSubdivideCasteljau Double
tolerance curve :: Bezier
curve@(Bezier Vec2
pFirst Vec2
_ Vec2
_ Vec2
_) = Vec2
pFirst Vec2 -> [Vec2] -> [Vec2]
forall a. a -> [a] -> [a]
: Bezier -> [Vec2]
go Bezier
curve
where
go :: Bezier -> [Vec2]
go (Bezier Vec2
p1 p2 :: Vec2
p2@(Vec2 Double
x2 Double
y2) p3 :: Vec2
p3@(Vec2 Double
x3 Double
y3) p4 :: Vec2
p4@(Vec2 Double
x4 Double
y4)) =
let
p12 :: Vec2
p12 = (Vec2
p1 Vec2 -> Vec2 -> Vec2
forall v. VectorSpace v => v -> v -> v
+. Vec2
p2 ) Vec2 -> Double -> Vec2
forall v. VectorSpace v => v -> Double -> v
/. Double
2
p23 :: Vec2
p23 = (Vec2
p2 Vec2 -> Vec2 -> Vec2
forall v. VectorSpace v => v -> v -> v
+. Vec2
p3 ) Vec2 -> Double -> Vec2
forall v. VectorSpace v => v -> Double -> v
/. Double
2
p34 :: Vec2
p34 = (Vec2
p3 Vec2 -> Vec2 -> Vec2
forall v. VectorSpace v => v -> v -> v
+. Vec2
p4 ) Vec2 -> Double -> Vec2
forall v. VectorSpace v => v -> Double -> v
/. Double
2
p123 :: Vec2
p123 = (Vec2
p12 Vec2 -> Vec2 -> Vec2
forall v. VectorSpace v => v -> v -> v
+. Vec2
p23 ) Vec2 -> Double -> Vec2
forall v. VectorSpace v => v -> Double -> v
/. Double
2
p234 :: Vec2
p234 = (Vec2
p23 Vec2 -> Vec2 -> Vec2
forall v. VectorSpace v => v -> v -> v
+. Vec2
p34 ) Vec2 -> Double -> Vec2
forall v. VectorSpace v => v -> Double -> v
/. Double
2
p1234 :: Vec2
p1234 = (Vec2
p123 Vec2 -> Vec2 -> Vec2
forall v. VectorSpace v => v -> v -> v
+. Vec2
p234) Vec2 -> Double -> Vec2
forall v. VectorSpace v => v -> Double -> v
/. Double
2
dp :: Vec2
dp@(Vec2 Double
dx Double
dy) = Vec2
p4 Vec2 -> Vec2 -> Vec2
forall v. VectorSpace v => v -> v -> v
-. Vec2
p1
d2 :: Double
d2 = Double -> Double
forall a. Num a => a -> a
abs ((Double
x2Double -> Double -> Double
forall a. Num a => a -> a -> a
-Double
x4)Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
dy Double -> Double -> Double
forall a. Num a => a -> a -> a
- (Double
y2Double -> Double -> Double
forall a. Num a => a -> a -> a
-Double
y4)Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
dx)
d3 :: Double
d3 = Double -> Double
forall a. Num a => a -> a
abs ((Double
x3Double -> Double -> Double
forall a. Num a => a -> a -> a
-Double
x4)Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
dy Double -> Double -> Double
forall a. Num a => a -> a -> a
- (Double
y3Double -> Double -> Double
forall a. Num a => a -> a -> a
-Double
y4)Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
dx)
curveIsFlat :: Bool
curveIsFlat = (Double
d2 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
d3)Double -> Double -> Double
forall a. Num a => a -> a -> a
*(Double
d2 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
d3) Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
toleranceDouble -> Integer -> Double
forall a b. (Num a, Integral b) => a -> b -> a
^Integer
2 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Vec2 -> Double
normSquare Vec2
dp
in if Bool
curveIsFlat
then
[Vec2
p4]
else Bezier -> [Vec2]
go (Vec2 -> Vec2 -> Vec2 -> Vec2 -> Bezier
Bezier Vec2
p1 Vec2
p12 Vec2
p123 Vec2
p1234)
[Vec2] -> [Vec2] -> [Vec2]
forall a. [a] -> [a] -> [a]
++
Bezier -> [Vec2]
go (Vec2 -> Vec2 -> Vec2 -> Vec2 -> Bezier
Bezier Vec2
p1234 Vec2
p234 Vec2
p34 Vec2
p4)
bezierSmoothen :: Sequential vector => vector Vec2 -> Vector Bezier
bezierSmoothen :: forall (vector :: * -> *).
Sequential vector =>
vector Vec2 -> Vector Bezier
bezierSmoothen vector Vec2
vecSequence
| Vector Vec2 -> Vec2
forall a. Vector a -> a
V.head Vector Vec2
vec Vec2 -> Vec2 -> Bool
forall a. Eq a => a -> a -> Bool
== Vector Vec2 -> Vec2
forall a. Vector a -> a
V.last Vector Vec2
vec = Vector Vec2 -> Vector Bezier
forall (vector :: * -> *).
Sequential vector =>
vector Vec2 -> Vector Bezier
bezierSmoothenLoop (Vector Vec2 -> Vector Vec2
forall a. Vector a -> Vector a
V.tail Vector Vec2
vec)
| Bool
otherwise = Vector Vec2 -> Vector Bezier
forall (vector :: * -> *).
Sequential vector =>
vector Vec2 -> Vector Bezier
bezierSmoothenOpen Vector Vec2
vec
where vec :: Vector Vec2
vec = vector Vec2 -> Vector Vec2
forall a. vector a -> Vector a
forall (f :: * -> *) a. Sequential f => f a -> Vector a
toVector vector Vec2
vecSequence
bezierSmoothenOpen :: Sequential vector => vector Vec2 -> Vector Bezier
bezierSmoothenOpen :: forall (vector :: * -> *).
Sequential vector =>
vector Vec2 -> Vector Bezier
bezierSmoothenOpen vector Vec2
pointsSequence = (Vec2 -> Vec2 -> Vec2 -> Vec2 -> Bezier)
-> Vector Vec2
-> Vector Vec2
-> Vector Vec2
-> Vector Vec2
-> Vector Bezier
forall a b c d e.
(a -> b -> c -> d -> e)
-> Vector a -> Vector b -> Vector c -> Vector d -> Vector e
V.zipWith4 Vec2 -> Vec2 -> Vec2 -> Vec2 -> Bezier
Bezier Vector Vec2
points Vector Vec2
controlPointsStart Vector Vec2
controlPointsEnd (Vector Vec2 -> Vector Vec2
forall a. Vector a -> Vector a
V.tail Vector Vec2
points)
where
points :: Vector Vec2
points = vector Vec2 -> Vector Vec2
forall a. vector a -> Vector a
forall (f :: * -> *) a. Sequential f => f a -> Vector a
toVector vector Vec2
pointsSequence
n :: Int
n = Vector Vec2 -> Int
forall a. Vector a -> Int
V.length Vector Vec2
points Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1
controlPointsStart :: Vector Vec2
controlPointsStart =
let low :: Vector Double
low = Int -> Vector Double
lowerDiagonal (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1)
diag :: Vector Double
diag = Int -> Vector Double
diagonal Int
n
upper :: Vector Double
upper = Int -> Vector Double
upperDiagonal (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1)
rhs :: Vector Vec2
rhs = Int -> Vector Vec2 -> Vector Vec2
forall vec. VectorSpace vec => Int -> Vector vec -> Vector vec
target Int
n Vector Vec2
points
in Vector Double
-> Vector Double -> Vector Double -> Vector Vec2 -> Vector Vec2
forall vec.
VectorSpace vec =>
Vector Double
-> Vector Double -> Vector Double -> Vector vec -> Vector vec
solveTridiagonal Vector Double
low Vector Double
diag Vector Double
upper Vector Vec2
rhs
controlPointsEnd :: Vector Vec2
controlPointsEnd = Int -> (Int -> Vec2) -> Vector Vec2
forall a. Int -> (Int -> a) -> Vector a
V.generate (Vector Vec2 -> Int
forall a. Vector a -> Int
V.length Vector Vec2
controlPointsStart) ((Int -> Vec2) -> Vector Vec2) -> (Int -> Vec2) -> Vector Vec2
forall a b. (a -> b) -> a -> b
$ \Int
i -> case () of
()
_ | Int
i Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1 -> (Vector Vec2
points Vector Vec2 -> Int -> Vec2
forall a. Vector a -> Int -> a
! Int
n Vec2 -> Vec2 -> Vec2
forall v. VectorSpace v => v -> v -> v
+. Vector Vec2
controlPointsStart Vector Vec2 -> Int -> Vec2
forall a. Vector a -> Int -> a
! (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1)) Vec2 -> Double -> Vec2
forall v. VectorSpace v => v -> Double -> v
/. Double
2
| Bool
otherwise -> Double
2 Double -> Vec2 -> Vec2
forall v. VectorSpace v => Double -> v -> v
*. (Vector Vec2
points Vector Vec2 -> Int -> Vec2
forall a. Vector a -> Int -> a
! (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1)) Vec2 -> Vec2 -> Vec2
forall v. VectorSpace v => v -> v -> v
-. Vector Vec2
controlPointsStart Vector Vec2 -> Int -> Vec2
forall a. Vector a -> Int -> a
! (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1)
upperDiagonal :: Int -> Vector Double
upperDiagonal :: Int -> Vector Double
upperDiagonal Int
len = Int -> Double -> Vector Double
forall a. Int -> a -> Vector a
V.replicate Int
len Double
1
lowerDiagonal :: Int -> Vector Double
lowerDiagonal :: Int -> Vector Double
lowerDiagonal Int
len = Int -> (Int -> Double) -> Vector Double
forall a. Int -> (Int -> a) -> Vector a
V.generate Int
len ((Int -> Double) -> Vector Double)
-> (Int -> Double) -> Vector Double
forall a b. (a -> b) -> a -> b
$ \Int
i -> case () of
()
_ | Int
i Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
lenInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1 -> Double
2
| Bool
otherwise -> Double
1
diagonal :: Int -> Vector Double
diagonal :: Int -> Vector Double
diagonal Int
len = Int -> (Int -> Double) -> Vector Double
forall a. Int -> (Int -> a) -> Vector a
V.generate Int
len ((Int -> Double) -> Vector Double)
-> (Int -> Double) -> Vector Double
forall a b. (a -> b) -> a -> b
$ \Int
i -> case () of
()
_ | Int
i Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 -> Double
2
| Int
i Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
lenInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1 -> Double
7
| Bool
otherwise -> Double
4
target :: VectorSpace vec => Int -> Vector vec -> Vector vec
target :: forall vec. VectorSpace vec => Int -> Vector vec -> Vector vec
target Int
n Vector vec
vertices = Int -> (Int -> vec) -> Vector vec
forall a. Int -> (Int -> a) -> Vector a
V.generate Int
n ((Int -> vec) -> Vector vec) -> (Int -> vec) -> Vector vec
forall a b. (a -> b) -> a -> b
$ \Int
i -> case () of
()
_ | Int
i Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 -> Vector vec
vertices Vector vec -> Int -> vec
forall a. Vector a -> Int -> a
! Int
0 vec -> vec -> vec
forall v. VectorSpace v => v -> v -> v
+. Double
2 Double -> vec -> vec
forall v. VectorSpace v => Double -> v -> v
*. Vector vec
vertices Vector vec -> Int -> vec
forall a. Vector a -> Int -> a
! Int
1
| Int
i Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1 -> Double
8 Double -> vec -> vec
forall v. VectorSpace v => Double -> v -> v
*. Vector vec
vertices Vector vec -> Int -> vec
forall a. Vector a -> Int -> a
! (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1) vec -> vec -> vec
forall v. VectorSpace v => v -> v -> v
+. Vector vec
vertices Vector vec -> Int -> vec
forall a. Vector a -> Int -> a
! Int
n
| Bool
otherwise -> Double
4 Double -> vec -> vec
forall v. VectorSpace v => Double -> v -> v
*. Vector vec
vertices Vector vec -> Int -> vec
forall a. Vector a -> Int -> a
! Int
i vec -> vec -> vec
forall v. VectorSpace v => v -> v -> v
+. Double
2 Double -> vec -> vec
forall v. VectorSpace v => Double -> v -> v
*. Vector vec
vertices Vector vec -> Int -> vec
forall a. Vector a -> Int -> a
! (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1)
bezierSmoothenLoop
:: Sequential vector
=> vector Vec2
-> Vector Bezier
bezierSmoothenLoop :: forall (vector :: * -> *).
Sequential vector =>
vector Vec2 -> Vector Bezier
bezierSmoothenLoop vector Vec2
pointsSequence
| Vector Vec2 -> Int
forall a. Vector a -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length Vector Vec2
points Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
2 = Vector Bezier
forall a. Vector a
V.empty
| Bool
otherwise =
let pointsWrapped :: Vector Vec2
pointsWrapped = Int -> Vector Vec2 -> Vector Vec2
forall {a}. Int -> Vector a -> Vector a
takeLast Int
3 Vector Vec2
points Vector Vec2 -> Vector Vec2 -> Vector Vec2
forall a. Semigroup a => a -> a -> a
<> Vector Vec2
points Vector Vec2 -> Vector Vec2 -> Vector Vec2
forall a. Semigroup a => a -> a -> a
<> Int -> Vector Vec2 -> Vector Vec2
forall {a}. Int -> Vector a -> Vector a
V.take Int
3 Vector Vec2
points
in Int -> Int -> Vector Bezier -> Vector Bezier
forall a. Int -> Int -> Vector a -> Vector a
V.slice Int
3 (Vector Vec2 -> Int
forall a. Vector a -> Int
V.length Vector Vec2
points) (Vector Vec2 -> Vector Bezier
forall (vector :: * -> *).
Sequential vector =>
vector Vec2 -> Vector Bezier
bezierSmoothenOpen Vector Vec2
pointsWrapped)
where
points :: Vector Vec2
points = vector Vec2 -> Vector Vec2
forall a. vector a -> Vector a
forall (f :: * -> *) a. Sequential f => f a -> Vector a
toVector vector Vec2
pointsSequence
takeLast :: Int -> Vector a -> Vector a
takeLast Int
n Vector a
vec = Int -> Vector a -> Vector a
forall {a}. Int -> Vector a -> Vector a
V.drop (Vector a -> Int
forall a. Vector a -> Int
V.length Vector a
vec Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
n) Vector a
vec