module Waterfall.IO ( writeSTL , writeSTEP ) where import Waterfall.Internal.Solid (Solid(..)) import qualified OpenCascade.BRepMesh.IncrementalMesh as BRepMesh.IncrementalMesh import qualified OpenCascade.StlAPI.Writer as StlWriter import qualified OpenCascade.STEPControl.Writer as StepWriter import qualified OpenCascade.STEPControl.StepModelType as StepModelType import Control.Monad.IO.Class (liftIO) import Control.Monad (void, unless) import System.IO (hPutStrLn, stderr) import Data.Acquire -- | Write a `Solid` to a (binary) STL file at a given path -- -- Because BRep representations of objects can store arbitrary precision curves, -- but STL files store triangulated surfaces, -- this function takes a "deflection" argument used to discretize curves. -- -- The deflection is the maximum allowable distance between a curve and the generated triangulation. writeSTL :: Double -> FilePath -> Solid -> IO () writeSTL linDeflection filepath (Solid run) = (`withAcquire` pure) $ do s <- run mesh <- BRepMesh.IncrementalMesh.fromShapeAndLinDeflection s linDeflection liftIO $ BRepMesh.IncrementalMesh.perform mesh writer <- StlWriter.new liftIO $ do StlWriter.setAsciiMode writer False res <- StlWriter.write writer s filepath unless res (hPutStrLn stderr ("failed to write " <> filepath)) return () -- | Write a `Solid` to a STEP file at a given path -- -- STEP files can be imported by [FreeCAD](https://www.freecad.org/) writeSTEP :: FilePath -> Solid -> IO () writeSTEP filepath (Solid run) = (`withAcquire` pure) $ do s <- run writer <- StepWriter.new _ <- liftIO $ StepWriter.transfer writer s StepModelType.Asls True void . liftIO $ StepWriter.write writer filepath