{-|
 This is directly implemented from [\"Gear Drawing with Bézier Curves\" by Dr A R Collins](https://www.arc.id.au/GearDrawing.html).

 Found Indirectly via Mathew Dockrey 
 ( [Attoparsec](https://www.attoparsec.com/) 
 ( [the YouTube channel](https://www.youtube.com/attoparsec), not the parser library ) )
 and his [Inkscape Plugin](https://github.com/attoparsec/inkscape-extensions)

 And David Douard and Jonas Bähr, and their [FreeCAD module](https://github.com/FreeCAD/FreeCAD/blob/0ac0882eeb4e3390aef464e1807a3631c5f2e858/src/Mod/PartDesign/fcgear/involute.py)
-}
module GearExample 
( gearExample
) where 

import qualified Waterfall.Solids as Solids
import qualified Waterfall.TwoD.Shape as Shape
import qualified Waterfall.TwoD.Path2D as Path2D
import Waterfall.TwoD.Transforms (rotate2D)
import Control.Lens ((^.))
import Linear (V2 (..), _y)
import Data.Maybe (catMaybes)


chebyExpnCoeffs :: Int -> (Double -> Double) -> Double
chebyExpnCoeffs :: Int -> (Double -> Double) -> Double
chebyExpnCoeffs Int
j Double -> Double
f = 
    let n :: Int
n = Int
50 :: Int
        jf :: Double
jf = Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
j
        nf :: Double
nf = Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
n 
        c :: Double
c = [Double] -> Double
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [let kf :: Double
kf = Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
k in Double -> Double
f (Double -> Double
forall a. Floating a => a -> a
cos (Double
forall a. Floating a => a
pi Double -> Double -> Double
forall a. Num a => a -> a -> a
* (Double
kf Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
0.5)Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
nf)) Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double -> Double
forall a. Floating a => a -> a
cos (Double
forall a. Floating a => a
pi Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
jf Double -> Double -> Double
forall a. Num a => a -> a -> a
* (Double
kf Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
0.5)Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
nf)| Int
k <- [Int
1..Int
n]]
     in Double
2 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
c Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
nf

cheby :: [[Double]] 
cheby :: [[Double]]
cheby = [ [ Double
1,  Double
0,  Double
0,  Double
0,  Double
0,  Double
0]
        , [ Double
0,  Double
1,  Double
0,  Double
0,  Double
0,  Double
0]
        , [-Double
1,  Double
0,  Double
2,  Double
0,  Double
0,  Double
0]
        , [ Double
0, -Double
3,  Double
0,  Double
4,  Double
0,  Double
0]
        , [ Double
1,  Double
0, -Double
8,  Double
0,  Double
8,  Double
0]
        , [ Double
0,  Double
5,  Double
0,-Double
20,  Double
0, Double
16]
        ]

-- limited to p' = 5, but in practice p' = 4
chebyApprox :: (Double -> Double) -> Int -> [Double]
chebyApprox :: (Double -> Double) -> Int -> [Double]
chebyApprox Double -> Double
f Int
p' = 
    let fnCoeffs :: [Double]
fnCoeffs = [Int -> (Double -> Double) -> Double
chebyExpnCoeffs Int
k Double -> Double
f | Int
k <- [Int
0..Int
p'] ]
        adjust :: a -> Double
adjust a
0 = [Double] -> Double
forall a. HasCallStack => [a] -> a
head [Double]
fnCoeffs Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
2
        adjust a
_ = Double
0
     in [ [Double] -> Double
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [[Double]
fnCoeffs[Double] -> Int -> Double
forall a. HasCallStack => [a] -> Int -> a
!!Int
k  Double -> Double -> Double
forall a. Num a => a -> a -> a
* ([[Double]]
cheby [[Double]] -> Int -> [Double]
forall a. HasCallStack => [a] -> Int -> a
!! Int
k [Double] -> Int -> Double
forall a. HasCallStack => [a] -> Int -> a
!! Int
pwr) | Int
k <- [Int
0..Int
p'] ] Double -> Double -> Double
forall a. Num a => a -> a -> a
- Int -> Double
forall {a}. (Eq a, Num a) => a -> Double
adjust Int
pwr | Int
pwr <- [Int
0..Int
p'] ]

binom :: Int -> Int -> Double 
binom :: Int -> Int -> Double
binom Int
n Int
k = Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral ([Int] -> Int
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
product [Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
k Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1 .. Int
n]) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral ([Int] -> Int
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
product [Int
1..Int
k])

involuteBezCoeffs :: Double -> Double -> Double -> Double -> (V2 Double, V2 Double, V2 Double, V2 Double)
involuteBezCoeffs :: Double
-> Double
-> Double
-> Double
-> (V2 Double, V2 Double, V2 Double, V2 Double)
involuteBezCoeffs Double
rA Double
rB Double
fStart Double
fStop = 
    let 
        p :: Int
p = Int
3
        ta :: Double
ta = Double -> Double
forall a. Floating a => a -> a
sqrt (Double
rA Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
rA Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
rB Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
rB)Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
rB -- involute angle at addendum
        ts :: Double
ts = Double
ta Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double -> Double
forall a. Floating a => a -> a
sqrt Double
fStart
        te :: Double
te = Double
ta Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double -> Double
forall a. Floating a => a -> a
sqrt Double
fStop

        involuteXbez :: Double -> Double
involuteXbez Double
t =
            let x :: Double
x = Double
tDouble -> Double -> Double
forall a. Num a => a -> a -> a
*Double
2 Double -> Double -> Double
forall a. Num a => a -> a -> a
-Double
1
                theta :: Double
theta = Double
x Double -> Double -> Double
forall a. Num a => a -> a -> a
* (Double
te Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
ts) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
2 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ (Double
ts Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
te)Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
2
            in Double
rB Double -> Double -> Double
forall a. Num a => a -> a -> a
* ( Double -> Double
forall a. Floating a => a -> a
cos Double
theta Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
theta Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double -> Double
forall a. Floating a => a -> a
sin Double
theta )
        involuteYbez :: Double -> Double
involuteYbez Double
t = 
            let x :: Double
x = Double
tDouble -> Double -> Double
forall a. Num a => a -> a -> a
*Double
2 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
1
                theta :: Double
theta = Double
x Double -> Double -> Double
forall a. Num a => a -> a -> a
* (Double
te Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
ts) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
2 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ (Double
ts Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
te)Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
2
            in Double
rB Double -> Double -> Double
forall a. Num a => a -> a -> a
* ( Double -> Double
forall a. Floating a => a -> a
sin Double
theta Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
theta Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double -> Double
forall a. Floating a => a -> a
cos Double
theta )

        bezCoeff :: Int -> (Double -> Double) -> Double
bezCoeff Int
i Double -> Double
f = 
            let polyCoeffs :: [Double]
polyCoeffs = (Double -> Double) -> Int -> [Double]
chebyApprox Double -> Double
f Int
p
            in [Double] -> Double
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [Int -> Int -> Double
binom Int
i Int
j Double -> Double -> Double
forall a. Num a => a -> a -> a
* ([Double]
polyCoeffs [Double] -> Int -> Double
forall a. HasCallStack => [a] -> Int -> a
!! Int
j) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Int -> Int -> Double
binom Int
p Int
j | Int
j<- [Int
0..Int
i]]

        v :: Int -> V2 Double
v Int
i = Double -> Double -> V2 Double
forall a. a -> a -> V2 a
V2 (Int -> (Double -> Double) -> Double
bezCoeff Int
i Double -> Double
involuteXbez) (Int -> (Double -> Double) -> Double
bezCoeff Int
i Double -> Double
involuteYbez)

    in (Int -> V2 Double
v Int
0, Int -> V2 Double
v Int
1, Int -> V2 Double
v Int
2, Int -> V2 Double
v Int
3)

genInvolutePolar :: Double -> Double -> Double
genInvolutePolar :: Double -> Double -> Double
genInvolutePolar Double
rb Double
r = let ra :: Double
ra = Double -> Double
forall a. Floating a => a -> a
sqrt (Double
r Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
r Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
rb Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
rb) in Double
raDouble -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
rb Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double -> Double
forall a. Floating a => a -> a
acos (Double
rb Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
r)

polarToCart :: Double -> Double -> V2 Double
polarToCart :: Double -> Double -> V2 Double
polarToCart Double
rad Double
angle = Double -> Double -> V2 Double
forall a. a -> a -> V2 a
V2 (Double
rad Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double -> Double
forall a. Floating a => a -> a
cos Double
angle) (Double
rad Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double -> Double
forall a. Floating a => a -> a
sin Double
angle)

genGearToothData :: Double -> Int -> Double -> Path2D.Path2D
genGearToothData :: Double -> Int -> Double -> Path2D
genGearToothData Double
m Int
z Double
phi = 
    let addendum :: Double
addendum = Double
m
        dedendum :: Double
dedendum = Double
1.25 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
m
        clearance :: Double
clearance = Double
dedendum Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
addendum
        rPitch :: Double
rPitch = Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
z  Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
m Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
2
        rb :: Double
rb = Double
rPitch Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double -> Double
forall a. Floating a => a -> a
cos Double
phi
        ra :: Double
ra = Double
rPitch Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
addendum
        rRoot :: Double
rRoot = Double
rPitch Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
dedendum
        fRad :: Double
fRad = Double
1.5 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
clearance 
        pitchAngle :: Double
pitchAngle = Double
2 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
forall a. Floating a => a
pi Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
z
        baseToPitchAngle :: Double
baseToPitchAngle = Double -> Double -> Double
genInvolutePolar Double
rb Double
rPitch
        rf' :: Double
rf' = Double -> Double
forall a. Floating a => a -> a
sqrt ((Double
rRoot Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
fRad) Double -> Double -> Double
forall a. Num a => a -> a -> a
* (Double
rRoot Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
fRad) Double -> Double -> Double
forall a. Num a => a -> a -> a
- (Double
fRad Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
fRad))
        rf :: Double
rf = if Double
rb Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
rf'
                then Double
rRoot Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
clearance  
                else Double
rf'
        pitchToFilletAngle :: Double
pitchToFilletAngle  = 
            if Double
rf Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
> Double
rb 
                then Double
baseToPitchAngle Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double -> Double -> Double
genInvolutePolar Double
rb Double
rf 
                else Double
baseToPitchAngle 
        filletAngle :: Double
filletAngle = Double -> Double
forall a. Floating a => a -> a
atan (Double
fRad Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ (Double
fRad Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
rRoot))
        fe :: Double
fe = Double
1
        fs :: Double
fs = if Double
rf Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
> Double
rb 
            then (Double
rf Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
rf Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
rb Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
rb) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ (Double
raDouble -> Double -> Double
forall a. Num a => a -> a -> a
*Double
ra Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
rbDouble -> Double -> Double
forall a. Num a => a -> a -> a
*Double
rb)
            else Double
0.01 -- fraction of length offset from base to avoid singularity
        fm :: Double
fm = Double
fs Double -> Double -> Double
forall a. Num a => a -> a -> a
+ (Double
fe Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
fs)Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
4
        (V2 Double
dbz1, V2 Double
dbz2, V2 Double
dbz3, V2 Double
dbz4) = Double
-> Double
-> Double
-> Double
-> (V2 Double, V2 Double, V2 Double, V2 Double)
involuteBezCoeffs Double
ra Double
rb Double
fs Double
fm 
        (V2 Double
_, V2 Double
abz2, V2 Double
abz3, V2 Double
abz4) = Double
-> Double
-> Double
-> Double
-> (V2 Double, V2 Double, V2 Double, V2 Double)
involuteBezCoeffs Double
ra Double
rb Double
fm Double
fe 
        rotateBez :: V2 Double -> V2 Double
rotateBez = Double -> V2 Double -> V2 Double
forall a. Transformable2D a => Double -> a -> a
rotate2D (-Double
baseToPitchAngleDouble -> Double -> Double
forall a. Num a => a -> a -> a
-Double
pitchAngleDouble -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
4)
        rotateBez' :: V2 Double -> V2 Double
rotateBez' = (V2 Double -> V2 Double -> V2 Double
forall a. Num a => a -> a -> a
* Double -> Double -> V2 Double
forall a. a -> a -> V2 a
V2 Double
1 (-Double
1))  (V2 Double -> V2 Double)
-> (V2 Double -> V2 Double) -> V2 Double -> V2 Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. V2 Double -> V2 Double
rotateBez
        fillet :: V2 Double
fillet = Double -> Double -> V2 Double
polarToCart Double
rf (-Double
pitchAngle Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
4 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
pitchToFilletAngle)
        arcMiddle :: V2 Double
arcMiddle = Double -> Double -> V2 Double
polarToCart Double
ra Double
0
        filletR :: V2 Double
filletR = (V2 Double -> V2 Double -> V2 Double
forall a. Num a => a -> a -> a
* Double -> Double -> V2 Double
forall a. a -> a -> V2 a
V2 Double
1 (-Double
1)) V2 Double
fillet
        rootR :: V2 Double
rootR = Double -> Double -> V2 Double
polarToCart Double
rRoot (Double
pitchAngleDouble -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
4 Double -> Double -> Double
forall a. Num a => a -> a -> a
+Double
pitchToFilletAngle Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
filletAngle)
        rootNext :: V2 Double
rootNext = Double -> Double -> V2 Double
polarToCart Double
rRoot (Double
3Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
pitchAngleDouble -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
4 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
pitchToFilletAngle Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
filletAngle)
        filletNext :: V2 Double
filletNext = Double -> V2 Double -> V2 Double
forall a. Transformable2D a => Double -> a -> a
rotate2D Double
pitchAngle V2 Double
fillet

    in V2 Double -> [V2 Double -> (V2 Double, Path2D)] -> Path2D
forall path point.
Monoid path =>
point -> [point -> (point, path)] -> path
Path2D.pathFrom V2 Double
fillet ([V2 Double -> (V2 Double, Path2D)] -> Path2D)
-> [V2 Double -> (V2 Double, Path2D)] -> Path2D
forall a b. (a -> b) -> a -> b
$ 
        [Maybe (V2 Double -> (V2 Double, Path2D))]
-> [V2 Double -> (V2 Double, Path2D)]
forall a. [Maybe a] -> [a]
catMaybes 
            [ if Double
rf Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
rb 
                then (V2 Double -> (V2 Double, Path2D))
-> Maybe (V2 Double -> (V2 Double, Path2D))
forall a. a -> Maybe a
Just ((V2 Double -> (V2 Double, Path2D))
 -> Maybe (V2 Double -> (V2 Double, Path2D)))
-> (V2 Double -> (V2 Double, Path2D))
-> Maybe (V2 Double -> (V2 Double, Path2D))
forall a b. (a -> b) -> a -> b
$ V2 Double -> V2 Double -> (V2 Double, Path2D)
forall point path.
AnyPath point path =>
point -> point -> (point, path)
Path2D.lineTo (V2 Double -> V2 Double
rotateBez V2 Double
dbz1)
                else Maybe (V2 Double -> (V2 Double, Path2D))
forall a. Maybe a
Nothing
            , (V2 Double -> (V2 Double, Path2D))
-> Maybe (V2 Double -> (V2 Double, Path2D))
forall a. a -> Maybe a
Just ((V2 Double -> (V2 Double, Path2D))
 -> Maybe (V2 Double -> (V2 Double, Path2D)))
-> (V2 Double -> (V2 Double, Path2D))
-> Maybe (V2 Double -> (V2 Double, Path2D))
forall a b. (a -> b) -> a -> b
$ V2 Double
-> V2 Double -> V2 Double -> V2 Double -> (V2 Double, Path2D)
forall point path.
AnyPath point path =>
point -> point -> point -> point -> (point, path)
Path2D.bezierTo (V2 Double -> V2 Double
rotateBez V2 Double
dbz2) (V2 Double -> V2 Double
rotateBez V2 Double
dbz3) (V2 Double -> V2 Double
rotateBez V2 Double
dbz4)
            , (V2 Double -> (V2 Double, Path2D))
-> Maybe (V2 Double -> (V2 Double, Path2D))
forall a. a -> Maybe a
Just ((V2 Double -> (V2 Double, Path2D))
 -> Maybe (V2 Double -> (V2 Double, Path2D)))
-> (V2 Double -> (V2 Double, Path2D))
-> Maybe (V2 Double -> (V2 Double, Path2D))
forall a b. (a -> b) -> a -> b
$ V2 Double
-> V2 Double -> V2 Double -> V2 Double -> (V2 Double, Path2D)
forall point path.
AnyPath point path =>
point -> point -> point -> point -> (point, path)
Path2D.bezierTo (V2 Double -> V2 Double
rotateBez V2 Double
abz2) (V2 Double -> V2 Double
rotateBez V2 Double
abz3) (V2 Double -> V2 Double
rotateBez V2 Double
abz4)
            , (V2 Double -> (V2 Double, Path2D))
-> Maybe (V2 Double -> (V2 Double, Path2D))
forall a. a -> Maybe a
Just ((V2 Double -> (V2 Double, Path2D))
 -> Maybe (V2 Double -> (V2 Double, Path2D)))
-> (V2 Double -> (V2 Double, Path2D))
-> Maybe (V2 Double -> (V2 Double, Path2D))
forall a b. (a -> b) -> a -> b
$ V2 Double -> V2 Double -> V2 Double -> (V2 Double, Path2D)
forall point path.
AnyPath point path =>
point -> point -> point -> (point, path)
Path2D.arcViaTo V2 Double
arcMiddle (V2 Double -> V2 Double
rotateBez' V2 Double
abz4)
            , (V2 Double -> (V2 Double, Path2D))
-> Maybe (V2 Double -> (V2 Double, Path2D))
forall a. a -> Maybe a
Just ((V2 Double -> (V2 Double, Path2D))
 -> Maybe (V2 Double -> (V2 Double, Path2D)))
-> (V2 Double -> (V2 Double, Path2D))
-> Maybe (V2 Double -> (V2 Double, Path2D))
forall a b. (a -> b) -> a -> b
$ V2 Double
-> V2 Double -> V2 Double -> V2 Double -> (V2 Double, Path2D)
forall point path.
AnyPath point path =>
point -> point -> point -> point -> (point, path)
Path2D.bezierTo (V2 Double -> V2 Double
rotateBez' V2 Double
abz3) (V2 Double -> V2 Double
rotateBez' V2 Double
abz2) (V2 Double -> V2 Double
rotateBez' V2 Double
dbz4)
            , (V2 Double -> (V2 Double, Path2D))
-> Maybe (V2 Double -> (V2 Double, Path2D))
forall a. a -> Maybe a
Just ((V2 Double -> (V2 Double, Path2D))
 -> Maybe (V2 Double -> (V2 Double, Path2D)))
-> (V2 Double -> (V2 Double, Path2D))
-> Maybe (V2 Double -> (V2 Double, Path2D))
forall a b. (a -> b) -> a -> b
$ V2 Double
-> V2 Double -> V2 Double -> V2 Double -> (V2 Double, Path2D)
forall point path.
AnyPath point path =>
point -> point -> point -> point -> (point, path)
Path2D.bezierTo (V2 Double -> V2 Double
rotateBez' V2 Double
dbz3) (V2 Double -> V2 Double
rotateBez' V2 Double
dbz2) (V2 Double -> V2 Double
rotateBez' V2 Double
dbz1)
            , if Double
rf Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
rb 
                then (V2 Double -> (V2 Double, Path2D))
-> Maybe (V2 Double -> (V2 Double, Path2D))
forall a. a -> Maybe a
Just ((V2 Double -> (V2 Double, Path2D))
 -> Maybe (V2 Double -> (V2 Double, Path2D)))
-> (V2 Double -> (V2 Double, Path2D))
-> Maybe (V2 Double -> (V2 Double, Path2D))
forall a b. (a -> b) -> a -> b
$ V2 Double -> V2 Double -> (V2 Double, Path2D)
forall point path.
AnyPath point path =>
point -> point -> (point, path)
Path2D.lineTo V2 Double
filletR
                else Maybe (V2 Double -> (V2 Double, Path2D))
forall a. Maybe a
Nothing
            , if V2 Double
rootNext V2 Double -> Getting Double (V2 Double) Double -> Double
forall s a. s -> Getting a s a -> a
^. Getting Double (V2 Double) Double
forall a. Lens' (V2 a) a
forall (t :: * -> *) a. R2 t => Lens' (t a) a
_y Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
> V2 Double
rootR V2 Double -> Getting Double (V2 Double) Double -> Double
forall s a. s -> Getting a s a -> a
^. Getting Double (V2 Double) Double
forall a. Lens' (V2 a) a
forall (t :: * -> *) a. R2 t => Lens' (t a) a
_y
                then (V2 Double -> (V2 Double, Path2D))
-> Maybe (V2 Double -> (V2 Double, Path2D))
forall a. a -> Maybe a
Just ((V2 Double -> (V2 Double, Path2D))
 -> Maybe (V2 Double -> (V2 Double, Path2D)))
-> (V2 Double -> (V2 Double, Path2D))
-> Maybe (V2 Double -> (V2 Double, Path2D))
forall a b. (a -> b) -> a -> b
$ [V2 Double -> (V2 Double, Path2D)]
-> V2 Double -> (V2 Double, Path2D)
forall path point.
Monoid path =>
[point -> (point, path)] -> point -> (point, path)
Path2D.pathFromTo 
                    [ Sense -> Double -> V2 Double -> V2 Double -> (V2 Double, Path2D)
Path2D.arcTo Sense
Path2D.Counterclockwise Double
fRad V2 Double
rootR
                    , Sense -> Double -> V2 Double -> V2 Double -> (V2 Double, Path2D)
Path2D.arcTo Sense
Path2D.Counterclockwise Double
rRoot V2 Double
rootNext -- these lines should be arcs
                    ]
                else Maybe (V2 Double -> (V2 Double, Path2D))
forall a. Maybe a
Nothing
            , (V2 Double -> (V2 Double, Path2D))
-> Maybe (V2 Double -> (V2 Double, Path2D))
forall a. a -> Maybe a
Just ((V2 Double -> (V2 Double, Path2D))
 -> Maybe (V2 Double -> (V2 Double, Path2D)))
-> (V2 Double -> (V2 Double, Path2D))
-> Maybe (V2 Double -> (V2 Double, Path2D))
forall a b. (a -> b) -> a -> b
$ Sense -> Double -> V2 Double -> V2 Double -> (V2 Double, Path2D)
Path2D.arcTo Sense
Path2D.Counterclockwise Double
fRad V2 Double
filletNext
        ]
-- Thickness, Module, Number Teeth, pressure Angle 
gearExample :: Double -> Double -> Int -> Double -> Solids.Solid
gearExample :: Double -> Double -> Int -> Double -> Solid
gearExample Double
thickness Double
moduleLength Int
nGears Double
pressureAngle =
    let segment :: Path2D
segment = Double -> Int -> Double -> Path2D
genGearToothData Double
moduleLength Int
nGears Double
pressureAngle
        path :: Path2D
path = Path2D -> Path2D
Path2D.repeatLooping Path2D
segment
        --path = mconcat [rotate2D (-fromIntegral n * pi * 2 / fromIntegral nGears) segment | n <- [0..nGears]]
    in Double -> Shape -> Solid
Solids.prism Double
thickness (Shape -> Solid) -> (Path2D -> Shape) -> Path2D -> Solid
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Path2D -> Shape
Shape.fromPath (Path2D -> Solid) -> Path2D -> Solid
forall a b. (a -> b) -> a -> b
$ Path2D
path