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

-- This file symbolicaly renders contours and contour fillings.
-- If it can't, it passes the puck to a marching-squares-like
-- algorithm...

module Graphics.Implicit.Export.SymbolicObj2 (symbolicGetContour) where

import Prelude((==), pure, fmap, ($), (/), (+), (*), cos, pi, sin, max, ceiling)

import Graphics.Implicit.Definitions (objectRounding, ObjectContext, , ℝ2, Fastℕ, SymbolicObj2(Square, Circle, Shared2), SharedObj(Translate, Scale, WithRounding), Polyline(Polyline), (⋯*), fromFastℕtoℝ)

import Linear ( V2(V2) )

import Graphics.Implicit.Export.Render (getContour)

symbolicGetContour ::  -> ObjectContext ->  SymbolicObj2 -> [Polyline]
symbolicGetContour :: ℝ -> ObjectContext -> SymbolicObj2 -> [Polyline]
symbolicGetContour _ ObjectContext
ctx (Square (V2 dx dy))
  | ObjectContext -> ℝ
objectRounding ObjectContext
ctx forall a. Eq a => a -> a -> Bool
== 0 = [[V2 ℝ] -> Polyline
Polyline [forall a. a -> a -> V2 a
V2 0 0, forall a. a -> a -> V2 a
V2 dx 0, forall a. a -> a -> V2 a
V2 dx dy, forall a. a -> a -> V2 a
V2 0 dy, forall a. a -> a -> V2 a
V2 0 0]]
-- FIXME: magic number.
symbolicGetContour res ObjectContext
_ (Circle r) =
  [ [V2 ℝ] -> Polyline
Polyline
    [ forall a. a -> a -> V2 a
V2 (rforall a. Num a => a -> a -> a
*forall a. Floating a => a -> a
cos(2forall a. Num a => a -> a -> a
*forall a. Floating a => a
piforall a. Num a => a -> a -> a
*Fastℕ -> ℝ
fromFastℕtoℝ Fastℕ
mforall a. Fractional a => a -> a -> a
/Fastℕ -> ℝ
fromFastℕtoℝ Fastℕ
n)) (rforall a. Num a => a -> a -> a
*forall a. Floating a => a -> a
sin(2forall a. Num a => a -> a -> a
*forall a. Floating a => a
piforall a. Num a => a -> a -> a
*Fastℕ -> ℝ
fromFastℕtoℝ Fastℕ
mforall a. Fractional a => a -> a -> a
/Fastℕ -> ℝ
fromFastℕtoℝ Fastℕ
n))
    | Fastℕ
m <- [Fastℕ
0.. Fastℕ
n]
    ]
  ]
  where
    n :: Fastℕ
    n :: Fastℕ
n = forall a. Ord a => a -> a -> a
max Fastℕ
5 forall a b. (a -> b) -> a -> b
$ forall a b. (RealFrac a, Integral b) => a -> b
ceiling forall a b. (a -> b) -> a -> b
$ 2forall a. Num a => a -> a -> a
*forall a. Floating a => a
piforall a. Num a => a -> a -> a
*rforall a. Fractional a => a -> a -> a
/res
symbolicGetContour res ObjectContext
ctx (Shared2 (WithRounding r SymbolicObj2
obj)) = ℝ -> ObjectContext -> SymbolicObj2 -> [Polyline]
symbolicGetContour res (ObjectContext
ctx { objectRounding :: ℝ
objectRounding = r }) SymbolicObj2
obj
symbolicGetContour res ObjectContext
ctx (Shared2 (Translate V2 ℝ
v SymbolicObj2
obj)) = (V2 ℝ -> V2 ℝ) -> [Polyline] -> [Polyline]
appOpPolylines (forall a. Num a => a -> a -> a
+ V2 ℝ
v) forall a b. (a -> b) -> a -> b
$ ℝ -> ObjectContext -> SymbolicObj2 -> [Polyline]
symbolicGetContour res ObjectContext
ctx SymbolicObj2
obj
symbolicGetContour res ObjectContext
ctx (Shared2 (Scale s :: V2 ℝ
s@(V2 a b) SymbolicObj2
obj)) = (V2 ℝ -> V2 ℝ) -> [Polyline] -> [Polyline]
appOpPolylines (forall a. ComponentWiseMultable a => a -> a -> a
⋯* V2 ℝ
s) forall a b. (a -> b) -> a -> b
$ ℝ -> ObjectContext -> SymbolicObj2 -> [Polyline]
symbolicGetContour (resforall a. Fractional a => a -> a -> a
/sc) ObjectContext
ctx SymbolicObj2
obj
    where sc :: ℝ
sc = forall a. Ord a => a -> a -> a
max a b
symbolicGetContour res ObjectContext
_ SymbolicObj2
obj = V2 ℝ -> SymbolicObj2 -> [Polyline]
getContour (forall (f :: * -> *) a. Applicative f => a -> f a
pure res) SymbolicObj2
obj

appOpPolylines :: (ℝ2 -> ℝ2) -> [Polyline] -> [Polyline]
appOpPolylines :: (V2 ℝ -> V2 ℝ) -> [Polyline] -> [Polyline]
appOpPolylines V2 ℝ -> V2 ℝ
op = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((V2 ℝ -> V2 ℝ) -> Polyline -> Polyline
appOpPolyline V2 ℝ -> V2 ℝ
op)
appOpPolyline :: (ℝ2 -> ℝ2) -> Polyline -> Polyline
appOpPolyline :: (V2 ℝ -> V2 ℝ) -> Polyline -> Polyline
appOpPolyline V2 ℝ -> V2 ℝ
op (Polyline [V2 ℝ]
xs) = [V2 ℝ] -> Polyline
Polyline forall a b. (a -> b) -> a -> b
$ forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap V2 ℝ -> V2 ℝ
op [V2 ℝ]
xs