-- | Representation of an axis-aligned rectangle on a 2D plane, with one of its
-- corners being a designated origin point.
module Data.Text.ParagraphLayout.Rect
(Rect(..)
,height
,union
,width
,x_max
,x_min
,x_terminus
,y_max
,y_min
,y_terminus
)
where
data Rect a = Rect { x_origin :: a, y_origin :: a, x_size :: a, y_size :: a }
deriving (Eq, Read, Show)
-- | Absolute difference between the X coordinates of the rectangle's sides.
width :: Num a => Rect a -> a
width r = abs $ x_size r
-- | Absolute difference between the Y coordinates of the rectangle's sides.
height :: Num a => Rect a -> a
height r = abs $ y_size r
-- | X coordinate of the corner opposite of the origin.
x_terminus :: Num a => Rect a -> a
x_terminus r = x_origin r + x_size r
-- | Y coordinate of the corner opposite of the origin.
y_terminus :: Num a => Rect a -> a
y_terminus r = y_origin r + y_size r
-- | The smaller of the two X coordinates of the rectangle's edges.
x_min :: (Num a, Ord a) => Rect a -> a
x_min r = x_origin r `min` x_terminus r
-- | The smaller of the two Y coordinates of the rectangle's edges.
y_min :: (Num a, Ord a) => Rect a -> a
y_min r = y_origin r `min` y_terminus r
-- | The larger of the two X coordinates of the rectangle's edges.
x_max :: (Num a, Ord a) => Rect a -> a
x_max r = x_origin r `max` x_terminus r
-- | The larger of the two Y coordinates of the rectangle's edges.
y_max :: (Num a, Ord a) => Rect a -> a
y_max r = y_origin r `max` y_terminus r
-- | Calculate the smallest rectangle that completely contains the given two
-- rectangles.
--
-- The origin of the resulting rectangle will be the corner with the lowest
-- X and Y coordinates, regardless of the origin of the input rectangles.
union :: (Num a, Ord a) => Rect a -> Rect a -> Rect a
union a b = Rect x1 y1 dx dy where
x1 = x_min a `min` x_min b
y1 = y_min a `min` y_min b
x2 = x_max a `max` x_max b
y2 = y_max a `max` y_max b
dx = x2 - x1
dy = y2 - y1
instance (Num a, Ord a) => Semigroup (Rect a) where
(<>) = union