\section{Bounding Boxes} Implements simple bounding boxes and spheres. \begin{code} module RSAGL.Modeling.BoundingBox (BoundingBox, Bound3D(..), boundingCenterRadius, minimalDistanceToBoundingBox) where import RSAGL.Math.Vector import RSAGL.Math.Interpolation import RSAGL.Math.Affine import RSAGL.Types data BoundingBox = BoundingBox { bbox_bottom, bbox_top, bbox_left, bbox_right, bbox_far, bbox_near :: !RSdouble } deriving (Show) class Bound3D a where boundingBox :: a -> BoundingBox instance Bound3D Point3D where boundingBox (Point3D x y z) = BoundingBox { bbox_bottom = y, bbox_top = y, bbox_right = x, bbox_left = x, bbox_near = z, bbox_far = z } instance Bound3D SurfaceVertex3D where boundingBox = boundingBox . sv3d_position instance (Bound3D a) => Bound3D [a] where boundingBox [] = error "instance Bound3D [a], boundingBox: can't construct boundingBox []" boundingBox (x:xs) = foldr combineBoundingBoxes (boundingBox x) $ xs instance Bound3D BoundingBox where boundingBox = id instance AffineTransformable BoundingBox where transform m = boundingBox . transform m . boundingBoxToPointCloud combineBoundingBoxes :: (Bound3D a,Bound3D b) => a -> b -> BoundingBox combineBoundingBoxes x y = BoundingBox { bbox_left = min (bbox_left b1) (bbox_left b2), bbox_right = max (bbox_right b1) (bbox_right b2), bbox_bottom = min (bbox_bottom b1) (bbox_bottom b2), bbox_top = max (bbox_top b1) (bbox_top b2), bbox_near = min (bbox_near b1) (bbox_near b2), bbox_far = max (bbox_far b1) (bbox_far b2) } where b1 = boundingBox x b2 = boundingBox y boundingBoxToPointCloud :: BoundingBox -> [Point3D] boundingBoxToPointCloud bbox = [Point3D (bbox_left bbox) (bbox_bottom bbox) (bbox_near bbox), Point3D (bbox_right bbox) (bbox_bottom bbox) (bbox_near bbox), Point3D (bbox_left bbox) (bbox_top bbox) (bbox_near bbox), Point3D (bbox_right bbox) (bbox_top bbox) (bbox_near bbox), Point3D (bbox_left bbox) (bbox_bottom bbox) (bbox_far bbox), Point3D (bbox_right bbox) (bbox_bottom bbox) (bbox_far bbox), Point3D (bbox_left bbox) (bbox_top bbox) (bbox_far bbox), Point3D (bbox_right bbox) (bbox_top bbox) (bbox_far bbox)] boundingCenterRadius :: BoundingBox -> (Point3D,RSdouble) boundingCenterRadius bbox = (lerp 0.5 (nlb,frt),distanceBetween nlb frt / 2) where nlb = Point3D (bbox_near bbox) (bbox_left bbox) (bbox_bottom bbox) frt = Point3D (bbox_far bbox) (bbox_right bbox) (bbox_top bbox) minimalDistanceToBoundingBox :: Point3D -> BoundingBox -> RSdouble minimalDistanceToBoundingBox p bbox = distanceBetween p c - r where (c,r) = boundingCenterRadius bbox \end{code}