module Geometry.Bezier
    where
import Geometry.Data
import Geometry.Vector

{- | A synonym describing a quadratic Bezier curve as three 'Point2's: start,
control and end.
 -}
type BQuad = (Point2,Point2,Point2)

{- | Split a quadratic Bezier curve into two at a fractional point along the
curve.
If the fraction is not between 0 and 1, this will create backwards curves.
 -}
splitBezierquad :: BQuad -> Float -> (BQuad,BQuad)
splitBezierquad (a,b,c) z
    = ( ( a
        , (z *.* b) -.- ((z-1) *.* a)
        , (z**2 *.* c) +.+ ((z-1)**2 *.* a) -.- (2*z*(z-1) *.* b)
        )
      , ( (z**2 *.* c) +.+ ((z-1)**2 *.* a) -.- (2*z*(z-1) *.* b)
        , (z *.* c) -.- ((z-1) *.* b)
        , c
        )
      )

{- | Split a quadratic Bezier curve into a given number of straight lines, and
 return the list of points defining these lines.
 -}
bQuadToLine :: BQuad -> Int -> [Point2]
bQuadToLine (a,_,c) 0 = [a,c]
bQuadToLine x i = let (l,r) = splitBezierquad x 0.5
                  in  bQuadToLine l (i-1) ++ bQuadToLine r (i-1)

{- | Transform a quadratic Bezier curve into a function.
 -}
bQuadToF :: (Point2,Point2,Point2) -> Float -> Point2
bQuadToF (c,b,a) t = t     *.* (t *.* a +.+ (1-t) *.* b) +.+
                     (1-t) *.* (t *.* b +.+ (1-t) *.* c)
