packages feed

implicit-0.0.2: Graphics/Implicit/ObjectUtil/GetBox3.hs

-- Implicit CAD. Copyright (C) 2011, Christopher Olah (chris@colah.ca)
-- Released under the GNU GPL, see LICENSE

{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances, FlexibleContexts, TypeSynonymInstances, UndecidableInstances #-}

module Graphics.Implicit.ObjectUtil.GetBox3 (getBox3) where

import Prelude hiding ((+),(-),(*),(/))
import Graphics.Implicit.SaneOperators
import Graphics.Implicit.Definitions
import qualified Graphics.Implicit.MathUtil as MathUtil
import Data.Maybe (fromMaybe)

import  Graphics.Implicit.ObjectUtil.GetBox2 (getBox2)

getBox3 :: SymbolicObj3 -> Box3

-- Primitives
getBox3 (Rect3R r a b) = (a,b)

getBox3 (Sphere r ) = ((-r, -r, -r), (r,r,r))

getBox3 (Cylinder h r1 r2) = ( (-r,-r,0), (r,r,h) ) where r = max r1 r2

-- (Rounded) CSG
getBox3 (Complement3 symbObj) = 
	((-infty, -infty, -infty), (infty, infty, infty)) where infty = (1::ℝ)/(0 ::ℝ)

getBox3 (UnionR3 r symbObjs) = ((left-r,bot-r,inward-r), (right+r,top+r,out+r))
	where 
		boxes = map getBox3 symbObjs
		isEmpty = ( == ((0,0,0),(0,0,0)) )
		(leftbot, topright) = unzip $ filter (not.isEmpty) boxes
		(lefts, bots, ins) = unzip3 leftbot
		(rights, tops, outs) = unzip3 topright
		left = minimum lefts
		bot = minimum bots
		inward = minimum ins
		right = maximum rights
		top = maximum tops
		out = maximum outs

getBox3 (IntersectR3 r symbObjs) = 
	let 
		boxes = map getBox3 symbObjs
		(leftbot, topright) = unzip boxes
		(lefts, bots, ins) = unzip3 leftbot
		(rights, tops, outs) = unzip3 topright
		left = maximum lefts
		bot = maximum bots
		inward = maximum ins
		right = minimum rights
		top = minimum tops
		out = minimum outs
	in
		if   top   > bot 
		  && right > left 
		  && out   > inward
		then ((left,bot,inward),(right,top,out))
		else ((0,0,0),(0,0,0))

getBox3 (DifferenceR3 r symbObjs) = firstBox
	where
		firstBox:_ = map getBox3 symbObjs

-- Simple transforms
getBox3 (Translate3 v symbObj) =
	let
		(a,b) = getBox3 symbObj
	in
		(a+v, b+v)

getBox3 (Scale3 s symbObj) =
	let
		(a,b) = getBox3 symbObj
	in
		(s ⋯* a, s ⋯* b)

getBox3 (Rotate3 _ symbObj) = ( (-d, -d, -d), (d, d, d) )
	where
		((x1,y1, z1), (x2,y2, z2)) = getBox3 symbObj
		d = (sqrt (2::ℝ) *) $ maximum $ map abs [x1, x2, y1, y2, z1, z2]

-- Boundary mods
getBox3 (Shell3 w symbObj) = 
	let
		(a,b) = getBox3 symbObj
		d = w/(2.0::ℝ)
	in
		(a - (d,d,d), b + (d,d,d))

getBox3 (Outset3 d symbObj) =
	let
		(a,b) = getBox3 symbObj
	in
		(a - (d,d,d), b + (d,d,d))

-- Misc
getBox3 (EmbedBoxedObj3 (obj,box)) = box

-- 2D Based
getBox3 (ExtrudeR r symbObj h) = ((x1,y1,0),(x2,y2,h))
	where
		((x1,y1),(x2,y2)) = getBox2 symbObj

getBox3 (ExtrudeOnEdgeOf symbObj1 symbObj2) =
	let
		((ax1,ay1),(ax2,ay2)) = getBox2 symbObj1
		((bx1,by1),(bx2,by2)) = getBox2 symbObj2
	in
		((bx1+ax1, by1+ax1, ay2), (bx2+ax2, by2+ax2, ay2))


getBox3 (ExtrudeRM r twist scale translate symbObj (Left h)) = 
	let
		((x1,y1),(x2,y2)) = getBox2 symbObj
		dx = x2 - x1
		dy = y2 - y1
		svals =  map (fromMaybe (const 1) scale) $ [0,h/(2::ℝ),h]
		sval = maximum $ map abs $ svals
		d = sval * sqrt (dx^2 + dy^2)
		(tvalsx, tvalsy) = unzip $ map (fromMaybe (const (0,0)) translate) $ [0,h/(2::ℝ),h]
		(tminx, tminy) = (minimum tvalsx, minimum tvalsy)
		(tmaxx, tmaxy) = (maximum tvalsx, maximum tvalsy)
	in
		((-d+tminx, -d+tminy, 0),(d+tmaxx, d+tmaxy, h)) 

getBox3 (ExtrudeRM r twist scale translate symbObj (Right hf)) = 
	let
		((x1,y1),(x2,y2)) = getBox2 symbObj
		dx = x2 - x1
		dy = y2 - y1
		h = maximum [hf (x1,y1), hf (x2,y1), hf (x2,y2), hf (x1,y2), hf ((x1+x2)/(2::ℝ), (y1+y2)/(2::ℝ))]
		svals =  map (fromMaybe (const 1) scale) $ [0,h/(2::ℝ),h]
		sval = maximum $ map abs $ svals
		d = sval * sqrt (dx^2 + dy^2)
		(tvalsx, tvalsy) = unzip $ map (fromMaybe (const (0,0)) translate) $ [0,h/(2::ℝ),h]
		(tminx, tminy) = (minimum tvalsx, minimum tvalsy)
		(tmaxx, tmaxy) = (maximum tvalsx, maximum tvalsy)
	in
		((-d+tminx, -d+tminy, 0),(d+tmaxx, d+tmaxy, h))