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

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ViewPatterns #-}

module Graphics.Implicit.Export.Resolution (estimateResolution) where

import Prelude (min, minimum, sqrt, ($), (*), (**), (-), (/), (>))
import Data.Maybe (Maybe (Just), fromMaybe)
import Graphics.Implicit (unionR)
import Graphics.Implicit.Definitions (SymbolicObj2, SymbolicObj3, )
import Graphics.Implicit.ExtOpenScad.Definitions (Message, OVal (ONum), VarLookup, lookupVarIn)
import Graphics.Implicit.Primitives (Object (getBox))
import Linear (V2 (V2), V3 (V3))
import Linear.Affine ((.-.))

-- | Find the resolution to raytrace at.
estimateResolution :: (VarLookup, [SymbolicObj2], [SymbolicObj3], [Message]) -> 
estimateResolution :: (VarLookup, [SymbolicObj2], [SymbolicObj3], [Message]) -> ℝ
estimateResolution (Text -> VarLookup -> Maybe OVal
lookupVarIn Text
"$res" -> Just (ONum res), [SymbolicObj2]
_, [SymbolicObj3]
_, [Message]
_) =
    -- If specified, use a resolution specified by the "$res" a variable in the input file.
    res
estimateResolution (VarLookup
vars, [SymbolicObj2]
_, SymbolicObj3
obj:[SymbolicObj3]
objs, [Message]
_) =
    -- If there was no resolution specified, use a resolution chosen for 3D objects.
    -- FIXME: magic numbers.
    let
        (V3 x1 y1 z1, V3 x2 y2 z2) = forall obj (f :: * -> *) a. Object obj f a => obj -> (f a, f a)
getBox (forall obj (f :: * -> *) a. Object obj f a => ℝ -> [obj] -> obj
unionR 0 (SymbolicObj3
objforall a. a -> [a] -> [a]
:[SymbolicObj3]
objs))
        (V3 x y z) = forall a. a -> a -> a -> V3 a
V3 (x2forall a. Num a => a -> a -> a
-x1) (y2forall a. Num a => a -> a -> a
-y1) (z2forall a. Num a => a -> a -> a
-z1)
    in case forall a. a -> Maybe a -> a
fromMaybe (ℝ -> OVal
ONum 1) forall a b. (a -> b) -> a -> b
$ Text -> VarLookup -> Maybe OVal
lookupVarIn Text
"$quality" VarLookup
vars of
        ONum qual | qual forall a. Ord a => a -> a -> Bool
> 0  -> forall a. Ord a => a -> a -> a
min (forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
minimum [x,y,z]forall a. Fractional a => a -> a -> a
/2) ((xforall a. Num a => a -> a -> a
*yforall a. Num a => a -> a -> a
*zforall a. Fractional a => a -> a -> a
/qual)forall a. Floating a => a -> a -> a
**(1forall a. Fractional a => a -> a -> a
/3) forall a. Fractional a => a -> a -> a
/ 22)
        OVal
_                     -> forall a. Ord a => a -> a -> a
min (forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
minimum [x,y,z]forall a. Fractional a => a -> a -> a
/2) ((xforall a. Num a => a -> a -> a
*yforall a. Num a => a -> a -> a
*z)forall a. Floating a => a -> a -> a
**(1forall a. Fractional a => a -> a -> a
/3) forall a. Fractional a => a -> a -> a
/ 22)
estimateResolution (VarLookup
vars, SymbolicObj2
obj:[SymbolicObj2]
objs, [SymbolicObj3]
_, [Message]
_) =
    -- ... Or use a resolution chosen for 2D objects.
    --   FIXME: magic numbers.
    let
        (V2 ℝ
p1,V2 ℝ
p2) = forall obj (f :: * -> *) a. Object obj f a => obj -> (f a, f a)
getBox (forall obj (f :: * -> *) a. Object obj f a => ℝ -> [obj] -> obj
unionR 0 (SymbolicObj2
objforall a. a -> [a] -> [a]
:[SymbolicObj2]
objs))
        (V2 x y) = V2 ℝ
p2 forall (p :: * -> *) a. (Affine p, Num a) => p a -> p a -> Diff p a
.-. V2 ℝ
p1
    in case forall a. a -> Maybe a -> a
fromMaybe (ℝ -> OVal
ONum 1) forall a b. (a -> b) -> a -> b
$ Text -> VarLookup -> Maybe OVal
lookupVarIn Text
"$quality" VarLookup
vars of
        ONum qual | qual forall a. Ord a => a -> a -> Bool
> 0 -> forall a. Ord a => a -> a -> a
min (forall a. Ord a => a -> a -> a
min x yforall a. Fractional a => a -> a -> a
/2) (forall a. Floating a => a -> a
sqrt(xforall a. Num a => a -> a -> a
*yforall a. Fractional a => a -> a -> a
/qual) forall a. Fractional a => a -> a -> a
/ 30)
        OVal
_                    -> forall a. Ord a => a -> a -> a
min (forall a. Ord a => a -> a -> a
min x yforall a. Fractional a => a -> a -> a
/2) (forall a. Floating a => a -> a
sqrt(xforall a. Num a => a -> a -> a
*y) forall a. Fractional a => a -> a -> a
/ 30)
estimateResolution (VarLookup, [SymbolicObj2], [SymbolicObj3], [Message])
_ =
    -- fallthrough value.
    1