module Waterfall.Fillet
( roundFillet
, roundConditionalFillet
, roundIndexedConditionalFillet
) where
import Waterfall.Internal.Solid (Solid (..), acquireSolid, solidFromAcquire)
import Waterfall.Internal.Edges (edgeEndpoints)
import qualified OpenCascade.BRepFilletAPI.MakeFillet as MakeFillet
import qualified OpenCascade.BRepBuilderAPI.MakeShape as MakeShape
import qualified OpenCascade.TopExp.Explorer as Explorer
import qualified OpenCascade.TopAbs.ShapeEnum as ShapeEnum
import qualified OpenCascade.TopoDS.Shape as TopoDS.Shape
import Foreign.Ptr (Ptr)
import Control.Monad (when)
import Control.Monad.IO.Class (liftIO)
import OpenCascade.Inheritance (upcast, unsafeDowncast)
import Linear.V3 (V3 (..))
addEdgesToMakeFillet :: (Integer -> (V3 Double, V3 Double) -> Maybe Double) -> Ptr MakeFillet.MakeFillet -> Ptr Explorer.Explorer -> IO ()
addEdgesToMakeFillet :: (Integer -> (V3 Double, V3 Double) -> Maybe Double)
-> Ptr MakeFillet -> Ptr Explorer -> IO ()
addEdgesToMakeFillet Integer -> (V3 Double, V3 Double) -> Maybe Double
radiusFn Ptr MakeFillet
builder Ptr Explorer
explorer = [Int] -> Integer -> IO ()
go [] Integer
0
where go :: [Int] -> Integer -> IO ()
go [Int]
visited Integer
i = do
isMore <- Ptr Explorer -> IO Bool
Explorer.more Ptr Explorer
explorer
when isMore $ do
v <- unsafeDowncast =<< Explorer.value explorer
hash <- TopoDS.Shape.hashCode (upcast v) (2^(31 :: Int))
if hash `elem` visited
then do
Explorer.next explorer
go visited i
else do
endpoints <- edgeEndpoints v
case radiusFn i endpoints of
Just Double
r | Double
r Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
> Double
0 -> Ptr MakeFillet -> Double -> Ptr Edge -> IO ()
MakeFillet.addEdgeWithRadius Ptr MakeFillet
builder Double
r Ptr Edge
v
Maybe Double
_ -> () -> IO ()
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
Explorer.next explorer
go (hash:visited) (i + 1)
roundIndexedConditionalFillet :: (Integer -> (V3 Double, V3 Double) -> Maybe Double) -> Solid -> Solid
roundIndexedConditionalFillet :: (Integer -> (V3 Double, V3 Double) -> Maybe Double)
-> Solid -> Solid
roundIndexedConditionalFillet Integer -> (V3 Double, V3 Double) -> Maybe Double
radiusFunction Solid
solid = Acquire (Ptr Shape) -> Solid
solidFromAcquire (Acquire (Ptr Shape) -> Solid) -> Acquire (Ptr Shape) -> Solid
forall a b. (a -> b) -> a -> b
$ do
s <- Solid -> Acquire (Ptr Shape)
acquireSolid Solid
solid
builder <- MakeFillet.fromShape s
explorer <- Explorer.new s ShapeEnum.Edge
liftIO $ addEdgesToMakeFillet radiusFunction builder explorer
MakeShape.shape (upcast builder)
roundConditionalFillet :: ((V3 Double, V3 Double) -> Maybe Double) -> Solid -> Solid
roundConditionalFillet :: ((V3 Double, V3 Double) -> Maybe Double) -> Solid -> Solid
roundConditionalFillet (V3 Double, V3 Double) -> Maybe Double
f = (Integer -> (V3 Double, V3 Double) -> Maybe Double)
-> Solid -> Solid
roundIndexedConditionalFillet (((V3 Double, V3 Double) -> Maybe Double)
-> Integer -> (V3 Double, V3 Double) -> Maybe Double
forall a b. a -> b -> a
const (V3 Double, V3 Double) -> Maybe Double
f)
roundFillet :: Double -> Solid -> Solid
roundFillet :: Double -> Solid -> Solid
roundFillet Double
r = ((V3 Double, V3 Double) -> Maybe Double) -> Solid -> Solid
roundConditionalFillet (Maybe Double -> (V3 Double, V3 Double) -> Maybe Double
forall a b. a -> b -> a
const (Maybe Double -> (V3 Double, V3 Double) -> Maybe Double)
-> (Double -> Maybe Double)
-> Double
-> (V3 Double, V3 Double)
-> Maybe Double
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Double -> Maybe Double
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Double -> (V3 Double, V3 Double) -> Maybe Double)
-> Double -> (V3 Double, V3 Double) -> Maybe Double
forall a b. (a -> b) -> a -> b
$ Double
r)