module Waterfall.Revolution 
( revolution
) where

import Waterfall.Internal.Solid (Solid (..), solidFromAcquire)
import Waterfall.TwoD.Internal.Path2D (Path2D (..))
import Waterfall.Internal.Finalizers (toAcquire)
import qualified OpenCascade.BRepPrimAPI.MakeRevol as MakeRevol
import qualified OpenCascade.BRepBuilderAPI.MakeSolid as MakeSolid
import qualified OpenCascade.BRepBuilderAPI.MakeShape as MakeShape
import qualified OpenCascade.GP as GP
import OpenCascade.Inheritance (upcast, unsafeDowncast)
import Waterfall.Transforms (rotate)
import Control.Monad.IO.Class (liftIO)
import Linear (unit, _x)

-- | Construct a `Solid` of revolution from a `Path2D`.
--
-- The `Path2D` is rotated about the y axis, should have endpoints that lie on it ( \(x = 0\) ).
-- 
-- The resulting `Solid` is rotated such that the axis of revolution is the z axis.
revolution :: Path2D -> Solid
revolution :: Path2D -> Solid
revolution (Path2D Ptr Wire
theRawPath) = V3 Double -> Double -> Solid -> Solid
forall a. Transformable a => V3 Double -> Double -> a -> a
rotate (ASetter' (V3 Double) Double -> V3 Double
forall (t :: * -> *) a.
(Additive t, Num a) =>
ASetter' (t a) a -> t a
unit ASetter' (V3 Double) Double
forall a. Lens' (V3 a) a
forall (t :: * -> *) a. R1 t => Lens' (t a) a
_x) (Double
forall a. Floating a => a
piDouble -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
2) (Solid -> Solid)
-> (Acquire (Ptr Shape) -> Solid) -> Acquire (Ptr Shape) -> Solid
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Acquire (Ptr Shape) -> Solid
solidFromAcquire (Acquire (Ptr Shape) -> Solid) -> Acquire (Ptr Shape) -> Solid
forall a b. (a -> b) -> a -> b
$ do
    Ptr Wire
p <- Ptr Wire -> Acquire (Ptr Wire)
forall a. a -> Acquire a
toAcquire Ptr Wire
theRawPath
    Ptr Ax1
axis <- Acquire (Ptr Ax1)
GP.oy -- revolve around the y axis
    Ptr MakeRevol
revol <- Ptr Shape -> Ptr Ax1 -> Bool -> Acquire (Ptr MakeRevol)
MakeRevol.fromShapeAndAx1 (Ptr Wire -> Ptr Shape
forall a b. SubTypeOf a b => Ptr b -> Ptr a
upcast Ptr Wire
p) Ptr Ax1
axis Bool
True
    Ptr Shape
shell <- Ptr MakeShape -> Acquire (Ptr Shape)
MakeShape.shape (Ptr MakeRevol -> Ptr MakeShape
forall a b. SubTypeOf a b => Ptr b -> Ptr a
upcast Ptr MakeRevol
revol)
    Ptr MakeSolid
solidBuilder <- Acquire (Ptr MakeSolid)
MakeSolid.new
    IO () -> Acquire ()
forall a. IO a -> Acquire a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> Acquire ()) -> IO () -> Acquire ()
forall a b. (a -> b) -> a -> b
$ Ptr MakeSolid -> Ptr Shell -> IO ()
MakeSolid.add Ptr MakeSolid
solidBuilder (Ptr Shell -> IO ()) -> IO (Ptr Shell) -> IO ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Ptr Shape -> IO (Ptr Shell)
forall a b. DiscriminatedSubTypeOf a b => Ptr a -> IO (Ptr b)
unsafeDowncast Ptr Shape
shell
    Ptr MakeShape -> Acquire (Ptr Shape)
MakeShape.shape (Ptr MakeSolid -> Ptr MakeShape
forall a b. SubTypeOf a b => Ptr b -> Ptr a
upcast Ptr MakeSolid
solidBuilder)