{- ORMOLU_DISABLE -}
-- Copyright 2014 2015 2016, Julia Longtin (julial@turinglace.com)
-- Copyright 2015 2016, Mike MacHenry (mike.machenry@gmail.com)
-- Implicit CAD. Copyright (C) 2011, Christopher Olah (chris@colah.ca)
-- Released under the GNU AGPLV3+, see LICENSE
{-# LANGUAGE FlexibleContexts    #-}
{-# LANGUAGE GADTs               #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications    #-}

module Graphics.Implicit.ObjectUtil.GetImplicitShared (getImplicitShared, normalize) where

import {-# SOURCE #-} Graphics.Implicit.Primitives (Object(getImplicit'))

import Prelude (flip, (-), (*), (>), (<), (&&), (/), product, abs, (**), fmap, (.), negate, ($), const)

import Graphics.Implicit.Definitions
    ( objectRounding, ObjectContext, SharedObj(Empty, Full, Complement, UnionR, IntersectR, DifferenceR, Translate, Scale, Mirror, Shell, Outset, EmbedBoxedObj, WithRounding), ComponentWiseMultable((⋯/)), , minℝ )

import Graphics.Implicit.MathUtil (infty, rmax, rmaximum, rminimum, reflect)

-- Use getImplicit2 for handling extrusion of 2D shapes to 3D.
import Graphics.Implicit.ObjectUtil.GetBoxShared (VectorStuff(elements, uniformV))

import Linear (Metric(dot))

------------------------------------------------------------------------------
-- | Normalize a dimensionality-polymorphic vector.
normalize
    :: forall f
     . (VectorStuff (f ), Metric f)
    => f 
    -> 
normalize :: forall (f :: * -> *). (VectorStuff (f ℝ), Metric f) => f ℝ -> ℝ
normalize f ℝ
v =
  let all1s :: f ℝ
all1s = forall vec. VectorStuff vec => ℝ -> vec
uniformV @(f ) 1
   in forall a. Num a => a -> a
abs (forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
product (forall vec. VectorStuff vec => vec -> [ℝ]
elements f ℝ
v)) forall a. Floating a => a -> a -> a
** (1 forall a. Fractional a => a -> a -> a
/ (f ℝ
all1s forall (f :: * -> *) a. (Metric f, Num a) => f a -> f a -> a
`dot` f ℝ
all1s))

-- Get a function that describes the surface of the object.
getImplicitShared
    :: forall obj f
     . ( Object obj f 
       , VectorStuff (f )
       , ComponentWiseMultable (f )
       , Metric f
       )
    => ObjectContext
    -> SharedObj obj f 
    -> f 
    -> 
getImplicitShared :: forall obj (f :: * -> *).
(Object obj f ℝ, VectorStuff (f ℝ), ComponentWiseMultable (f ℝ),
 Metric f) =>
ObjectContext -> SharedObj obj f ℝ -> f ℝ -> ℝ
getImplicitShared ObjectContext
_ SharedObj obj f ℝ
Empty = forall a b. a -> b -> a
const forall t. Fractional t => t
infty
getImplicitShared ObjectContext
_ SharedObj obj f ℝ
Full = forall a b. a -> b -> a
const forall a b. (a -> b) -> a -> b
$ -forall t. Fractional t => t
infty
getImplicitShared ObjectContext
ctx (Complement obj
symbObj) =
  forall a. Num a => a -> a
negate forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall obj (f :: * -> *) a.
Object obj f a =>
ObjectContext -> obj -> f a -> a
getImplicit' ObjectContext
ctx obj
symbObj
getImplicitShared ObjectContext
ctx (UnionR r [obj]
symbObjs) = \f ℝ
p ->
  ℝ -> [ℝ] -> ℝ
rminimum r forall a b. (a -> b) -> a -> b
$ forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall a b c. (a -> b -> c) -> b -> a -> c
flip (forall obj (f :: * -> *) a.
Object obj f a =>
ObjectContext -> obj -> f a -> a
getImplicit' ObjectContext
ctx) f ℝ
p) [obj]
symbObjs
getImplicitShared ObjectContext
ctx (IntersectR r [obj]
symbObjs) = \f ℝ
p ->
  ℝ -> [ℝ] -> ℝ
rmaximum r forall a b. (a -> b) -> a -> b
$ forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall a b c. (a -> b -> c) -> b -> a -> c
flip (forall obj (f :: * -> *) a.
Object obj f a =>
ObjectContext -> obj -> f a -> a
getImplicit' ObjectContext
ctx) f ℝ
p) [obj]
symbObjs
getImplicitShared ObjectContext
ctx (DifferenceR _ obj
symbObj []) =
  forall obj (f :: * -> *) a.
Object obj f a =>
ObjectContext -> obj -> f a -> a
getImplicit' ObjectContext
ctx obj
symbObj
getImplicitShared ObjectContext
ctx (DifferenceR r obj
symbObj [obj]
symbObjs) =
    let headObj :: f ℝ -> ℝ
headObj = forall obj (f :: * -> *) a.
Object obj f a =>
ObjectContext -> obj -> f a -> a
getImplicit' ObjectContext
ctx obj
symbObj
    in
      \f ℝ
p -> do
        let
          maxTail :: ℝ
maxTail = ℝ -> [ℝ] -> ℝ
rmaximum r
                  forall a b. (a -> b) -> a -> b
$ forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall a b c. (a -> b -> c) -> b -> a -> c
flip (forall obj (f :: * -> *).
(Object obj f ℝ, VectorStuff (f ℝ), ComponentWiseMultable (f ℝ),
 Metric f) =>
ObjectContext -> SharedObj obj f ℝ -> f ℝ -> ℝ
getImplicitShared ObjectContext
ctx) f ℝ
p forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall obj (f :: * -> *) a. obj -> SharedObj obj f a
Complement) [obj]
symbObjs
        if maxTail forall a. Ord a => a -> a -> Bool
> -minℝ Bool -> Bool -> Bool
&& maxTail forall a. Ord a => a -> a -> Bool
< minℝ
          then ℝ -> ℝ -> ℝ -> ℝ
rmax r (f ℝ -> ℝ
headObj f ℝ
p) minℝ
          else ℝ -> ℝ -> ℝ -> ℝ
rmax r (f ℝ -> ℝ
headObj f ℝ
p) maxTail

-- Simple transforms
getImplicitShared ObjectContext
ctx (Translate f ℝ
v obj
symbObj) = \f ℝ
p ->
  forall obj (f :: * -> *) a.
Object obj f a =>
ObjectContext -> obj -> f a -> a
getImplicit' ObjectContext
ctx obj
symbObj (f ℝ
p forall a. Num a => a -> a -> a
- f ℝ
v)
getImplicitShared ObjectContext
ctx (Scale f ℝ
s obj
symbObj) = \f ℝ
p ->
  forall (f :: * -> *). (VectorStuff (f ℝ), Metric f) => f ℝ -> ℝ
normalize f ℝ
s forall a. Num a => a -> a -> a
* forall obj (f :: * -> *) a.
Object obj f a =>
ObjectContext -> obj -> f a -> a
getImplicit' ObjectContext
ctx obj
symbObj (f ℝ
p forall a. ComponentWiseMultable a => a -> a -> a
⋯/ f ℝ
s)
getImplicitShared ObjectContext
ctx (Mirror f ℝ
v obj
symbObj) =
    forall obj (f :: * -> *) a.
Object obj f a =>
ObjectContext -> obj -> f a -> a
getImplicit' ObjectContext
ctx obj
symbObj forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: * -> *) a.
(Num (f a), Fractional a, Metric f) =>
f a -> f a -> f a
reflect f ℝ
v
-- Boundary mods
getImplicitShared ObjectContext
ctx (Shell w obj
symbObj) = \f ℝ
p ->
  forall a. Num a => a -> a
abs (forall obj (f :: * -> *) a.
Object obj f a =>
ObjectContext -> obj -> f a -> a
getImplicit' ObjectContext
ctx obj
symbObj f ℝ
p) forall a. Num a => a -> a -> a
- wforall a. Fractional a => a -> a -> a
/2
getImplicitShared ObjectContext
ctx (Outset d obj
symbObj) = \f ℝ
p ->
  forall obj (f :: * -> *) a.
Object obj f a =>
ObjectContext -> obj -> f a -> a
getImplicit' ObjectContext
ctx obj
symbObj f ℝ
p forall a. Num a => a -> a -> a
- d
-- Misc
getImplicitShared ObjectContext
_ (EmbedBoxedObj (f ℝ -> ℝ
obj,(f ℝ, f ℝ)
_)) = f ℝ -> ℝ
obj
getImplicitShared ObjectContext
ctx (WithRounding r obj
obj) = forall obj (f :: * -> *) a.
Object obj f a =>
ObjectContext -> obj -> f a -> a
getImplicit' (ObjectContext
ctx { objectRounding :: ℝ
objectRounding = r }) obj
obj