{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE FlexibleInstances #-}
module Waterfall.Path.Common
( AnyPath ()
, line
, lineTo
, lineRelative
, arcVia
, arcViaTo
, arcViaRelative
, bezier
, bezierTo
, bezierRelative
, pathFrom
, pathFromTo
) where
import Data.Acquire
import qualified OpenCascade.TopoDS as TopoDS
import qualified OpenCascade.GP as GP
import Foreign.Ptr
import Waterfall.Internal.Path (Path (..))
import Waterfall.TwoD.Internal.Path2D (Path2D (..))
import Waterfall.Internal.Finalizers (unsafeFromAcquire)
import Control.Arrow (second)
import Data.Foldable (foldl', traverse_)
import qualified OpenCascade.BRepBuilderAPI.MakeWire as MakeWire
import Control.Monad.IO.Class (liftIO)
import qualified OpenCascade.BRepBuilderAPI.MakeEdge as MakeEdge
import qualified OpenCascade.GC.MakeArcOfCircle as MakeArcOfCircle
import OpenCascade.Inheritance (upcast)
import qualified OpenCascade.NCollection.Array1 as NCollection.Array1
import qualified OpenCascade.Geom.BezierCurve as BezierCurve
import Data.Proxy (Proxy (..))
import Linear (V3 (..), V2 (..))
import qualified OpenCascade.GP.Pnt as GP.Pnt
class AnyPath point path | path -> point where
fromWire :: Acquire (Ptr TopoDS.Wire) -> path
pointToGPPnt :: Proxy path -> point -> Acquire (Ptr GP.Pnt)
edgesToPath :: (AnyPath point path) => Acquire [Ptr TopoDS.Edge] -> path
edgesToPath :: forall point path. AnyPath point path => Acquire [Ptr Edge] -> path
edgesToPath Acquire [Ptr Edge]
es = Acquire (Ptr Wire) -> path
forall point path. AnyPath point path => Acquire (Ptr Wire) -> path
fromWire (Acquire (Ptr Wire) -> path) -> Acquire (Ptr Wire) -> path
forall a b. (a -> b) -> a -> b
$ do
edges <- Acquire [Ptr Edge]
es
builder <- MakeWire.new
liftIO $ traverse_ (MakeWire.addEdge builder) edges
MakeWire.wire builder
line :: forall point path. (AnyPath point path) => point -> point -> path
line :: forall point path. AnyPath point path => point -> point -> path
line point
start point
end = Acquire [Ptr Edge] -> path
forall point path. AnyPath point path => Acquire [Ptr Edge] -> path
edgesToPath (Acquire [Ptr Edge] -> path) -> Acquire [Ptr Edge] -> path
forall a b. (a -> b) -> a -> b
$ do
pt1 <- Proxy path -> point -> Acquire (Ptr Pnt)
forall point path.
AnyPath point path =>
Proxy path -> point -> Acquire (Ptr Pnt)
pointToGPPnt (Proxy path
forall {k} (t :: k). Proxy t
Proxy :: Proxy path) point
start
pt2 <- pointToGPPnt (Proxy :: Proxy path) end
pure <$> MakeEdge.fromPnts pt1 pt2
lineTo :: (AnyPath point path) => point -> point -> (point, path)
lineTo :: forall point path.
AnyPath point path =>
point -> point -> (point, path)
lineTo point
end = \point
start -> (point
end, point -> point -> path
forall point path. AnyPath point path => point -> point -> path
line point
start point
end)
lineRelative :: (AnyPath point path, Num point) => point -> point -> (point, path)
lineRelative :: forall point path.
(AnyPath point path, Num point) =>
point -> point -> (point, path)
lineRelative point
dEnd = do
end <- (point -> point -> point
forall a. Num a => a -> a -> a
+ point
dEnd)
lineTo end
arcVia :: forall point path. (AnyPath point path) => point -> point -> point -> path
arcVia :: forall point path.
AnyPath point path =>
point -> point -> point -> path
arcVia point
start point
mid point
end = Acquire [Ptr Edge] -> path
forall point path. AnyPath point path => Acquire [Ptr Edge] -> path
edgesToPath (Acquire [Ptr Edge] -> path) -> Acquire [Ptr Edge] -> path
forall a b. (a -> b) -> a -> b
$ do
s <- Proxy path -> point -> Acquire (Ptr Pnt)
forall point path.
AnyPath point path =>
Proxy path -> point -> Acquire (Ptr Pnt)
pointToGPPnt (Proxy path
forall {k} (t :: k). Proxy t
Proxy :: Proxy path) point
start
m <- pointToGPPnt (Proxy :: Proxy path) mid
e <- pointToGPPnt (Proxy :: Proxy path) end
theArc <- MakeArcOfCircle.from3Pnts s m e
pure <$> MakeEdge.fromCurve (upcast theArc)
arcViaTo :: (AnyPath point path) => point -> point -> point -> (point, path)
arcViaTo :: forall point path.
AnyPath point path =>
point -> point -> point -> (point, path)
arcViaTo point
mid point
end = \point
start -> (point
end, point -> point -> point -> path
forall point path.
AnyPath point path =>
point -> point -> point -> path
arcVia point
start point
mid point
end)
arcViaRelative :: (AnyPath point path, Num point) => point -> point -> point -> (point, path)
arcViaRelative :: forall point path.
(AnyPath point path, Num point) =>
point -> point -> point -> (point, path)
arcViaRelative point
dMid point
dEnd = do
mid <- (point -> point -> point
forall a. Num a => a -> a -> a
+ point
dMid)
end <- (+ dEnd)
arcViaTo mid end
bezier :: forall point path. (AnyPath point path) => point -> point -> point -> point -> path
bezier :: forall point path.
AnyPath point path =>
point -> point -> point -> point -> path
bezier point
start point
controlPoint1 point
controlPoint2 point
end = Acquire [Ptr Edge] -> path
forall point path. AnyPath point path => Acquire [Ptr Edge] -> path
edgesToPath (Acquire [Ptr Edge] -> path) -> Acquire [Ptr Edge] -> path
forall a b. (a -> b) -> a -> b
$ do
s <- Proxy path -> point -> Acquire (Ptr Pnt)
forall point path.
AnyPath point path =>
Proxy path -> point -> Acquire (Ptr Pnt)
pointToGPPnt (Proxy path
forall {k} (t :: k). Proxy t
Proxy :: Proxy path) point
start
c1 <- pointToGPPnt (Proxy :: Proxy path) controlPoint1
c2 <- pointToGPPnt (Proxy :: Proxy path) controlPoint2
e <- pointToGPPnt (Proxy :: Proxy path) end
arr <- NCollection.Array1.newGPPntArray 1 4
liftIO $ do
NCollection.Array1.setValueGPPnt arr 1 s
NCollection.Array1.setValueGPPnt arr 2 c1
NCollection.Array1.setValueGPPnt arr 3 c2
NCollection.Array1.setValueGPPnt arr 4 e
b <- BezierCurve.toHandle =<< BezierCurve.fromPnts arr
pure <$> MakeEdge.fromCurve (upcast b)
bezierTo :: (AnyPath point path) => point -> point -> point -> point -> (point, path)
bezierTo :: forall point path.
AnyPath point path =>
point -> point -> point -> point -> (point, path)
bezierTo point
controlPoint1 point
controlPoint2 point
end = \point
start -> (point
end, point -> point -> point -> point -> path
forall point path.
AnyPath point path =>
point -> point -> point -> point -> path
bezier point
start point
controlPoint1 point
controlPoint2 point
end)
bezierRelative :: (AnyPath point path, Num point) => point -> point -> point -> point -> (point, path)
bezierRelative :: forall point path.
(AnyPath point path, Num point) =>
point -> point -> point -> point -> (point, path)
bezierRelative point
dControlPoint1 point
dControlPoint2 point
dEnd = do
controlPoint1 <- (point -> point -> point
forall a. Num a => a -> a -> a
+ point
dControlPoint1)
controlPoint2 <- (+ dControlPoint2)
end <- (+ dEnd)
bezierTo controlPoint1 controlPoint2 end
pathFrom :: (Monoid path) => point -> [point -> (point, path)] -> path
pathFrom :: forall path point.
Monoid path =>
point -> [point -> (point, path)] -> path
pathFrom point
start [point -> (point, path)]
commands = (point, path) -> path
forall a b. (a, b) -> b
snd ((point, path) -> path) -> (point, path) -> path
forall a b. (a -> b) -> a -> b
$ [point -> (point, path)] -> point -> (point, path)
forall path point.
Monoid path =>
[point -> (point, path)] -> point -> (point, path)
pathFromTo [point -> (point, path)]
commands point
start
pathFromTo :: (Monoid path) => [point -> (point, path)] -> point -> (point, path)
pathFromTo :: forall path point.
Monoid path =>
[point -> (point, path)] -> point -> (point, path)
pathFromTo [point -> (point, path)]
commands point
start =
let go :: (t, [b]) -> (t -> (d, b)) -> (d, [b])
go (t
pos, [b]
paths) t -> (d, b)
cmd = (b -> [b]) -> (d, b) -> (d, [b])
forall b c d. (b -> c) -> (d, b) -> (d, c)
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (d, b) (d, c)
second (b -> [b] -> [b]
forall a. a -> [a] -> [a]
:[b]
paths) (t -> (d, b)
cmd t
pos)
(point
end, [path]
allPaths) = ((point, [path]) -> (point -> (point, path)) -> (point, [path]))
-> (point, [path]) -> [point -> (point, path)] -> (point, [path])
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (point, [path]) -> (point -> (point, path)) -> (point, [path])
forall {t} {b} {d}. (t, [b]) -> (t -> (d, b)) -> (d, [b])
go (point
start, []) [point -> (point, path)]
commands
in (point
end, [path] -> path
forall a. Monoid a => [a] -> a
mconcat [path]
allPaths)
instance AnyPath (V3 Double) Path where
fromWire :: Acquire (Ptr TopoDS.Wire) -> Path
fromWire :: Acquire (Ptr Wire) -> Path
fromWire = Ptr Wire -> Path
Path (Ptr Wire -> Path)
-> (Acquire (Ptr Wire) -> Ptr Wire) -> Acquire (Ptr Wire) -> Path
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Acquire (Ptr Wire) -> Ptr Wire
forall a. Acquire a -> a
unsafeFromAcquire
pointToGPPnt :: Proxy Path -> V3 Double -> Acquire (Ptr GP.Pnt)
pointToGPPnt :: Proxy Path -> V3 Double -> Acquire (Ptr Pnt)
pointToGPPnt Proxy Path
_ (V3 Double
x Double
y Double
z) = Double -> Double -> Double -> Acquire (Ptr Pnt)
GP.Pnt.new Double
x Double
y Double
z
instance AnyPath (V2 Double) Path2D where
fromWire :: Acquire (Ptr TopoDS.Wire) -> Path2D
fromWire :: Acquire (Ptr Wire) -> Path2D
fromWire = Ptr Wire -> Path2D
Path2D (Ptr Wire -> Path2D)
-> (Acquire (Ptr Wire) -> Ptr Wire) -> Acquire (Ptr Wire) -> Path2D
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Acquire (Ptr Wire) -> Ptr Wire
forall a. Acquire a -> a
unsafeFromAcquire
pointToGPPnt :: Proxy Path2D -> V2 Double -> Acquire (Ptr GP.Pnt)
pointToGPPnt :: Proxy Path2D -> V2 Double -> Acquire (Ptr Pnt)
pointToGPPnt Proxy Path2D
_ (V2 Double
x Double
y) = Double -> Double -> Double -> Acquire (Ptr Pnt)
GP.Pnt.new Double
x Double
y Double
0