#[cfg(feature="serde")]
use serde::{Deserialize, Serialize};
use super::{Coordinate, Dimensions};
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(Clone, Eq, Debug, Default, PartialEq)]
pub struct Rectangle {
pub coordinate : Coordinate,
pub dimensions : Dimensions
}
impl Rectangle {
#[inline]
pub const fn width (&self) -> usize {
self.dimensions.columns
}
#[inline]
pub const fn height (&self) -> usize {
self.dimensions.rows
}
#[inline]
pub const fn min (&self) -> Coordinate {
self.coordinate
}
#[inline]
pub const fn max (&self) -> Coordinate {
Coordinate {
row: self.coordinate.row + self.height() - 1,
column: self.coordinate.column + self.width() - 1,
}
}
#[inline]
pub const fn upper_left (&self) -> Coordinate {
self.min()
}
#[inline]
pub const fn upper_right (&self) -> Coordinate {
Coordinate {
row: self.min().row,
column: self.max().column
}
}
#[inline]
pub const fn lower_right (&self) -> Coordinate {
self.max()
}
#[inline]
pub const fn lower_left (&self) -> Coordinate {
Coordinate {
row: self.max().row,
column: self.min().column
}
}
#[inline]
pub fn row (&self, row : usize) -> Option <Self> {
if row < self.height() {
let coordinate = self.min() + (row, 0).into();
let dimensions = (1, self.width()).into();
Some (Rectangle { coordinate, dimensions })
} else {
None
}
}
#[inline]
pub fn column (&self, column : usize) -> Option <Self> {
if column < self.width() {
let coordinate = self.min() + (0, column).into();
let dimensions = (self.height(), 1).into();
Some (Rectangle { coordinate, dimensions })
} else {
None
}
}
#[inline]
pub const fn area (&self) -> usize {
self.height() * self.width()
}
#[inline]
pub fn contains (&self, Coordinate { row, column } : Coordinate) -> bool {
self.contains_rc (row, column)
}
#[inline]
pub fn contains_rc (&self, row : usize, column : usize) -> bool {
self.min().row <= row && row <= self.max().row &&
self.min().column <= column && column <= self.max().column
}
#[inline]
pub fn iter (&self) -> impl Iterator <Item = Coordinate> {
let row = self.min().row;
let col = self.min().column;
let height = self.height();
let width = self.width();
(row..row + height).map (move |row| std::iter::repeat (row)
.zip (col..col + width)).flatten().map (Into::into)
}
} impl From <(Coordinate, Dimensions)> for Rectangle {
fn from ((coordinate, dimensions) : (Coordinate, Dimensions)) -> Self {
Rectangle { coordinate, dimensions }
}
}
impl From <Dimensions> for Rectangle {
fn from (dimensions : Dimensions) -> Self {
Rectangle { coordinate: (0, 0).into(), dimensions }
}
}