Created
May 18, 2016 17:53
-
-
Save jFransham/668e1a8943975b6a3bbbfd1c92c0854d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use ::set::Set; | |
use std::convert::TryFrom; | |
use std::ops::Add; | |
use sdl2::rect::Rect as SdlRect; | |
use num::Num; | |
pub type Bounds = Rectangle<f64>; | |
pub type Clip = Rectangle<u32>; | |
#[derive(Clone, Copy, Debug, PartialEq)] | |
pub struct Rectangle<P, S=P> { | |
pub x: P, | |
pub y: P, | |
pub width: S, | |
pub height: S, | |
} | |
impl<P: Clone, S: Clone> Rectangle<P, S> { | |
pub fn with_position(&self, x: P, y: P) -> Self { | |
Rectangle { | |
x: x, | |
y: y, | |
.. self.clone() | |
} | |
} | |
pub fn with_size(&self, w: S, h: S) -> Self { | |
Rectangle { | |
width: w, | |
height: h, | |
.. self.clone() | |
} | |
} | |
} | |
impl<O, P: Copy + Add<S, Output=O>, S: Copy> Rectangle<P, S> { | |
pub fn left(&self) -> P { self.x } | |
pub fn right(&self) -> O { self.x + self.width } | |
pub fn top(&self) -> P { self.y } | |
pub fn bottom(&self) -> O { self.y + self.height } | |
} | |
trait MinMax { | |
fn min(self, other: Self) -> Self; | |
fn max(self, other: Self) -> Self; | |
} | |
impl<T: PartialOrd> MinMax for T { | |
fn min(self, other: Self) -> Self { | |
if self < other { | |
self | |
} else { | |
other | |
} | |
} | |
fn max(self, other: Self) -> Self { | |
if self > other { | |
self | |
} else { | |
other | |
} | |
} | |
} | |
impl<T: Num + PartialOrd + Copy> Rectangle<T> { | |
pub fn clip_inside(&self, boundary: &Self) -> Option<Self> { | |
if self.width > boundary.width || self.height > boundary.height { | |
None | |
} else { | |
Some( | |
Rectangle { | |
x: self.x | |
.max(boundary.x) | |
.min(boundary.right() - self.width), | |
y: self.y | |
.max(boundary.y) | |
.min(boundary.bottom() - self.height), | |
width: self.width, | |
height: self.height, | |
} | |
) | |
} | |
} | |
} | |
impl Default for Bounds { | |
fn default() -> Self { | |
use std::f64; | |
Bounds { | |
x: 0.0, | |
y: 0.0, | |
width: f64::NAN, | |
height: f64::NAN, | |
} | |
} | |
} | |
impl<P: Default, S: Default> Default for Rectangle<P, S> { | |
default fn default() -> Self { | |
Rectangle { | |
x: Default::default(), | |
y: Default::default(), | |
width: Default::default(), | |
height: Default::default(), | |
} | |
} | |
} | |
impl Set for Bounds { | |
fn union(&self, other: &Self) -> Self { | |
let (x, y) = ( | |
self.x.min(other.x), | |
self.y.min(other.y), | |
); | |
Bounds { | |
x: x, | |
y: y, | |
width: self.right().max(other.right()) - x, | |
height: self.bottom().max(other.bottom()) - y, | |
} | |
} | |
fn intersection(&self, other: &Self) -> Option<Self> { | |
let (x, y) = ( | |
self.x.max(other.x), | |
self.y.max(other.y), | |
); | |
let (w, h) = ( | |
self.right().min(other.right()) - x, | |
self.bottom().min(other.bottom()) - y, | |
); | |
if w > 0.0 && h > 0.0 { | |
Some( | |
Bounds { | |
x: x, | |
y: y, | |
width: w, | |
height: h, | |
} | |
) | |
} else { | |
None | |
} | |
} | |
fn contains(&self, subset: &Self) -> bool { | |
subset.left() >= self.left() && | |
subset.right() <= self.right() && | |
subset.top() >= self.top() && | |
subset.bottom() <= self.bottom() | |
} | |
} | |
impl TryFrom<Bounds> for SdlRect { | |
type Err = (); | |
fn try_from(bounds: Bounds) -> Result<SdlRect, ()> { | |
use std::i32::MAX as IMAX; | |
use std::u32::MAX as UMAX; | |
let (imax, umax) = (IMAX as f64, UMAX as f64); | |
if | |
bounds.x.abs() <= imax && | |
bounds.y.abs() <= imax && | |
bounds.width <= umax && | |
bounds.height <= umax && | |
bounds.width > 0.0 && | |
bounds.height > 0.0 | |
{ | |
Ok( | |
SdlRect::new( | |
bounds.x as _, | |
bounds.y as _, | |
bounds.width as _, | |
bounds.height as _ | |
) | |
) | |
} else { | |
Err(()) | |
} | |
} | |
} | |
impl From<Clip> for SdlRect { | |
fn from(clip: Clip) -> SdlRect { | |
SdlRect::new( | |
clip.x as _, | |
clip.y as _, | |
clip.width, | |
clip.height | |
) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment