{- 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) = SymbolicObj3 -> (V3 ℝ, V3 ℝ)
forall obj (f :: * -> *) a. Object obj f a => obj -> (f a, f a)
getBox (ℝ -> [SymbolicObj3] -> SymbolicObj3
forall obj (f :: * -> *) a. Object obj f a => ℝ -> [obj] -> obj
unionR 0 (SymbolicObj3
objSymbolicObj3 -> [SymbolicObj3] -> [SymbolicObj3]
forall a. a -> [a] -> [a]
:[SymbolicObj3]
objs))
        (V3 x y z) = ℝ -> ℝ -> ℝ -> V3 ℝ
forall a. a -> a -> a -> V3 a
V3 (x2ℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
-x1) (y2ℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
-y1) (z2ℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
-z1)
    in case OVal -> Maybe OVal -> OVal
forall a. a -> Maybe a -> a
fromMaybe (ℝ -> OVal
ONum 1) (Maybe OVal -> OVal) -> Maybe OVal -> OVal
forall a b. (a -> b) -> a -> b
$ Text -> VarLookup -> Maybe OVal
lookupVarIn Text
"$quality" VarLookup
vars of
        ONum qual | qual ℝ -> ℝ -> Bool
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) ((xℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
*yℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
*zℝ -> ℝ -> ℝ
forall a. Fractional a => a -> a -> a
/qual)ℝ -> ℝ -> ℝ
forall a. Floating a => a -> a -> a
**(1ℝ -> ℝ -> ℝ
forall 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) ((xℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
*yℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
*z)ℝ -> ℝ -> ℝ
forall a. Floating a => a -> a -> a
**(1ℝ -> ℝ -> ℝ
forall 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) = SymbolicObj2 -> (V2 ℝ, V2 ℝ)
forall obj (f :: * -> *) a. Object obj f a => obj -> (f a, f a)
getBox (ℝ -> [SymbolicObj2] -> SymbolicObj2
forall obj (f :: * -> *) a. Object obj f a => ℝ -> [obj] -> obj
unionR 0 (SymbolicObj2
objSymbolicObj2 -> [SymbolicObj2] -> [SymbolicObj2]
forall a. a -> [a] -> [a]
:[SymbolicObj2]
objs))
        (V2 x y) = V2 ℝ
p2 V2 ℝ -> V2 ℝ -> Diff V2 ℝ
forall (p :: * -> *) a. (Affine p, Num a) => p a -> p a -> Diff p a
.-. V2 ℝ
p1
    in case OVal -> Maybe OVal -> OVal
forall a. a -> Maybe a -> a
fromMaybe (ℝ -> OVal
ONum 1) (Maybe OVal -> OVal) -> Maybe OVal -> OVal
forall a b. (a -> b) -> a -> b
$ Text -> VarLookup -> Maybe OVal
lookupVarIn Text
"$quality" VarLookup
vars of
        ONum qual | qual ℝ -> ℝ -> Bool
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 yℝ -> ℝ -> ℝ
forall a. Fractional a => a -> a -> a
/2) (ℝ -> ℝ
forall a. Floating a => a -> a
sqrt(xℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
*yℝ -> ℝ -> ℝ
forall 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 yℝ -> ℝ -> ℝ
forall a. Fractional a => a -> a -> a
/2) (ℝ -> ℝ
forall a. Floating a => a -> a
sqrt(xℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
*y) ℝ -> ℝ -> ℝ
forall a. Fractional a => a -> a -> a
/ 30)
estimateResolution (VarLookup, [SymbolicObj2], [SymbolicObj3], [Message])
_ =
    -- fallthrough value.
    1