{- ORMOLU_DISABLE -}
-- Copyright 2016, Julia Longtin (julial@turinglace.com)
-- Implicit CAD. Copyright (C) 2011, Christopher Olah (chris@colah.ca)
-- Released under the GNU AGPLV3+, see LICENSE

-- Allow us to use the tearser parallel list comprehension syntax, to avoid having to call zip in the complicated comprehensions below.
{-# LANGUAGE ParallelListComp #-}

-- export getContour and getMesh, which returns the edge of a 2D object, or the surface of a 3D object, respectively.
module Graphics.Implicit.Export.Render (getMesh, getContour) where

import Prelude(error, (-), ceiling, ($), (+), (*), max, div, tail, fmap, reverse, (.), foldMap, min, Int, (<>), (<$>))

import Graphics.Implicit.Definitions (, , Fastℕ, ℝ2, ℝ3, TriangleMesh, Obj2, SymbolicObj2, Obj3, SymbolicObj3, Polyline(getSegments), (⋯/), fromℕtoℝ, fromℕ)

import Graphics.Implicit.Export.Symbolic.Rebound2 (rebound2)

import Graphics.Implicit.Export.Symbolic.Rebound3 (rebound3)

import Graphics.Implicit.ObjectUtil (getBox2, getBox3)

import Data.Foldable(fold)
import Linear ( V3(V3), V2(V2) )

-- Here's the plan for rendering a cube (the 2D case is trivial):

-- (1) We calculate midpoints using interpolate.
--     This guarentees that our mesh will line up everywhere.
--     (Contrast with calculating them in getSegs)
import Graphics.Implicit.Export.Render.Interpolate (interpolate)

-- (2) We calculate the segments separating the inside and outside of our
--     object on the sides of the cube.
--     getSegs internally uses refine from RefineSegs to subdivide the segs
--     to better match the boundary.
import Graphics.Implicit.Export.Render.GetSegs (getSegs)

-- (3) We put the segments from all sides of the cube together
--     and extract closed loops.
import Graphics.Implicit.Export.Render.GetLoops (getLoops)

-- (4) We tesselate the loops, using a mixture of triangles and squares
import Graphics.Implicit.Export.Render.TesselateLoops (tesselateLoop)

-- (5) We try to merge squares, then turn everything into triangles.
import Graphics.Implicit.Export.Render.HandleSquares (mergedSquareTris)

-- Success: This is our mesh.

-- Each step on the Z axis is done in parallel using Control.Parallel.Strategies
import Control.Parallel.Strategies (using, rdeepseq, parBuffer)

-- The actual code is just a bunch of ugly argument passing.
-- Utility functions can be found at the end.

-- For efficiency, we need to avoid looking things up in other lists
-- (since they're 3D, it's an O(n³) operation...). So we need to make
-- our algorithms "flow" along the data structure instead of accessing
-- within it. To do this we use the ParallelListComp GHC extention.

-- We also compute lots of things in advance and pass them in as arguments,
-- to reduce redundant computations.

-- All in all, this is kind of ugly. But it is necessary.

-- Note: As far as the actual results of the rendering algorithm, nothing in
--       this file really matters. All the actual decisions about how to build
--       the mesh are abstracted into the imported files.

-- For the 2D case, we need one last thing, cleanLoopsFromSegs:
import Graphics.Implicit.Export.Render.HandlePolylines (cleanLoopsFromSegs)
import Data.Maybe (fromMaybe)
import Graphics.Implicit.Primitives (getImplicit)

-- Set the default types for the numbers in this file.
default (, Fastℕ, )

getMesh :: ℝ3 -> SymbolicObj3 -> TriangleMesh
getMesh :: ℝ3 -> SymbolicObj3 -> TriangleMesh
getMesh res :: ℝ3
res@(V3 xres yres zres) SymbolicObj3
symObj =
    let
        -- Grow bounds a little to avoid sampling at exact bounds
        (Obj3
obj, (p1 :: ℝ3
p1@(V3 x1 y1 z1), ℝ3
p2)) = (Obj3, (ℝ3, ℝ3)) -> (Obj3, (ℝ3, ℝ3))
rebound3 (SymbolicObj3 -> Obj3
forall obj (f :: * -> *) a. Object obj f a => obj -> f a -> a
getImplicit SymbolicObj3
symObj, SymbolicObj3 -> (ℝ3, ℝ3)
getBox3 SymbolicObj3
symObj)

        -- How much space are we rendering?
        d :: ℝ3
d = ℝ3
p2 ℝ3 -> ℝ3 -> ℝ3
forall a. Num a => a -> a -> a
- ℝ3
p1

        -- How many steps will we take on each axis?
        nx, ny, nz :: 
        steps :: V3 ℕ
steps@(V3 nx ny nz) = ℝ -> ℕ
forall a b. (RealFrac a, Integral b) => a -> b
ceiling (ℝ -> ℕ) -> ℝ3 -> V3 ℕ
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ( ℝ3
d ℝ3 -> ℝ3 -> ℝ3
forall a. ComponentWiseMultable a => a -> a -> a
⋯/ ℝ3
res)

        -- How big are the steps?
        (V3 rx ry rz) = ℝ3
d ℝ3 -> ℝ3 -> ℝ3
forall a. ComponentWiseMultable a => a -> a -> a
⋯/ (ℕ -> ℝ
fromℕtoℝ (ℕ -> ℝ) -> V3 ℕ -> ℝ3
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> V3 ℕ
steps)

        -- The planes we're rendering along.
        pYZ :: [ℝ]
pYZ = [ x1 ℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
+ rxℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
*ℕ -> ℝ
fromℕtoℝ n | n <- [0.. nx] ]
        pXZ :: [ℝ]
pXZ = [ y1 ℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
+ ryℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
*ℕ -> ℝ
fromℕtoℝ n | n <- [0.. ny] ]
        pXY :: [ℝ]
pXY = [ z1 ℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
+ rzℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
*ℕ -> ℝ
fromℕtoℝ n | n <- [0.. nz] ]

        -- performance tuning.
        -- FIXME: magic number.
        forcesteps :: Int
        forcesteps :: Int
forcesteps = Int
32

        -- Evaluate obj to avoid waste in mids, segs, later.
        objV :: [[[ℝ]]]
objV = ℕ -> ℕ -> ℕ -> [[[ℝ]]]
par3DList nx ny nz

        -- Sample our object(s) at every point in the 3D space given.
        par3DList ::  ->  ->  -> [[[]]]
        par3DList :: ℕ -> ℕ -> ℕ -> [[[ℝ]]]
par3DList lenx leny lenz =
            [[[ ℕ -> ℕ -> ℕ -> ℝ
sample mx my mz
            | mx <- [0..lenx] ] | my <- [0..leny] ] | mz <- [0..lenz] ]
              [[[ℝ]]] -> Strategy [[[ℝ]]] -> [[[ℝ]]]
forall a. a -> Strategy a -> a
`using` Int -> Strategy [[ℝ]] -> Strategy [[[ℝ]]]
forall a. Int -> Strategy a -> Strategy [a]
parBuffer (Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
1 (Int -> Int) -> Int -> Int
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Int
forall a. Integral a => a -> a -> a
div (ℕ -> Int
forall n. N n => ℕ -> n
fromℕ (ℕ -> Int) -> ℕ -> Int
forall a b. (a -> b) -> a -> b
$ (lenxℕ -> ℕ -> ℕ
forall a. Num a => a -> a -> a
+lenyℕ -> ℕ -> ℕ
forall a. Num a => a -> a -> a
+lenz)) Int
forcesteps) Strategy [[ℝ]]
forall a. NFData a => Strategy a
rdeepseq

        -- sample our object(s) at the given point.
        sample ::  ->  ->  -> 
        sample :: ℕ -> ℕ -> ℕ -> ℝ
sample mx my mz = Obj3
obj Obj3 -> Obj3
forall a b. (a -> b) -> a -> b
$
              ℝ -> ℝ -> ℝ -> ℝ3
forall a. a -> a -> a -> V3 a
V3
                (x1 ℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
+ rxℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
*(ℕ -> ℝ
fromℕtoℝ mx))
                (y1 ℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
+ ryℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
*(ℕ -> ℝ
fromℕtoℝ my))
                (z1 ℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
+ rzℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
*(ℕ -> ℝ
fromℕtoℝ mz))

        -- (1) Calculate mid points on X, Y, and Z axis in 3D space.
        midsZ :: [[[ℝ]]]
midsZ = [[[
                 ℝ2 -> ℝ2 -> (ℝ -> ℝ) -> ℝ -> ℝ
interpolate (ℝ -> ℝ -> ℝ2
forall a. a -> a -> V2 a
V2 z0 objX0Y0Z0) (ℝ -> ℝ -> ℝ2
forall a. a -> a -> V2 a
V2 z1' objX0Y0Z1) (Obj3 -> ℝ -> ℝ -> ℝ -> ℝ
appABC Obj3
obj x0 y0) zres
                 | x0 <- [ℝ]
pYZ |                   objX0Y0Z0 <- [ℝ]
objY0Z0 | objX0Y0Z1 <- [ℝ]
objY0Z1
                ]| y0 <- [ℝ]
pXZ |                   [ℝ]
objY0Z0   <- [[ℝ]]
objZ0   | [ℝ]
objY0Z1   <- [[ℝ]]
objZ1
                ]| z0 <- [ℝ]
pXY | z1' <- [ℝ] -> [ℝ]
forall a. [a] -> [a]
tail [ℝ]
pXY | [[ℝ]]
objZ0     <- [[[ℝ]]]
objV    | [[ℝ]]
objZ1     <- [[[ℝ]]] -> [[[ℝ]]]
forall a. [a] -> [a]
tail [[[ℝ]]]
objV
                ] [[[ℝ]]] -> Strategy [[[ℝ]]] -> [[[ℝ]]]
forall a. a -> Strategy a -> a
`using` Int -> Strategy [[ℝ]] -> Strategy [[[ℝ]]]
forall a. Int -> Strategy a -> Strategy [a]
parBuffer (Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
1 (Int -> Int) -> Int -> Int
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Int
forall a. Integral a => a -> a -> a
div (ℕ -> Int
forall n. N n => ℕ -> n
fromℕ nz) Int
forcesteps) Strategy [[ℝ]]
forall a. NFData a => Strategy a
rdeepseq

        midsY :: [[[ℝ]]]
midsY = [[[
                 ℝ2 -> ℝ2 -> (ℝ -> ℝ) -> ℝ -> ℝ
interpolate (ℝ -> ℝ -> ℝ2
forall a. a -> a -> V2 a
V2 y0 objX0Y0Z0) (ℝ -> ℝ -> ℝ2
forall a. a -> a -> V2 a
V2 y1' objX0Y1Z0) (Obj3 -> ℝ -> ℝ -> ℝ -> ℝ
appACB Obj3
obj x0 z0) yres
                 | x0 <- [ℝ]
pYZ |                   objX0Y0Z0 <- [ℝ]
objY0Z0 | objX0Y1Z0 <- [ℝ]
objY1Z0
                ]| y0 <- [ℝ]
pXZ | y1' <- [ℝ] -> [ℝ]
forall a. [a] -> [a]
tail [ℝ]
pXZ | [ℝ]
objY0Z0   <- [[ℝ]]
objZ0   | [ℝ]
objY1Z0   <- [[ℝ]] -> [[ℝ]]
forall a. [a] -> [a]
tail [[ℝ]]
objZ0
                ]| z0 <- [ℝ]
pXY |                   [[ℝ]]
objZ0     <- [[[ℝ]]]
objV
                ] [[[ℝ]]] -> Strategy [[[ℝ]]] -> [[[ℝ]]]
forall a. a -> Strategy a -> a
`using` Int -> Strategy [[ℝ]] -> Strategy [[[ℝ]]]
forall a. Int -> Strategy a -> Strategy [a]
parBuffer (Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
1 (Int -> Int) -> Int -> Int
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Int
forall a. Integral a => a -> a -> a
div (ℕ -> Int
forall n. N n => ℕ -> n
fromℕ ny) Int
forcesteps) Strategy [[ℝ]]
forall a. NFData a => Strategy a
rdeepseq

        midsX :: [[[ℝ]]]
midsX = [[[
                 ℝ2 -> ℝ2 -> (ℝ -> ℝ) -> ℝ -> ℝ
interpolate (ℝ -> ℝ -> ℝ2
forall a. a -> a -> V2 a
V2 x0 objX0Y0Z0) (ℝ -> ℝ -> ℝ2
forall a. a -> a -> V2 a
V2 x1' objX1Y0Z0) (Obj3 -> ℝ -> ℝ -> ℝ -> ℝ
appBCA Obj3
obj y0 z0) xres
                 | x0 <- [ℝ]
pYZ | x1' <- [ℝ] -> [ℝ]
forall a. [a] -> [a]
tail [ℝ]
pYZ | objX0Y0Z0 <- [ℝ]
objY0Z0 | objX1Y0Z0 <- [ℝ] -> [ℝ]
forall a. [a] -> [a]
tail [ℝ]
objY0Z0
                ]| y0 <- [ℝ]
pXZ |                   [ℝ]
objY0Z0   <- [[ℝ]]
objZ0
                ]| z0 <- [ℝ]
pXY |                   [[ℝ]]
objZ0     <- [[[ℝ]]]
objV
                ] [[[ℝ]]] -> Strategy [[[ℝ]]] -> [[[ℝ]]]
forall a. a -> Strategy a -> a
`using` Int -> Strategy [[ℝ]] -> Strategy [[[ℝ]]]
forall a. Int -> Strategy a -> Strategy [a]
parBuffer (Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
1 (Int -> Int) -> Int -> Int
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Int
forall a. Integral a => a -> a -> a
div (ℕ -> Int
forall n. N n => ℕ -> n
fromℕ nx) Int
forcesteps) Strategy [[ℝ]]
forall a. NFData a => Strategy a
rdeepseq

        -- (2) Calculate segments for each side
        segsZ :: [[[[[ℝ3]]]]]
segsZ = [[[
            ℝ -> Polyline -> [ℝ3]
injZ z0 (Polyline -> [ℝ3]) -> [Polyline] -> [[ℝ3]]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ℝ2 -> ℝ2 -> Obj2 -> (ℝ, ℝ, ℝ, ℝ) -> (ℝ, ℝ, ℝ, ℝ) -> [Polyline]
getSegs (ℝ -> ℝ -> ℝ2
forall a. a -> a -> V2 a
V2 x0 y0) (ℝ -> ℝ -> ℝ2
forall a. a -> a -> V2 a
V2 x1' y1') (Obj3
obj Obj3 -> ℝ -> Obj2
**$ z0) (objX0Y0Z0, objX1Y0Z0, objX0Y1Z0, objX1Y1Z0) (midA0, midA1, midB0, midB1)
             | x0<-[ℝ]
pYZ | x1'<-[ℝ] -> [ℝ]
forall a. [a] -> [a]
tail [ℝ]
pYZ |midB0<-[ℝ]
mX''  | midB1<-[ℝ]
mX'T     | midA0<-[ℝ]
mY''  | midA1<-[ℝ] -> [ℝ]
forall a. [a] -> [a]
tail [ℝ]
mY''  | objX0Y0Z0<-[ℝ]
objY0Z0 | objX1Y0Z0<- [ℝ] -> [ℝ]
forall a. [a] -> [a]
tail [ℝ]
objY0Z0 | objX0Y1Z0<-[ℝ]
objY1Z0    | objX1Y1Z0<-[ℝ] -> [ℝ]
forall a. [a] -> [a]
tail [ℝ]
objY1Z0
            ]| y0<-[ℝ]
pXZ | y1'<-[ℝ] -> [ℝ]
forall a. [a] -> [a]
tail [ℝ]
pXZ |[ℝ]
mX'' <-[[ℝ]]
mX'   | [ℝ]
mX'T <-[[ℝ]] -> [[ℝ]]
forall a. [a] -> [a]
tail [[ℝ]]
mX' | [ℝ]
mY'' <-[[ℝ]]
mY'                       | [ℝ]
objY0Z0  <-[[ℝ]]
objZ0                              | [ℝ]
objY1Z0  <-[[ℝ]] -> [[ℝ]]
forall a. [a] -> [a]
tail [[ℝ]]
objZ0
            ]| z0<-[ℝ]
pXY                 |[[ℝ]]
mX'  <-[[[ℝ]]]
midsX |                   [[ℝ]]
mY'  <-[[[ℝ]]]
midsY                     | [[ℝ]]
objZ0    <-[[[ℝ]]]
objV
            ] [[[[[ℝ3]]]]] -> Strategy [[[[[ℝ3]]]]] -> [[[[[ℝ3]]]]]
forall a. a -> Strategy a -> a
`using` Int -> Strategy [[[[ℝ3]]]] -> Strategy [[[[[ℝ3]]]]]
forall a. Int -> Strategy a -> Strategy [a]
parBuffer (Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
1 (Int -> Int) -> Int -> Int
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Int
forall a. Integral a => a -> a -> a
div (ℕ -> Int
forall n. N n => ℕ -> n
fromℕ nz) Int
forcesteps) Strategy [[[[ℝ3]]]]
forall a. NFData a => Strategy a
rdeepseq

        segsY :: [[[[[ℝ3]]]]]
segsY = [[[
            ℝ -> Polyline -> [ℝ3]
injY y0 (Polyline -> [ℝ3]) -> [Polyline] -> [[ℝ3]]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ℝ2 -> ℝ2 -> Obj2 -> (ℝ, ℝ, ℝ, ℝ) -> (ℝ, ℝ, ℝ, ℝ) -> [Polyline]
getSegs (ℝ -> ℝ -> ℝ2
forall a. a -> a -> V2 a
V2 x0 z0) (ℝ -> ℝ -> ℝ2
forall a. a -> a -> V2 a
V2 x1' z1') (Obj3
obj Obj3 -> ℝ -> Obj2
*$* y0) (objX0Y0Z0, objX1Y0Z0, objX0Y0Z1, objX1Y0Z1) (midA0, midA1, midB0, midB1)
             | x0<-[ℝ]
pYZ | x1'<-[ℝ] -> [ℝ]
forall a. [a] -> [a]
tail [ℝ]
pYZ | midB0<-[ℝ]
mB''  | midB1<-[ℝ]
mBT'       | midA0<-[ℝ]
mA''  | midA1<-[ℝ] -> [ℝ]
forall a. [a] -> [a]
tail [ℝ]
mA'' | objX0Y0Z0<-[ℝ]
objY0Z0 | objX1Y0Z0<-[ℝ] -> [ℝ]
forall a. [a] -> [a]
tail [ℝ]
objY0Z0 | objX0Y0Z1<-[ℝ]
objY0Z1 | objX1Y0Z1<-[ℝ] -> [ℝ]
forall a. [a] -> [a]
tail [ℝ]
objY0Z1
            ]| y0<-[ℝ]
pXZ |                 [ℝ]
mB'' <-[[ℝ]]
mB'   | [ℝ]
mBT' <-[[ℝ]]
mBT        | [ℝ]
mA'' <-[[ℝ]]
mA'                      | [ℝ]
objY0Z0  <-[[ℝ]]
objZ0                             | [ℝ]
objY0Z1  <-[[ℝ]]
objZ1
            ]| z0<-[ℝ]
pXY | z1'<-[ℝ] -> [ℝ]
forall a. [a] -> [a]
tail [ℝ]
pXY | [[ℝ]]
mB'  <-[[[ℝ]]]
midsX | [[ℝ]]
mBT  <-[[[ℝ]]] -> [[[ℝ]]]
forall a. [a] -> [a]
tail [[[ℝ]]]
midsX | [[ℝ]]
mA'  <-[[[ℝ]]]
midsZ                    | [[ℝ]]
objZ0    <-[[[ℝ]]]
objV                              | [[ℝ]]
objZ1    <-[[[ℝ]]] -> [[[ℝ]]]
forall a. [a] -> [a]
tail [[[ℝ]]]
objV
            ] [[[[[ℝ3]]]]] -> Strategy [[[[[ℝ3]]]]] -> [[[[[ℝ3]]]]]
forall a. a -> Strategy a -> a
`using` Int -> Strategy [[[[ℝ3]]]] -> Strategy [[[[[ℝ3]]]]]
forall a. Int -> Strategy a -> Strategy [a]
parBuffer (Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
1 (Int -> Int) -> Int -> Int
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Int
forall a. Integral a => a -> a -> a
div (ℕ -> Int
forall n. N n => ℕ -> n
fromℕ ny) Int
forcesteps) Strategy [[[[ℝ3]]]]
forall a. NFData a => Strategy a
rdeepseq

        segsX :: [[[[[ℝ3]]]]]
segsX = [[[
            ℝ -> Polyline -> [ℝ3]
injX x0 (Polyline -> [ℝ3]) -> [Polyline] -> [[ℝ3]]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ℝ2 -> ℝ2 -> Obj2 -> (ℝ, ℝ, ℝ, ℝ) -> (ℝ, ℝ, ℝ, ℝ) -> [Polyline]
getSegs (ℝ -> ℝ -> ℝ2
forall a. a -> a -> V2 a
V2 y0 z0) (ℝ -> ℝ -> ℝ2
forall a. a -> a -> V2 a
V2 y1' z1') (Obj3
obj Obj3 -> ℝ -> Obj2
$** x0) (objX0Y0Z0, objX0Y1Z0, objX0Y0Z1, objX0Y1Z1) (midA0, midA1, midB0, midB1)
             | x0<-[ℝ]
pYZ |                 midB0<-[ℝ]
mB''  | midB1<-[ℝ]
mBT'       | midA0<-[ℝ]
mA''  | midA1<-[ℝ]
mA'T     | objX0Y0Z0<-[ℝ]
objY0Z0 | objX0Y1Z0<-[ℝ]
objY1Z0    | objX0Y0Z1<-[ℝ]
objY0Z1    | objX0Y1Z1<-     [ℝ]
objY1Z1
            ]| y0<-[ℝ]
pXZ | y1'<-[ℝ] -> [ℝ]
forall a. [a] -> [a]
tail [ℝ]
pXZ | [ℝ]
mB'' <-[[ℝ]]
mB'   | [ℝ]
mBT' <-[[ℝ]]
mBT        | [ℝ]
mA'' <-[[ℝ]]
mA'   | [ℝ]
mA'T <-[[ℝ]] -> [[ℝ]]
forall a. [a] -> [a]
tail [[ℝ]]
mA' | [ℝ]
objY0Z0  <-[[ℝ]]
objZ0   | [ℝ]
objY1Z0  <-[[ℝ]] -> [[ℝ]]
forall a. [a] -> [a]
tail [[ℝ]]
objZ0 | [ℝ]
objY0Z1  <-[[ℝ]]
objZ1      | [ℝ]
objY1Z1  <-[[ℝ]] -> [[ℝ]]
forall a. [a] -> [a]
tail [[ℝ]]
objZ1
            ]| z0<-[ℝ]
pXY | z1'<-[ℝ] -> [ℝ]
forall a. [a] -> [a]
tail [ℝ]
pXY | [[ℝ]]
mB'  <-[[[ℝ]]]
midsY | [[ℝ]]
mBT  <-[[[ℝ]]] -> [[[ℝ]]]
forall a. [a] -> [a]
tail [[[ℝ]]]
midsY | [[ℝ]]
mA'  <-[[[ℝ]]]
midsZ                   | [[ℝ]]
objZ0    <- [[[ℝ]]]
objV                           | [[ℝ]]
objZ1    <- [[[ℝ]]] -> [[[ℝ]]]
forall a. [a] -> [a]
tail [[[ℝ]]]
objV
            ] [[[[[ℝ3]]]]] -> Strategy [[[[[ℝ3]]]]] -> [[[[[ℝ3]]]]]
forall a. a -> Strategy a -> a
`using` Int -> Strategy [[[[ℝ3]]]] -> Strategy [[[[[ℝ3]]]]]
forall a. Int -> Strategy a -> Strategy [a]
parBuffer (Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
1 (Int -> Int) -> Int -> Int
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Int
forall a. Integral a => a -> a -> a
div (ℕ -> Int
forall n. N n => ℕ -> n
fromℕ nx) Int
forcesteps) Strategy [[[[ℝ3]]]]
forall a. NFData a => Strategy a
rdeepseq

        -- (3) & (4) : get and tesselate loops
        -- FIXME: hack.
        minres :: ℝ
minres = xres ℝ -> ℝ -> ℝ
forall a. Ord a => a -> a -> a
`min` yres ℝ -> ℝ -> ℝ
forall a. Ord a => a -> a -> a
`min` zres
        sqTris :: [[[[TriSquare]]]]
sqTris = [[[
            ([[ℝ3]] -> [TriSquare]) -> [[[ℝ3]]] -> [TriSquare]
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap (ℝ -> Obj3 -> [[ℝ3]] -> [TriSquare]
tesselateLoop minres Obj3
obj) ([[[ℝ3]]] -> [TriSquare]) -> [[[ℝ3]]] -> [TriSquare]
forall a b. (a -> b) -> a -> b
$
              [[[ℝ3]]] -> Maybe [[[ℝ3]]] -> [[[ℝ3]]]
forall a. a -> Maybe a -> a
fromMaybe ([Char] -> [[[ℝ3]]]
forall a. HasCallStack => [Char] -> a
error [Char]
"unclosed loop in paths given") (Maybe [[[ℝ3]]] -> [[[ℝ3]]]) -> Maybe [[[ℝ3]]] -> [[[ℝ3]]]
forall a b. (a -> b) -> a -> b
$ [[ℝ3]] -> Maybe [[[ℝ3]]]
forall a. Eq a => [[a]] -> Maybe [[[a]]]
getLoops ([[ℝ3]] -> Maybe [[[ℝ3]]]) -> [[ℝ3]] -> Maybe [[[ℝ3]]]
forall a b. (a -> b) -> a -> b
$
                        [[ℝ3]]
segX''' [[ℝ3]] -> [[ℝ3]] -> [[ℝ3]]
forall a. Semigroup a => a -> a -> a
<>
                   [[ℝ3]] -> [[ℝ3]]
mapR [[ℝ3]]
segX''T [[ℝ3]] -> [[ℝ3]] -> [[ℝ3]]
forall a. Semigroup a => a -> a -> a
<>
                   [[ℝ3]] -> [[ℝ3]]
mapR [[ℝ3]]
segY''' [[ℝ3]] -> [[ℝ3]] -> [[ℝ3]]
forall a. Semigroup a => a -> a -> a
<>
                        [[ℝ3]]
segY'T' [[ℝ3]] -> [[ℝ3]] -> [[ℝ3]]
forall a. Semigroup a => a -> a -> a
<>
                        [[ℝ3]]
segZ''' [[ℝ3]] -> [[ℝ3]] -> [[ℝ3]]
forall a. Semigroup a => a -> a -> a
<>
                   [[ℝ3]] -> [[ℝ3]]
mapR [[ℝ3]]
segZT''
             | [[ℝ3]]
segZ'''<- [[[ℝ3]]]
segZ''| [[ℝ3]]
segZT''<- [[[ℝ3]]]
segZT'
             | [[ℝ3]]
segY'''<- [[[ℝ3]]]
segY''| [[ℝ3]]
segY'T'<- [[[ℝ3]]]
segY'T
             | [[ℝ3]]
segX'''<- [[[ℝ3]]]
segX''| [[ℝ3]]
segX''T<- [[[ℝ3]]] -> [[[ℝ3]]]
forall a. [a] -> [a]
tail [[[ℝ3]]]
segX''

            ]| [[[ℝ3]]]
segZ'' <- [[[[ℝ3]]]]
segZ' | [[[ℝ3]]]
segZT' <- [[[[ℝ3]]]]
segZT
             | [[[ℝ3]]]
segY'' <- [[[[ℝ3]]]]
segY' | [[[ℝ3]]]
segY'T <- [[[[ℝ3]]]] -> [[[[ℝ3]]]]
forall a. [a] -> [a]
tail [[[[ℝ3]]]]
segY'
             | [[[ℝ3]]]
segX'' <- [[[[ℝ3]]]]
segX'

            ]| [[[[ℝ3]]]]
segZ'  <- [[[[[ℝ3]]]]]
segsZ | [[[[ℝ3]]]]
segZT  <- [[[[[ℝ3]]]]] -> [[[[[ℝ3]]]]]
forall a. [a] -> [a]
tail [[[[[ℝ3]]]]]
segsZ
             | [[[[ℝ3]]]]
segY'  <- [[[[[ℝ3]]]]]
segsY
             | [[[[ℝ3]]]]
segX'  <- [[[[[ℝ3]]]]]
segsX
            ] [[[[TriSquare]]]]
-> Strategy [[[[TriSquare]]]] -> [[[[TriSquare]]]]
forall a. a -> Strategy a -> a
`using` Int -> Strategy [[[TriSquare]]] -> Strategy [[[[TriSquare]]]]
forall a. Int -> Strategy a -> Strategy [a]
parBuffer (Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
1 (Int -> Int) -> Int -> Int
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Int
forall a. Integral a => a -> a -> a
div (ℕ -> Int
forall n. N n => ℕ -> n
fromℕ (ℕ -> Int) -> ℕ -> Int
forall a b. (a -> b) -> a -> b
$ nxℕ -> ℕ -> ℕ
forall a. Num a => a -> a -> a
+nyℕ -> ℕ -> ℕ
forall a. Num a => a -> a -> a
+nz) Int
forcesteps) Strategy [[[TriSquare]]]
forall a. NFData a => Strategy a
rdeepseq

    in
      -- (5) merge squares, etc
      [TriSquare] -> TriangleMesh
mergedSquareTris ([TriSquare] -> TriangleMesh)
-> ([[[TriSquare]]] -> [TriSquare])
-> [[[TriSquare]]]
-> TriangleMesh
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [[TriSquare]] -> [TriSquare]
forall (t :: * -> *) m. (Foldable t, Monoid m) => t m -> m
fold ([[TriSquare]] -> [TriSquare])
-> ([[[TriSquare]]] -> [[TriSquare]])
-> [[[TriSquare]]]
-> [TriSquare]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [[[TriSquare]]] -> [[TriSquare]]
forall (t :: * -> *) m. (Foldable t, Monoid m) => t m -> m
fold ([[[TriSquare]]] -> TriangleMesh)
-> [[[TriSquare]]] -> TriangleMesh
forall a b. (a -> b) -> a -> b
$ [[[[TriSquare]]]] -> [[[TriSquare]]]
forall (t :: * -> *) m. (Foldable t, Monoid m) => t m -> m
fold [[[[TriSquare]]]]
sqTris

-- | getContour gets a polyline describing the edge of a 2D object.
getContour :: ℝ2 -> SymbolicObj2 -> [Polyline]
getContour :: ℝ2 -> SymbolicObj2 -> [Polyline]
getContour res :: ℝ2
res@(V2 xres yres) SymbolicObj2
symObj =
    let
        -- Grow bounds a little to avoid sampling at exact bounds
        (Obj2
obj, (p1 :: ℝ2
p1@(V2 x1 y1), ℝ2
p2)) = (Obj2, (ℝ2, ℝ2)) -> (Obj2, (ℝ2, ℝ2))
rebound2 (SymbolicObj2 -> Obj2
forall obj (f :: * -> *) a. Object obj f a => obj -> f a -> a
getImplicit SymbolicObj2
symObj, SymbolicObj2 -> (ℝ2, ℝ2)
getBox2 SymbolicObj2
symObj)

        -- The size of the region we're being asked to search.
        d :: ℝ2
d = ℝ2
p2 ℝ2 -> ℝ2 -> ℝ2
forall a. Num a => a -> a -> a
- ℝ2
p1

        -- How many steps will we take on each axis?
        nx, ny :: 
        steps :: V2 ℕ
steps@(V2 nx ny) = ℝ -> ℕ
forall a b. (RealFrac a, Integral b) => a -> b
ceiling (ℝ -> ℕ) -> ℝ2 -> V2 ℕ
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (ℝ2
d ℝ2 -> ℝ2 -> ℝ2
forall a. ComponentWiseMultable a => a -> a -> a
⋯/ ℝ2
res)

        -- How big are the steps?
        (V2 rx ry) = ℝ2
d ℝ2 -> ℝ2 -> ℝ2
forall a. ComponentWiseMultable a => a -> a -> a
⋯/ (ℕ -> ℝ
fromℕtoℝ (ℕ -> ℝ) -> V2 ℕ -> ℝ2
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> V2 ℕ
steps)

        -- The lines we are rendering along.
        pX :: [ℝ]
pX = [ x1 ℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
+ rxℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
*ℕ -> ℝ
fromℕtoℝ p | p <- [0.. nx] ]
        pY :: [ℝ]
pY = [ y1 ℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
+ ryℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
*ℕ -> ℝ
fromℕtoℝ p | p <- [0.. ny] ]

        -- Performance tuning.
        -- FIXME: magic number.
        forcesteps :: Int
        forcesteps :: Int
forcesteps = Int
32

        -- Evaluate obj to avoid waste in mids, segs, later.
        objV :: [[ℝ]]
objV = ℕ -> ℕ -> [[ℝ]]
par2DList nx ny

        -- Sample our object(s) at every point in the 2D plane given.
        par2DList ::  ->  -> [[]]
        par2DList :: ℕ -> ℕ -> [[ℝ]]
par2DList lenx leny =
            [[ ℕ -> ℕ -> ℝ
sample mx my
                  | mx <- [0..lenx]
                ] | my <- [0..leny]
                ] [[ℝ]] -> Strategy [[ℝ]] -> [[ℝ]]
forall a. a -> Strategy a -> a
`using` Int -> Strategy [ℝ] -> Strategy [[ℝ]]
forall a. Int -> Strategy a -> Strategy [a]
parBuffer (Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
1 (Int -> Int) -> Int -> Int
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Int
forall a. Integral a => a -> a -> a
div (ℕ -> Int
forall n. N n => ℕ -> n
fromℕ (ℕ -> Int) -> ℕ -> Int
forall a b. (a -> b) -> a -> b
$ lenxℕ -> ℕ -> ℕ
forall a. Num a => a -> a -> a
+leny) Int
forcesteps) Strategy [ℝ]
forall a. NFData a => Strategy a
rdeepseq

        -- sample our object(s) at the given point.
        sample ::  ->  -> 
        sample :: ℕ -> ℕ -> ℝ
sample mx my = Obj2
obj Obj2 -> Obj2
forall a b. (a -> b) -> a -> b
$
          ℝ -> ℝ -> ℝ2
forall a. a -> a -> V2 a
V2
                (x1 ℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
+ rxℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
*ℕ -> ℝ
fromℕtoℝ mx)
                (y1 ℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
+ ryℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
*ℕ -> ℝ
fromℕtoℝ my)

        -- Calculate mid points on X axis in 2D space.
        midsX :: [[ℝ]]
midsX = [[
                 ℝ2 -> ℝ2 -> (ℝ -> ℝ) -> ℝ -> ℝ
interpolate (ℝ -> ℝ -> ℝ2
forall a. a -> a -> V2 a
V2 x0 objX0Y0) (ℝ -> ℝ -> ℝ2
forall a. a -> a -> V2 a
V2 x1' objX1Y0) (Obj2
obj Obj2 -> ℝ -> ℝ -> ℝ
*$ y0) xres
                 | x0 <- [ℝ]
pX | x1' <- [ℝ] -> [ℝ]
forall a. [a] -> [a]
tail [ℝ]
pX | objX0Y0 <- [ℝ]
objY0 | objX1Y0 <- [ℝ] -> [ℝ]
forall a. [a] -> [a]
tail [ℝ]
objY0
                ]| y0 <- [ℝ]
pY |                   [ℝ]
objY0   <- [[ℝ]]
objV
                ] [[ℝ]] -> Strategy [[ℝ]] -> [[ℝ]]
forall a. a -> Strategy a -> a
`using` Int -> Strategy [ℝ] -> Strategy [[ℝ]]
forall a. Int -> Strategy a -> Strategy [a]
parBuffer (Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
1 (Int -> Int) -> Int -> Int
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Int
forall a. Integral a => a -> a -> a
div (ℕ -> Int
forall n. N n => ℕ -> n
fromℕ nx) Int
forcesteps) Strategy [ℝ]
forall a. NFData a => Strategy a
rdeepseq

        -- Calculate mid points on Y axis in 2D space.
        midsY :: [[ℝ]]
midsY = [[
                 ℝ2 -> ℝ2 -> (ℝ -> ℝ) -> ℝ -> ℝ
interpolate (ℝ -> ℝ -> ℝ2
forall a. a -> a -> V2 a
V2 y0 objX0Y0) (ℝ -> ℝ -> ℝ2
forall a. a -> a -> V2 a
V2 y1' objX0Y1) (Obj2
obj Obj2 -> ℝ -> ℝ -> ℝ
$* x0) yres
                 | x0 <- [ℝ]
pX |                  objX0Y0 <- [ℝ]
objY0   | objX0Y1 <- [ℝ]
objY1
                ]| y0 <- [ℝ]
pY | y1' <- [ℝ] -> [ℝ]
forall a. [a] -> [a]
tail [ℝ]
pY | [ℝ]
objY0   <- [[ℝ]]
objV    | [ℝ]
objY1   <- [[ℝ]] -> [[ℝ]]
forall a. [a] -> [a]
tail [[ℝ]]
objV
                ] [[ℝ]] -> Strategy [[ℝ]] -> [[ℝ]]
forall a. a -> Strategy a -> a
`using` Int -> Strategy [ℝ] -> Strategy [[ℝ]]
forall a. Int -> Strategy a -> Strategy [a]
parBuffer (Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
1 (Int -> Int) -> Int -> Int
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Int
forall a. Integral a => a -> a -> a
div (ℕ -> Int
forall n. N n => ℕ -> n
fromℕ ny) Int
forcesteps) Strategy [ℝ]
forall a. NFData a => Strategy a
rdeepseq

        -- Calculate segments for each side
        segs :: [[[Polyline]]]
segs = [[
            ℝ2 -> ℝ2 -> Obj2 -> (ℝ, ℝ, ℝ, ℝ) -> (ℝ, ℝ, ℝ, ℝ) -> [Polyline]
getSegs (ℝ -> ℝ -> ℝ2
forall a. a -> a -> V2 a
V2 x0 y0) (ℝ -> ℝ -> ℝ2
forall a. a -> a -> V2 a
V2 x1' y1') Obj2
obj (objX0Y0, objX1Y0, objX0Y1, objX1Y1) (midA0, midA1, midB0, midB1)
             | x0<-[ℝ]
pX | x1'<-[ℝ] -> [ℝ]
forall a. [a] -> [a]
tail [ℝ]
pX |midB0<-[ℝ]
mX''  | midB1<-[ℝ]
mX'T       | midA0<-[ℝ]
mY''  | midA1<-[ℝ] -> [ℝ]
forall a. [a] -> [a]
tail [ℝ]
mY'' | objX0Y0<-[ℝ]
objY0 | objX1Y0<-[ℝ] -> [ℝ]
forall a. [a] -> [a]
tail [ℝ]
objY0 | objX0Y1<-[ℝ]
objY1 | objX1Y1<-[ℝ] -> [ℝ]
forall a. [a] -> [a]
tail [ℝ]
objY1
            ]| y0<-[ℝ]
pY | y1'<-[ℝ] -> [ℝ]
forall a. [a] -> [a]
tail [ℝ]
pY |[ℝ]
mX'' <-[[ℝ]]
midsX | [ℝ]
mX'T <-[[ℝ]] -> [[ℝ]]
forall a. [a] -> [a]
tail [[ℝ]]
midsX | [ℝ]
mY'' <-[[ℝ]]
midsY                    | [ℝ]
objY0 <- [[ℝ]]
objV                        | [ℝ]
objY1 <- [[ℝ]] -> [[ℝ]]
forall a. [a] -> [a]
tail [[ℝ]]
objV
            ] [[[Polyline]]] -> Strategy [[[Polyline]]] -> [[[Polyline]]]
forall a. a -> Strategy a -> a
`using` Int -> Strategy [[Polyline]] -> Strategy [[[Polyline]]]
forall a. Int -> Strategy a -> Strategy [a]
parBuffer (Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
1 (Int -> Int) -> Int -> Int
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Int
forall a. Integral a => a -> a -> a
div (ℕ -> Int
forall n. N n => ℕ -> n
fromℕ (ℕ -> Int) -> ℕ -> Int
forall a b. (a -> b) -> a -> b
$ nxℕ -> ℕ -> ℕ
forall a. Num a => a -> a -> a
+ny) Int
forcesteps) Strategy [[Polyline]]
forall a. NFData a => Strategy a
rdeepseq
    in
      -- Merge squares
      [Polyline] -> [Polyline]
cleanLoopsFromSegs ([Polyline] -> [Polyline])
-> ([[Polyline]] -> [Polyline]) -> [[Polyline]] -> [Polyline]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [[Polyline]] -> [Polyline]
forall (t :: * -> *) m. (Foldable t, Monoid m) => t m -> m
fold ([[Polyline]] -> [Polyline]) -> [[Polyline]] -> [Polyline]
forall a b. (a -> b) -> a -> b
$ [[[Polyline]]] -> [[Polyline]]
forall (t :: * -> *) m. (Foldable t, Monoid m) => t m -> m
fold [[[Polyline]]]
segs

-- utility functions

injX ::  -> Polyline -> [ℝ3]
injX :: ℝ -> Polyline -> [ℝ3]
injX val Polyline
polyline = (ℝ -> ℝ2 -> ℝ3
prepend val) (ℝ2 -> ℝ3) -> [ℝ2] -> [ℝ3]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Polyline -> [ℝ2]
getSegments Polyline
polyline
  where
    prepend ::  -> ℝ2 -> ℝ3
    prepend :: ℝ -> ℝ2 -> ℝ3
prepend a (V2 b c) = ℝ -> ℝ -> ℝ -> ℝ3
forall a. a -> a -> a -> V3 a
V3 a b c

injY ::  -> Polyline -> [ℝ3]
injY :: ℝ -> Polyline -> [ℝ3]
injY val Polyline
polyline = (ℝ -> ℝ2 -> ℝ3
insert val)  (ℝ2 -> ℝ3) -> [ℝ2] -> [ℝ3]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Polyline -> [ℝ2]
getSegments Polyline
polyline
  where
    insert ::  -> ℝ2 -> ℝ3
    insert :: ℝ -> ℝ2 -> ℝ3
insert b (V2 a c) = ℝ -> ℝ -> ℝ -> ℝ3
forall a. a -> a -> a -> V3 a
V3 a b c

injZ ::  -> Polyline -> [ℝ3]
injZ :: ℝ -> Polyline -> [ℝ3]
injZ val Polyline
polyline = (ℝ -> ℝ2 -> ℝ3
postfix val) (ℝ2 -> ℝ3) -> [ℝ2] -> [ℝ3]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Polyline -> [ℝ2]
getSegments Polyline
polyline
  where
    postfix ::  -> ℝ2 -> ℝ3
    postfix :: ℝ -> ℝ2 -> ℝ3
postfix c (V2 a b) = ℝ -> ℝ -> ℝ -> ℝ3
forall a. a -> a -> a -> V3 a
V3 a b c

($**) :: Obj3 ->  -> ℝ2 -> 
Obj3
f $** :: Obj3 -> ℝ -> Obj2
$** a = \(V2 b c) -> Obj3
f (ℝ -> ℝ -> ℝ -> ℝ3
forall a. a -> a -> a -> V3 a
V3 a b c)
infixr 0 $**

(*$*) :: Obj3 ->  -> ℝ2 -> 
Obj3
f *$* :: Obj3 -> ℝ -> Obj2
*$* b = \(V2 a c) -> Obj3
f (ℝ -> ℝ -> ℝ -> ℝ3
forall a. a -> a -> a -> V3 a
V3 a b c)
infixr 0 *$*

(**$) :: Obj3 ->  -> ℝ2 -> 
Obj3
f **$ :: Obj3 -> ℝ -> Obj2
**$ c = \(V2 a b) -> Obj3
f (ℝ -> ℝ -> ℝ -> ℝ3
forall a. a -> a -> a -> V3 a
V3 a b c)
infixr 0 **$

($*) :: Obj2 ->  ->  -> 
Obj2
f $* :: Obj2 -> ℝ -> ℝ -> ℝ
$* a = Obj2
f Obj2 -> (ℝ -> ℝ2) -> ℝ -> ℝ
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ℝ -> ℝ -> ℝ2
forall a. a -> a -> V2 a
V2 a
infixr 0 $*

(*$) :: Obj2 ->  ->  -> 
Obj2
f *$ :: Obj2 -> ℝ -> ℝ -> ℝ
*$ b = \a -> Obj2
f (ℝ -> ℝ -> ℝ2
forall a. a -> a -> V2 a
V2 a b)
infixr 0 *$

appABC :: Obj3 ->  ->  ->  -> 
appABC :: Obj3 -> ℝ -> ℝ -> ℝ -> ℝ
appABC Obj3
f a b c = Obj3
f (ℝ -> ℝ -> ℝ -> ℝ3
forall a. a -> a -> a -> V3 a
V3 a b c)
appBCA :: Obj3 ->  ->  ->  -> 
appBCA :: Obj3 -> ℝ -> ℝ -> ℝ -> ℝ
appBCA Obj3
f b c a = Obj3
f (ℝ -> ℝ -> ℝ -> ℝ3
forall a. a -> a -> a -> V3 a
V3 a b c)
appACB :: Obj3 ->  ->  ->  -> 
appACB :: Obj3 -> ℝ -> ℝ -> ℝ -> ℝ
appACB Obj3
f a c b = Obj3
f (ℝ -> ℝ -> ℝ -> ℝ3
forall a. a -> a -> a -> V3 a
V3 a b c)

mapR :: [[ℝ3]] -> [[ℝ3]]
mapR :: [[ℝ3]] -> [[ℝ3]]
mapR = ([ℝ3] -> [ℝ3]) -> [[ℝ3]] -> [[ℝ3]]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [ℝ3] -> [ℝ3]
forall a. [a] -> [a]
reverse