implicit-0.0.0: Graphics/Implicit/Operations.hs
-- Implicit CAD. Copyright (C) 2011, Christopher Olah (chris@colah.ca)
-- Released under the GNU GPL, see LICENSE
{-# LANGUAGE FlexibleInstances, FlexibleContexts #-}
module Graphics.Implicit.Operations (
translate,
scale,
complement,
union, intersect, difference,
unionR, intersectR, differenceR,
shell,
slice,
bubble,
extrude,
extrudeR,
extrudeOnEdgeOf
) where
import Prelude hiding ((+),(-),(*),(/))
import Graphics.Implicit.Definitions
import Graphics.Implicit.MathUtil
import Graphics.Implicit.SaneOperators
-- | Translate an object by a vector of appropriate dimension.
translate ::
(Additive a a a, AdditiveInvertable a)
=> a -- ^ Vector to translate by (Also: a is a vector, blah, blah)
-> (a -> ℝ) -- ^ Object to translate
-> (a -> ℝ) -- ^ Resulting object
translate p obj = \q -> obj (q-p)
-- | Scale an object
scale :: (Multiplicative a ℝ a) =>
ℝ -- ^ Amount to scale by
-> (a -> ℝ) -- ^ Object to scale
-> (a -> ℝ) -- ^ Resulting scaled object
scale s obj = \p -> s * obj (p/s)
complement ::
(a -> ℝ) -- ^ Object to complement
-> (a -> ℝ) -- ^ Result
complement obj = \p -> - obj p
shell ::
ℝ -- ^ width of shell
-> (a -> ℝ) -- ^ object to take shell of
-> (a -> ℝ) -- ^ resulting shell
shell w a = \p -> abs (a p) - w/(2.0::ℝ)
-- | Rounded union
unionR ::
ℝ -- ^ The radius of rounding
-> [a -> ℝ] -- ^ objects to union
-> (a -> ℝ) -- ^ Resulting object
unionR r objs = \p -> rminimum r $ map ($p) objs
-- | Rounded minimum
intersectR ::
ℝ -- ^ The radius of rounding
-> [a -> ℝ] -- ^ Objects to intersect
-> (a -> ℝ) -- ^ Resulting object
intersectR r objs = \p -> rmaximum r $ map ($p) objs
-- | Rounded difference
differenceR ::
ℝ -- ^ The radius of rounding
-> [a -> ℝ] -- ^ Objects to difference
-> (a -> ℝ) -- ^ Resulting object
differenceR r (x:xs) = \p -> rmaximum r $ (x p) :(map (negate . ($p)) xs)
-- | Union a list of objects
union ::
[a -> ℝ] -- ^ List of objects to union
-> (a -> ℝ) -- ^ The object resulting from the union
union objs = \p -> minimum $ map ($p) objs
-- | Intersect a list of objects
intersect ::
[a -> ℝ] -- ^ List of objects to intersect
-> (a -> ℝ) -- ^ The object resulting from the intersection
intersect objs = \p -> maximum $ map ($p) objs
-- | Difference a list of objects
difference ::
[a -> ℝ] -- ^ List of objects to difference
-> (a -> ℝ) -- ^ The object resulting from the difference
difference (obj:objs) = \p -> maximum $ map ($p) $ obj:(map complement objs)
-- | Slice a 3D objects at a given z value to make a 2D object.
slice ::
ℝ -- ^ z-level to cut at
-> Obj3 -- ^ 3D object to slice from
-> Obj2 -- ^ Resulting 2D object
slice z obj = \(a,b) -> obj (a,b,z)
-- | Bubble out a 2D object into a 3D one.
bubble :: ℝ -> Obj2 -> Obj3
bubble s obj =
let
spsqrt n = signum n * sqrt (abs n)
spsq n = signum n * n ** 2
in
\(x,y,z) -> spsqrt ( z ** 2 + s * obj (x,y) )
-- | Extrude a 2D object. (The extrusion goes into the z-plane)
extrude ::
ℝ -- ^ Length to extrude
-> Obj2 -- ^ 2D object to extrude
-> Obj3 -- ^ Resulting 3D object
extrude h obj = \(x,y,z) -> max (obj (x,y)) (abs (z + h/(2.0 :: ℝ )) - h)
-- | Rounded extrude. Instead of the extrude having a flat top or bottom, it is bevelled.
extrudeR ::
ℝ -- ^ Radius of rounding
-> ℝ -- ^ Length to extrude
-> Obj2 -- ^ 2D object to extrude
-> Obj3 -- ^ Resulting 3D object
extrudeR r h obj = \(x,y,z) -> rmax r (obj (x,y)) (abs (z + h/(2.0 :: ℝ)) - h)
-- | Create a 3D object by extruding a 2D object along the edge of another 2D object.
-- For example, extruding a circle on the edge of another circle would make a torus.
extrudeOnEdgeOf ::
Obj2 -- ^ Object to extrude
-> Obj2 -- ^ Object to extrude along the edge of
-> Obj3 -- ^ Resulting 3D object
extrudeOnEdgeOf a b = \(x,y,z) -> a (b (x,y), z)