{- | This module provides the 'BBox1' type (mainly for completeness). -} module Data.BoundingBox.B1 where import Data.Vector.Class import Data.Vector.V1 import qualified Data.BoundingBox.Range as R -- | The 'BBox1' type is basically a 'Range', but all the operations over it work with 'Vector1' (which is really 'Scalar'). While it's called a bounding /box/, a 1-dimensional box is in truth a simple line interval, just like 'Range'. newtype BBox1 = BBox1 {range :: R.Range} deriving (Eq, Show) -- | Given two vectors, construct a bounding box (swapping the endpoints if necessary). bound_corners :: Vector1 -> Vector1 -> BBox1 bound_corners (Vector1 xa) (Vector1 xb) = BBox1 $ R.bound_corners xa xb -- | Find the bounds of a list of points. (Throws an exception if the list is empty.) bound_points :: [Vector1] -> BBox1 bound_points = BBox1 . R.bound_points . map v1x -- | Test whether a 'Vector1' lies within a 'BBox1'. within_bounds :: Vector1 -> BBox1 -> Bool within_bounds (Vector1 x) (BBox1 r) = x `R.within_bounds` r -- | Return the minimum endpoint for a 'BBox1'. min_point :: BBox1 -> Vector1 min_point = Vector1 . R.min_point . range -- | Return the maximum endpoint for a 'BBox1'. max_point :: BBox1 -> Vector1 max_point = Vector1 . R.max_point . range -- | Take the union of two 'BBox1' values. The result is a new 'BBox1' that contains all the points the original boxes contained, plus any extra space between them. union :: BBox1 -> BBox1 -> BBox1 union (BBox1 r0) (BBox1 r1) = BBox1 (r0 `R.union` r1) -- | Take the intersection of two 'BBox1' values. If the boxes do not overlap, return 'Nothing'. Otherwise return a 'BBox1' containing only the points common to both argument boxes. isect :: BBox1 -> BBox1 -> Maybe BBox1 isect (BBox1 r0) (BBox1 r1) = do r <- (r0 `R.isect` r1) return (BBox1 r) -- | Efficiently compute the union of a list of bounding boxes. unions :: [BBox1] -> BBox1 unions = BBox1 . R.unions . map range