{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE FlexibleInstances #-}
{-|
Paths in 2D / 3D space.

This module defines functions that can be used with "Waterfall.Path" or "Waterfall.TwoD.Path2D".
Those modules both export monomorphized variants of the functions defined in this module
-}
module Waterfall.Path.Common 
( AnyPath ()
, line
, lineTo
, lineRelative
, arcVia
, arcViaTo
, arcViaRelative
, bezier
, bezierTo
, bezierRelative
, pathFrom
, pathFromTo
, pathEndpoints
, splice
, closeLoop
, reversePath
, splitPath
) where
import Data.Acquire
import qualified OpenCascade.TopoDS as TopoDS
import qualified OpenCascade.GP as GP
import Foreign.Ptr
import Waterfall.Internal.Path.Common (RawPath (..))
import Waterfall.Internal.Path (Path (..))
import Waterfall.TwoD.Internal.Path2D (Path2D (..))
import Waterfall.Internal.Finalizers (unsafeFromAcquire, toAcquire, unsafeFromAcquireT)
import Waterfall.Internal.FromOpenCascade (gpPntToV3)
import Waterfall.Internal.Edges (wireEndpoints, reverseWire, splitWires)
import Control.Arrow (second)
import Data.Foldable (foldl')
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, unsafeDowncast)
import qualified OpenCascade.NCollection.Array1 as NCollection.Array1
import qualified OpenCascade.Geom.BezierCurve as BezierCurve
import qualified OpenCascade.GP.Trsf as GP.Trsf
import qualified OpenCascade.GP.Vec as  GP.Vec
import qualified OpenCascade.BRepBuilderAPI.Transform as BRepBuilderAPI.Transform
import Data.Proxy (Proxy (..))
import Linear (V3 (..), V2 (..), _xy, Epsilon, nearZero)
import qualified OpenCascade.GP.Pnt as GP.Pnt
import Control.Lens ((^.))

-- | Class used to abstract over constructing `Path` and `Path2D` 
-- 
-- There are instances for @AnyPath (V3 Double) Path@
-- and for @AnyPath (V2 Double) Path2D@
class AnyPath point path | path -> point where
    reconstructPath :: RawPath -> path
    deconstructPath :: path -> RawPath
    pointToV3 :: Proxy path -> point -> V3 Double
    v3ToPoint :: Proxy path -> V3 Double -> point 

pointToGPPnt :: AnyPath point path => Proxy path -> point -> Acquire (Ptr GP.Pnt)
pointToGPPnt :: forall point path.
AnyPath point path =>
Proxy path -> point -> Acquire (Ptr Pnt)
pointToGPPnt Proxy path
proxy point
pnt = 
    let (V3 Double
x Double
y Double
z) = Proxy path -> point -> V3 Double
forall point path.
AnyPath point path =>
Proxy path -> point -> V3 Double
pointToV3 Proxy path
proxy point
pnt
    in Double -> Double -> Double -> Acquire (Ptr Pnt)
GP.Pnt.new Double
x Double
y Double
z 

fromWire :: AnyPath point path => Acquire (Ptr TopoDS.Wire) -> path
fromWire :: forall point path. AnyPath point path => Acquire (Ptr Wire) -> path
fromWire = RawPath -> path
forall point path. AnyPath point path => RawPath -> path
reconstructPath (RawPath -> path)
-> (Acquire (Ptr Wire) -> RawPath) -> Acquire (Ptr Wire) -> path
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Ptr Wire -> RawPath
ComplexRawPath (Ptr Wire -> RawPath)
-> (Acquire (Ptr Wire) -> Ptr Wire)
-> Acquire (Ptr Wire)
-> RawPath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Acquire (Ptr Wire) -> Ptr Wire
forall a. Acquire a -> a
unsafeFromAcquire

edgeToPath :: (AnyPath point path) => Acquire (Ptr TopoDS.Edge) -> path
edgeToPath :: forall point path. AnyPath point path => Acquire (Ptr Edge) -> path
edgeToPath 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
    Ptr Edge
edge <- Acquire (Ptr Edge)
es
    Ptr MakeWire
builder <- Acquire (Ptr MakeWire)
MakeWire.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 MakeWire -> Ptr Edge -> IO ()
MakeWire.addEdge Ptr MakeWire
builder Ptr Edge
edge
    Ptr MakeWire -> Acquire (Ptr Wire)
MakeWire.wire Ptr MakeWire
builder

-- | A straight line between two points
line :: forall point path. (AnyPath point path, Epsilon point) => point -> point -> path
line :: forall point path.
(AnyPath point path, Epsilon point) =>
point -> point -> path
line point
start point
end = 
    if point -> Bool
forall a. Epsilon a => a -> Bool
nearZero (point
start point -> point -> point
forall a. Num a => a -> a -> a
- point
end)
        then RawPath -> path
forall point path. AnyPath point path => RawPath -> path
reconstructPath (RawPath -> path) -> (point -> RawPath) -> point -> path
forall b c a. (b -> c) -> (a -> b) -> a -> c
. V3 Double -> RawPath
SinglePointRawPath (V3 Double -> RawPath) -> (point -> V3 Double) -> point -> RawPath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Proxy path -> point -> V3 Double
forall point path.
AnyPath point path =>
Proxy path -> point -> V3 Double
pointToV3 (Proxy path
forall {k} (t :: k). Proxy t
Proxy :: Proxy path) (point -> path) -> point -> path
forall a b. (a -> b) -> a -> b
$ point
start
        else Acquire (Ptr Edge) -> path
forall point path. AnyPath point path => Acquire (Ptr Edge) -> path
edgeToPath (Acquire (Ptr Edge) -> path) -> Acquire (Ptr Edge) -> path
forall a b. (a -> b) -> a -> b
$ do
            Ptr Pnt
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
            Ptr Pnt
pt2 <- 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
end
            Ptr Pnt -> Ptr Pnt -> Acquire (Ptr Edge)
MakeEdge.fromPnts Ptr Pnt
pt1 Ptr Pnt
pt2

-- | Version of `line` designed to work with `pathFrom`
lineTo :: (AnyPath point path, Epsilon point) => point -> point -> (point, path)
lineTo :: forall point path.
(AnyPath point path, Epsilon point) =>
point -> point -> (point, path)
lineTo point
end = \point
start -> (point
end, point -> point -> path
forall point path.
(AnyPath point path, Epsilon point) =>
point -> point -> path
line point
start point
end) 

-- | Version of `line` designed to work with `pathFrom`
-- 
-- With relative points; specifying the distance of the endpoint
-- relative to the start of the line, rather than in absolute space.
lineRelative :: (AnyPath point path, Epsilon point) => point -> point -> (point, path)
lineRelative :: forall point path.
(AnyPath point path, Epsilon point) =>
point -> point -> (point, path)
lineRelative point
dEnd = do
    point
end <- (point -> point -> point
forall a. Num a => a -> a -> a
+ point
dEnd)
    point -> point -> (point, path)
forall point path.
(AnyPath point path, Epsilon point) =>
point -> point -> (point, path)
lineTo point
end

-- | Section of a circle based on three arguments, the start point, a point on the arc, and the endpoint
arcVia :: forall point path. (AnyPath point path, Epsilon point) => point -> point -> point -> path
arcVia :: forall point path.
(AnyPath point path, Epsilon point) =>
point -> point -> point -> path
arcVia point
start point
mid point
end =
    if point -> Bool
forall a. Epsilon a => a -> Bool
nearZero (point
start point -> point -> point
forall a. Num a => a -> a -> a
- point
end) Bool -> Bool -> Bool
&& point -> Bool
forall a. Epsilon a => a -> Bool
nearZero (point
start point -> point -> point
forall a. Num a => a -> a -> a
- point
mid) 
        then RawPath -> path
forall point path. AnyPath point path => RawPath -> path
reconstructPath (RawPath -> path) -> (point -> RawPath) -> point -> path
forall b c a. (b -> c) -> (a -> b) -> a -> c
. V3 Double -> RawPath
SinglePointRawPath (V3 Double -> RawPath) -> (point -> V3 Double) -> point -> RawPath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Proxy path -> point -> V3 Double
forall point path.
AnyPath point path =>
Proxy path -> point -> V3 Double
pointToV3 (Proxy path
forall {k} (t :: k). Proxy t
Proxy :: Proxy path) (point -> path) -> point -> path
forall a b. (a -> b) -> a -> b
$ point
start
        else Acquire (Ptr Edge) -> path
forall point path. AnyPath point path => Acquire (Ptr Edge) -> path
edgeToPath (Acquire (Ptr Edge) -> path) -> Acquire (Ptr Edge) -> path
forall a b. (a -> b) -> a -> b
$ do
            Ptr Pnt
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
            Ptr Pnt
m <- 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
mid
            Ptr Pnt
e <- 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
end
            Ptr (Handle TrimmedCurve)
theArc <- Ptr Pnt
-> Ptr Pnt -> Ptr Pnt -> Acquire (Ptr (Handle TrimmedCurve))
MakeArcOfCircle.from3Pnts Ptr Pnt
s Ptr Pnt
m Ptr Pnt
e
            Ptr (Handle Curve) -> Acquire (Ptr Edge)
MakeEdge.fromCurve (Ptr (Handle TrimmedCurve) -> Ptr (Handle Curve)
forall a b. SubTypeOf a b => Ptr b -> Ptr a
upcast Ptr (Handle TrimmedCurve)
theArc)

-- | Version of `arcVia` designed to work with `pathFrom`
--
-- The first argument is a point on the arc
-- The second argument is the endpoint of the arc
arcViaTo :: (AnyPath point path, Epsilon point) => point -> point -> point -> (point, path)
arcViaTo :: forall point path.
(AnyPath point path, Epsilon point) =>
point -> point -> point -> (point, path)
arcViaTo point
mid point
end = \point
start -> (point
end, point -> point -> point -> path
forall point path.
(AnyPath point path, Epsilon point) =>
point -> point -> point -> path
arcVia point
start point
mid point
end) 

-- | Version of `arcVia` designed to work with `pathFrom`
-- 
-- With relative points; specifying the distance of the midpoint and endpoint
-- relative to the start of the line, rather than in absolute space.
arcViaRelative :: (AnyPath point path, Epsilon point) => point -> point -> point -> (point, path)
arcViaRelative :: forall point path.
(AnyPath point path, Epsilon point) =>
point -> point -> point -> (point, path)
arcViaRelative point
dMid point
dEnd = do
    point
mid <- (point -> point -> point
forall a. Num a => a -> a -> a
+ point
dMid) 
    point
end <- (point -> point -> point
forall a. Num a => a -> a -> a
+ point
dEnd) 
    point -> point -> point -> (point, path)
forall point path.
(AnyPath point path, Epsilon point) =>
point -> point -> point -> (point, path)
arcViaTo point
mid point
end

-- | Bezier curve of order 3
-- 
-- The arguments are, the start of the curve, the two control points, and the end of the curve
bezier :: forall point path. (AnyPath point path, Epsilon point) => point -> point -> point -> point -> path
bezier :: forall point path.
(AnyPath point path, Epsilon point) =>
point -> point -> point -> point -> path
bezier point
start point
controlPoint1 point
controlPoint2 point
end = 
    if point -> Bool
forall a. Epsilon a => a -> Bool
nearZero (point
start point -> point -> point
forall a. Num a => a -> a -> a
- point
end) Bool -> Bool -> Bool
&& point -> Bool
forall a. Epsilon a => a -> Bool
nearZero (point
start point -> point -> point
forall a. Num a => a -> a -> a
- point
controlPoint1) Bool -> Bool -> Bool
&& point -> Bool
forall a. Epsilon a => a -> Bool
nearZero (point
start point -> point -> point
forall a. Num a => a -> a -> a
- point
controlPoint2)
        then RawPath -> path
forall point path. AnyPath point path => RawPath -> path
reconstructPath (RawPath -> path) -> (point -> RawPath) -> point -> path
forall b c a. (b -> c) -> (a -> b) -> a -> c
. V3 Double -> RawPath
SinglePointRawPath (V3 Double -> RawPath) -> (point -> V3 Double) -> point -> RawPath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Proxy path -> point -> V3 Double
forall point path.
AnyPath point path =>
Proxy path -> point -> V3 Double
pointToV3 (Proxy path
forall {k} (t :: k). Proxy t
Proxy :: Proxy path) (point -> path) -> point -> path
forall a b. (a -> b) -> a -> b
$ point
start
        else Acquire (Ptr Edge) -> path
forall point path. AnyPath point path => Acquire (Ptr Edge) -> path
edgeToPath (Acquire (Ptr Edge) -> path) -> Acquire (Ptr Edge) -> path
forall a b. (a -> b) -> a -> b
$ do
            Ptr Pnt
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
            Ptr Pnt
c1 <- 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
controlPoint1
            Ptr Pnt
c2 <- 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
controlPoint2
            Ptr Pnt
e <- 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
end
            Ptr (Array1 Pnt)
arr <- Int -> Int -> Acquire (Ptr (Array1 Pnt))
NCollection.Array1.newGPPntArray Int
1 Int
4
            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
$ do 
                Ptr (Array1 Pnt) -> Int -> Ptr Pnt -> IO ()
NCollection.Array1.setValueGPPnt Ptr (Array1 Pnt)
arr Int
1 Ptr Pnt
s
                Ptr (Array1 Pnt) -> Int -> Ptr Pnt -> IO ()
NCollection.Array1.setValueGPPnt Ptr (Array1 Pnt)
arr Int
2 Ptr Pnt
c1
                Ptr (Array1 Pnt) -> Int -> Ptr Pnt -> IO ()
NCollection.Array1.setValueGPPnt Ptr (Array1 Pnt)
arr Int
3 Ptr Pnt
c2
                Ptr (Array1 Pnt) -> Int -> Ptr Pnt -> IO ()
NCollection.Array1.setValueGPPnt Ptr (Array1 Pnt)
arr Int
4 Ptr Pnt
e
            Ptr (Handle BezierCurve)
b <- Ptr BezierCurve -> Acquire (Ptr (Handle BezierCurve))
BezierCurve.toHandle (Ptr BezierCurve -> Acquire (Ptr (Handle BezierCurve)))
-> Acquire (Ptr BezierCurve) -> Acquire (Ptr (Handle BezierCurve))
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Ptr (Array1 Pnt) -> Acquire (Ptr BezierCurve)
BezierCurve.fromPnts Ptr (Array1 Pnt)
arr
            Ptr (Handle Curve) -> Acquire (Ptr Edge)
MakeEdge.fromCurve (Ptr (Handle BezierCurve) -> Ptr (Handle Curve)
forall a b. SubTypeOf a b => Ptr b -> Ptr a
upcast Ptr (Handle BezierCurve)
b)

-- | Version of `bezier` designed to work with `pathFrom`
bezierTo :: (AnyPath point path, Epsilon point) => point -> point -> point -> point -> (point, path)
bezierTo :: forall point path.
(AnyPath point path, Epsilon point) =>
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, Epsilon point) =>
point -> point -> point -> point -> path
bezier point
start point
controlPoint1 point
controlPoint2 point
end) 

-- | Version of `bezier` designed to work with `pathFrom`
-- 
-- With relative points; specifying the distance of the control points and the endpoint
-- relative to the start of the line, rather than in absolute space.
bezierRelative :: (AnyPath point path, Epsilon point) => point -> point -> point -> point -> (point, path)
bezierRelative :: forall point path.
(AnyPath point path, Epsilon point) =>
point -> point -> point -> point -> (point, path)
bezierRelative point
dControlPoint1 point
dControlPoint2 point
dEnd = do
    point
controlPoint1 <- (point -> point -> point
forall a. Num a => a -> a -> a
+ point
dControlPoint1)
    point
controlPoint2 <- (point -> point -> point
forall a. Num a => a -> a -> a
+ point
dControlPoint2)
    point
end <- (point -> point -> point
forall a. Num a => a -> a -> a
+ point
dEnd)
    point -> point -> point -> point -> (point, path)
forall point path.
(AnyPath point path, Epsilon point) =>
point -> point -> point -> point -> (point, path)
bezierTo point
controlPoint1 point
controlPoint2 point
end

-- | When combining paths, we're generally interested in pairs of paths that share a common endpoint.
--
-- Rather than having to repeat these common endpoints, `pathFrom` can be used to combine a list of path components.
-- 
-- Where a path component is a function from a start point, to a tuple of an end point, and a path; @V2 Double -> (V2 Double, Path2D)@. 
-- 
-- A typical use of `pathFrom` uses a list of functions with the suffix \"To\" or \"Relative\", e.g:
--
-- @
-- Path.pathFrom zero 
--    [ Path.bezierRelative (V3 0 0 0.5) (V3 0.5 0.5 0.5) (V3 0.5 0.5 1)
--    , Path.bezierRelative (V3 0 0 0.5) (V3 (-0.5) (-0.5) 0.5) (V3 (-0.5) (-0.5) 1)
--    , Path.arcViaRelative (V3 0 1 1) (V3 0 2 0)
--    , Path.lineTo (V3 0 2 0) 
--    ] @
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 
     
-- | Combines a list of "path components", as used by `pathFrom`
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] -> path) -> ([path] -> [path]) -> [path] -> path
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [path] -> [path]
forall a. [a] -> [a]
reverse ([path] -> path) -> [path] -> path
forall a b. (a -> b) -> a -> b
$ [path]
allPaths)

-- | Returns the start and end of a `Path`
pathEndpoints :: forall point path. (AnyPath point path) => path -> Maybe (point, point)
pathEndpoints :: forall point path.
AnyPath point path =>
path -> Maybe (point, point)
pathEndpoints path
path = 
    case path -> RawPath
forall point path. AnyPath point path => path -> RawPath
deconstructPath path
path of 
        ComplexRawPath Ptr Wire
p -> 
            Acquire (Maybe (point, point)) -> Maybe (point, point)
forall a. Acquire a -> a
unsafeFromAcquire (Acquire (Maybe (point, point)) -> Maybe (point, point))
-> Acquire (Maybe (point, point)) -> Maybe (point, point)
forall a b. (a -> b) -> a -> b
$ do
                Ptr Wire
wire <- Ptr Wire -> Acquire (Ptr Wire)
forall a. a -> Acquire a
toAcquire Ptr Wire
p
                (V3 Double
s, V3 Double
e) <- IO (V3 Double, V3 Double) -> Acquire (V3 Double, V3 Double)
forall a. IO a -> Acquire a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (V3 Double, V3 Double) -> Acquire (V3 Double, V3 Double))
-> IO (V3 Double, V3 Double) -> Acquire (V3 Double, V3 Double)
forall a b. (a -> b) -> a -> b
$ Ptr Wire -> IO (V3 Double, V3 Double)
wireEndpoints Ptr Wire
wire
                Maybe (point, point) -> Acquire (Maybe (point, point))
forall a. a -> Acquire a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe (point, point) -> Acquire (Maybe (point, point)))
-> ((point, point) -> Maybe (point, point))
-> (point, point)
-> Acquire (Maybe (point, point))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (point, point) -> Maybe (point, point)
forall a. a -> Maybe a
Just ((point, point) -> Acquire (Maybe (point, point)))
-> (point, point) -> Acquire (Maybe (point, point))
forall a b. (a -> b) -> a -> b
$ (Proxy path -> V3 Double -> point
forall point path.
AnyPath point path =>
Proxy path -> V3 Double -> point
v3ToPoint (Proxy path
forall {k} (t :: k). Proxy t
Proxy :: Proxy path) V3 Double
s, Proxy path -> V3 Double -> point
forall point path.
AnyPath point path =>
Proxy path -> V3 Double -> point
v3ToPoint (Proxy path
forall {k} (t :: k). Proxy t
Proxy :: Proxy path) V3 Double
e)
        SinglePointRawPath V3 Double
p -> let x :: point
x = Proxy path -> V3 Double -> point
forall point path.
AnyPath point path =>
Proxy path -> V3 Double -> point
v3ToPoint (Proxy path
forall {k} (t :: k). Proxy t
Proxy :: Proxy path) V3 Double
p in (point, point) -> Maybe (point, point)
forall a. a -> Maybe a
Just (point
x, point
x)
        RawPath
EmptyRawPath -> Maybe (point, point)
forall a. Maybe a
Nothing
            

-- | Convert a path into a function that can be used as an argument to `pathFrom`
--
-- Takes a path, and returns a function which takes a new start point for the path, and returns 
-- tupled, the path translated onto the new start point, and the new endpoint 
splice :: forall point path. (AnyPath point path, Num point) => path -> point -> (point, path)
splice :: forall point path.
(AnyPath point path, Num point) =>
path -> point -> (point, path)
splice path
path point
pnt =
    case path -> RawPath
forall point path. AnyPath point path => path -> RawPath
deconstructPath path
path of
        ComplexRawPath Ptr Wire
unacquiredWire ->  
            let res :: (point, Ptr Wire)
res = Acquire (point, Ptr Wire) -> (point, Ptr Wire)
forall a. Acquire a -> a
unsafeFromAcquire (Acquire (point, Ptr Wire) -> (point, Ptr Wire))
-> Acquire (point, Ptr Wire) -> (point, Ptr Wire)
forall a b. (a -> b) -> a -> b
$ do
                    Ptr Wire
wire <- Ptr Wire -> Acquire (Ptr Wire)
forall a. a -> Acquire a
toAcquire Ptr Wire
unacquiredWire
                    (V3 Double
s, V3 Double
e) <- IO (V3 Double, V3 Double) -> Acquire (V3 Double, V3 Double)
forall a. IO a -> Acquire a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (V3 Double, V3 Double) -> Acquire (V3 Double, V3 Double))
-> IO (V3 Double, V3 Double) -> Acquire (V3 Double, V3 Double)
forall a b. (a -> b) -> a -> b
$ Ptr Wire -> IO (V3 Double, V3 Double)
wireEndpoints Ptr Wire
wire
                    let s' :: point
s' = Proxy path -> V3 Double -> point
forall point path.
AnyPath point path =>
Proxy path -> V3 Double -> point
v3ToPoint (Proxy path
forall {k} (t :: k). Proxy t
Proxy :: Proxy path) V3 Double
s
                        e' :: point
e' = Proxy path -> V3 Double -> point
forall point path.
AnyPath point path =>
Proxy path -> V3 Double -> point
v3ToPoint (Proxy path
forall {k} (t :: k). Proxy t
Proxy :: Proxy path) V3 Double
e
                    Ptr Pnt
gp <- 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
pnt
                    V3 Double
p <- IO (V3 Double) -> Acquire (V3 Double)
forall a. IO a -> Acquire a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (V3 Double) -> Acquire (V3 Double))
-> IO (V3 Double) -> Acquire (V3 Double)
forall a b. (a -> b) -> a -> b
$ Ptr Pnt -> IO (V3 Double)
gpPntToV3 Ptr Pnt
gp
                    let (V3 Double
x Double
y Double
z) = V3 Double
p V3 Double -> V3 Double -> V3 Double
forall a. Num a => a -> a -> a
- V3 Double
s
                    Ptr Trsf
trsf <- Acquire (Ptr Trsf)
GP.Trsf.new
                    Ptr Vec
vec <- Double -> Double -> Double -> Acquire (Ptr Vec)
GP.Vec.new Double
x Double
y Double
z
                    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 Trsf -> Ptr Vec -> IO ()
GP.Trsf.setTranslation Ptr Trsf
trsf Ptr Vec
vec
                    Ptr Wire
newWire <- (IO (Ptr Wire) -> Acquire (Ptr Wire)
forall a. IO a -> Acquire a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Ptr Wire) -> Acquire (Ptr Wire))
-> (Ptr Shape -> IO (Ptr Wire)) -> Ptr Shape -> Acquire (Ptr Wire)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Ptr Shape -> IO (Ptr Wire)
forall a b. DiscriminatedSubTypeOf a b => Ptr a -> IO (Ptr b)
unsafeDowncast) (Ptr Shape -> Acquire (Ptr Wire))
-> Acquire (Ptr Shape) -> Acquire (Ptr Wire)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Ptr Shape -> Ptr Trsf -> Bool -> Acquire (Ptr Shape)
BRepBuilderAPI.Transform.transform (Ptr Wire -> Ptr Shape
forall a b. SubTypeOf a b => Ptr b -> Ptr a
upcast Ptr Wire
wire) Ptr Trsf
trsf Bool
True 
                    (point, Ptr Wire) -> Acquire (point, Ptr Wire)
forall a. a -> Acquire a
forall (m :: * -> *) a. Monad m => a -> m a
return (point
pnt point -> point -> point
forall a. Num a => a -> a -> a
+ point
e' point -> point -> point
forall a. Num a => a -> a -> a
- point
s', Ptr Wire
newWire)
            in ((point, Ptr Wire) -> point
forall a b. (a, b) -> a
fst (point, Ptr Wire)
res, Acquire (Ptr Wire) -> path
forall point path. AnyPath point path => Acquire (Ptr Wire) -> path
fromWire (((point, Ptr Wire) -> Ptr Wire)
-> Acquire (point, Ptr Wire) -> Acquire (Ptr Wire)
forall a b. (a -> b) -> Acquire a -> Acquire b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (point, Ptr Wire) -> Ptr Wire
forall a b. (a, b) -> b
snd (Acquire (point, Ptr Wire) -> Acquire (Ptr Wire))
-> ((point, Ptr Wire) -> Acquire (point, Ptr Wire))
-> (point, Ptr Wire)
-> Acquire (Ptr Wire)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (point, Ptr Wire) -> Acquire (point, Ptr Wire)
forall a. a -> Acquire a
toAcquire ((point, Ptr Wire) -> Acquire (Ptr Wire))
-> (point, Ptr Wire) -> Acquire (Ptr Wire)
forall a b. (a -> b) -> a -> b
$ (point, Ptr Wire)
res))
        RawPath
_ -> (point
pnt, RawPath -> path
forall point path. AnyPath point path => RawPath -> path
reconstructPath RawPath
EmptyRawPath)

-- | Given a path, return a new path with the endpoints joined by a straight line.
closeLoop :: (AnyPath point path, Monoid path, Epsilon point) => path -> path
closeLoop :: forall point path.
(AnyPath point path, Monoid path, Epsilon point) =>
path -> path
closeLoop path
p = 
    case path -> Maybe (point, point)
forall point path.
AnyPath point path =>
path -> Maybe (point, point)
pathEndpoints path
p of
        Just (point
s, point
e) -> if point -> Bool
forall a. Epsilon a => a -> Bool
nearZero (point
s point -> point -> point
forall a. Num a => a -> a -> a
- point
e) 
            then path
p
            else path
p path -> path -> path
forall a. Semigroup a => a -> a -> a
<> point -> point -> path
forall point path.
(AnyPath point path, Epsilon point) =>
point -> point -> path
line point
e point
s
        Maybe (point, point)
Nothing -> path
p

reversePath :: (AnyPath point path) => path -> path
reversePath :: forall point path. AnyPath point path => path -> path
reversePath path
p = 
    case path -> RawPath
forall point path. AnyPath point path => path -> RawPath
deconstructPath path
p of
        ComplexRawPath Ptr Wire
r -> Acquire (Ptr Wire) -> path
forall point path. AnyPath point path => Acquire (Ptr Wire) -> path
fromWire (Acquire (Ptr Wire) -> path)
-> (Ptr Wire -> Acquire (Ptr Wire)) -> Ptr Wire -> path
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Ptr Wire -> Acquire (Ptr Wire)
reverseWire (Ptr Wire -> path) -> Ptr Wire -> path
forall a b. (a -> b) -> a -> b
$ Ptr Wire
r
        RawPath
_ -> path
p

-- | Break a path appart at any "non smooth" point
splitPath :: (AnyPath point path) => path -> [path]
splitPath :: forall point path. AnyPath point path => path -> [path]
splitPath path
p = 
    case path -> RawPath
forall point path. AnyPath point path => path -> RawPath
deconstructPath path
p of 
        ComplexRawPath Ptr Wire
r -> (Ptr Wire -> path) -> [Ptr Wire] -> [path]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (RawPath -> path
forall point path. AnyPath point path => RawPath -> path
reconstructPath (RawPath -> path) -> (Ptr Wire -> RawPath) -> Ptr Wire -> path
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Ptr Wire -> RawPath
ComplexRawPath) ([Ptr Wire] -> [path])
-> (Ptr Wire -> [Ptr Wire]) -> Ptr Wire -> [path]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Acquire [Ptr Wire] -> [Ptr Wire]
forall (t :: * -> *) a. Traversable t => Acquire (t a) -> t a
unsafeFromAcquireT (Acquire [Ptr Wire] -> [Ptr Wire])
-> (Ptr Wire -> Acquire [Ptr Wire]) -> Ptr Wire -> [Ptr Wire]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Ptr Wire -> Acquire [Ptr Wire]
splitWires (Ptr Wire -> [path]) -> Ptr Wire -> [path]
forall a b. (a -> b) -> a -> b
$ Ptr Wire
r
        RawPath
_ -> [path
p]

instance AnyPath (V3 Double) Path where
    reconstructPath :: RawPath -> Path
    reconstructPath :: RawPath -> Path
reconstructPath = RawPath -> Path
Path 
    pointToV3 :: Proxy Path -> V3 Double -> V3 Double
    pointToV3 :: Proxy Path -> V3 Double -> V3 Double
pointToV3 Proxy Path
_ = V3 Double -> V3 Double
forall a. a -> a
id
    deconstructPath :: Path -> RawPath
    deconstructPath :: Path -> RawPath
deconstructPath (Path RawPath
path) = RawPath
path
    v3ToPoint :: Proxy Path -> V3 Double -> V3 Double
    v3ToPoint :: Proxy Path -> V3 Double -> V3 Double
v3ToPoint Proxy Path
_ = V3 Double -> V3 Double
forall a. a -> a
id

instance AnyPath (V2 Double) Path2D where
    reconstructPath :: RawPath -> Path2D
    reconstructPath :: RawPath -> Path2D
reconstructPath = RawPath -> Path2D
Path2D
    pointToV3 :: Proxy Path2D -> V2 Double -> V3 Double
    pointToV3 :: Proxy Path2D -> V2 Double -> V3 Double
pointToV3 Proxy Path2D
_ (V2 Double
x Double
y) = Double -> Double -> Double -> V3 Double
forall a. a -> a -> a -> V3 a
V3 Double
x Double
y Double
0
    deconstructPath :: Path2D -> RawPath
    deconstructPath :: Path2D -> RawPath
deconstructPath (Path2D RawPath
path) = RawPath
path
    v3ToPoint :: Proxy Path2D -> V3 Double -> V2 Double
    v3ToPoint :: Proxy Path2D -> V3 Double -> V2 Double
v3ToPoint Proxy Path2D
_  = (V3 Double
-> Getting (V2 Double) (V3 Double) (V2 Double) -> V2 Double
forall s a. s -> Getting a s a -> a
^. Getting (V2 Double) (V3 Double) (V2 Double)
forall a. Lens' (V3 a) (V2 a)
forall (t :: * -> *) a. R2 t => Lens' (t a) (V2 a)
_xy)