extern crate num;
use num::traits::*;
use std::ops::*;
use vector::*;
#[derive(Debug, Clone, Copy, PartialEq)]
#[repr(C)]
pub struct Point<T> {
pub x:T,
pub y:T }
pub type Pointf = Point<f32>;
pub type Pointi = Point<i32>;
impl<T:Copy> Point<T> {
pub fn new(x:T, y:T ) -> Point<T> {
Point{ x:x, y:y }
}
pub fn new_s(s:T ) -> Point<T> {
Point{ x:s, y:s }
}
pub fn new_v2(v:Vector2<T> ) -> Point<T> {
Point{ x:v.x, y:v.y }
}
pub fn new_v3(v:Vector3<T> ) -> Point<T> {
Point{ x:v.x, y:v.y }
}
pub fn new_v4(v:Vector4<T> ) -> Point<T> {
Point{ x:v.x, y:v.y }
}
pub fn v2_cast(self) -> Vector2<T> {
Vector2{ x:self.x, y:self.y}
}
}
impl<T:Copy + Zero + One> Default for Point<T> {
fn default() -> Point<T> {
Point{ x:T::zero(),
y:T::zero() }
}
}
impl<T:Copy + Zero + PartialEq> Zero for Point<T> {
fn zero() -> Point<T> {
Point{ x:T::zero(),
y:T::zero() }
}
fn is_zero(&self) -> bool {
self.x == T::zero() &&
self.y == T::zero()
}
}
impl<T:Copy + Num> One for Point<T> {
fn one() -> Point<T> {
Point{ x: T::one(), y: T::one() }
}
}
impl<T:Add<Output = T> + Zero + Copy> Add<Point<T>> for Point<T> {
type Output = Point<T>;
fn add(self, rhs:Point<T>) -> Point<T> {
Point{ x:self.x + rhs.x,
y:self.y + rhs.y }
}
}
impl<T:Add<Output = T> + Zero + Copy> Add<Vector2<T>> for Point<T> {
type Output = Point<T>;
fn add(self, rhs:Vector2<T>) -> Point<T> {
Point{ x:self.x + rhs.x,
y:self.y + rhs.y }
}
}
impl<T:Sub<Output = T> + Zero + Copy> Sub<Point<T>> for Point<T> {
type Output = Point<T>;
fn sub(self, rhs:Point<T>) -> Point<T> {
Point{ x:self.x - rhs.x,
y:self.y - rhs.y }
}
}
impl<T:Copy + Num> Mul<Point<T>> for Point<T> {
type Output = Point<T>;
fn mul(self, rhs:Point<T>) -> Point<T> {
Point{x: self.x * rhs.x,
y: self.y * rhs.y }
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
#[repr(C)]
pub struct Size<T> {
pub width:T,
pub height:T }
pub type Sizef = Size<f32>;
pub type Sizei = Size<i32>;
impl<T:Copy> Size<T> {
pub fn new(w:T, h:T ) -> Size<T> {
Size{ width:w, height:h }
}
pub fn new_s(s:T ) -> Size<T> {
Size{ width:s, height:s }
}
pub fn new_v2(v:Vector2<T> ) -> Size<T> {
Size{ width:v.x, height:v.y }
}
pub fn v2_cast(self) -> Vector2<T> {
Vector2{ x:self.width, y:self.height}
}
}
impl<T:Copy + Zero + One> Default for Size<T> {
fn default() -> Size<T> {
Size{ width: T::one(),
height: T::one() }
}
}
impl<T:Copy + Zero + PartialEq> Zero for Size<T> {
fn zero() -> Size<T> {
Size{ width: T::zero(),
height: T::zero() }
}
fn is_zero(&self) -> bool {
self.width == T::zero() &&
self.height == T::zero()
}
}
impl<T:Copy + Num> One for Size<T> {
fn one() -> Size<T> {
Size{ width: T::one(), height: T::one() }
}
}
impl<T:Add<Output = T> + Zero + Copy> Add<Size<T>> for Size<T> {
type Output = Size<T>;
fn add(self, rhs:Size<T>) -> Size<T> {
Size{ width: self.width + rhs.width,
height: self.height + rhs.height }
}
}
impl<T:Add<Output = T> + Zero + Copy> Add<Vector2<T>> for Size<T> {
type Output = Size<T>;
fn add(self, rhs:Vector2<T>) -> Size<T> {
Size{ width: self.width + rhs.x,
height: self.height + rhs.y }
}
}
impl<T:Sub<Output = T> + Zero + Copy> Sub<Size<T>> for Size<T> {
type Output = Size<T>;
fn sub(self, rhs:Size<T>) -> Size<T> {
Size{ width: self.width - rhs.width,
height: self.height - rhs.height }
}
}
impl<T:Copy + Num> Mul<Size<T>> for Size<T> {
type Output = Size<T>;
fn mul(self, rhs:Size<T>) -> Size<T> {
Size{width: self.width * rhs.width,
height: self.height * rhs.height }
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
#[repr(C)]
pub struct Rect<T> {
pub origin:Point<T>,
pub size:Size<T> }
pub type Rectf = Rect<f32>;
pub type Recti = Rect<i32>;
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum RectEdge {
MinX,
MinY,
MaxX,
MaxY
}
impl<T:Copy> Rect<T> {
pub fn new(x:T, y:T, w:T, h:T ) -> Rect<T> {
Rect{ origin: Point{x:x, y:y}, size: Size{width:w, height:h} }
}
pub fn new_ps(p:Point<T>, s:Size<T> ) -> Rect<T> {
Rect{ origin: p, size: s }
}
pub fn new_v4(v:Vector4<T> ) -> Rect<T> {
Rect{ origin: Point{x:v.x, y:v.y}, size: Size{width:v.z, height:v.w} }
}
pub fn v4_cast(self) -> Vector4<T> {
Vector4{ x:self.origin.x, y:self.origin.y, z:self.size.width, w:self.size.height}
}
}
impl<T:Copy + Num + Signed + PartialOrd> Rect<T> {
pub fn new_p(a:Point<T>, b:Point<T> ) -> Rect<T> {
Rect{ origin: a,
size: Size{width:b.x - a.x, height: b.y - a.y }}.standardize()
}
pub fn new_pp(x1:T, y1:T, x2:T, y2:T ) -> Rect<T> {
Rect{ origin: Point{x:x1, y:y1},
size: Size{width:x2 - x1, height: y2 - y1 }}.standardize()
}
pub fn min_x(self) -> T {
self.origin.x
}
pub fn max_x(self) -> T {
self.origin.x + self.size.width
}
pub fn min_y(self) -> T {
self.origin.y
}
pub fn max_y(self) -> T {
self.origin.y + self.size.height
}
pub fn min(self) -> Point<T> {
Point{ x:self.origin.x,
y:self.origin.y }
}
pub fn max(self) -> Point<T> {
Point{ x:self.origin.x + self.size.width,
y:self.origin.y + self.size.height }
}
pub fn mid_x(self) -> T {
let two = T::one() + T::one();
return self.origin.x + self.size.width / two;
}
pub fn mid_y(self) -> T {
let two = T::one() + T::one();
return self.origin.y + self.size.height / two;
}
pub fn mid(self) -> Point<T> {
let two = T::one() + T::one();
return Point{ x:self.origin.x + self.size.width / two,
y:self.origin.y + self.size.height / two }
}
pub fn standardize(self) -> Rect<T> {
let mut r = self;
if r.size.width < T::zero() {
r.origin.x = r.origin.x + r.size.width;
r.size.width = -r.size.width;
}
if r.size.height < T::zero() {
r.origin.y = r.origin.y + r.size.height;
r.size.height = -r.size.height;
}
return r;
}
pub fn is_empty(self) -> bool {
self.size.is_zero()
}
}
impl<T:Copy + Float + Signed> Rect<T> {
pub fn null() -> Rect<T> {
Rect{ origin: Point {x: Float::max_value(), y: Float::max_value()},
size: Size {width: T::zero(), height: T::zero()}}
}
pub fn is_null(self) -> bool {
return
self.origin.x == Float::max_value() &&
self.origin.y == Float::max_value() &&
self.size.width.is_zero() &&
self.size.height.is_zero();
}
pub fn infinite() -> Rect<T> {
Rect{ origin: Point {x: Float::infinity(), y: Float::infinity()},
size: Size {width: T::zero(), height: T::zero()}}
}
pub fn is_infinite(self) -> bool {
return
self.origin.x.is_infinite() ||
self.origin.y.is_infinite() ||
self.size.width.is_infinite() ||
self.size.height.is_infinite();
}
pub fn divide(self, amount:T, edge:RectEdge) -> (Rect<T>, Rect<T>) {
let rect = self.standardize();
let mut slice = rect;
let mut remainder = Rect::new(T::zero(), T::zero(), T::zero(), T::zero());
if ((edge == RectEdge::MinX || edge == RectEdge::MaxX) && amount > rect.size.width ) ||
((edge == RectEdge::MinY || edge == RectEdge::MaxY) && amount > rect.size.height) {
return (slice, remainder);
}
match edge {
RectEdge::MinX => {
slice.origin.x = rect.origin.x;
slice.origin.y = rect.origin.y;
slice.size.width = amount;
slice.size.height = rect.size.height;
remainder.origin.x = rect.origin.x + amount;
remainder.origin.y = rect.origin.y;
remainder.size.width = rect.size.width - amount;
remainder.size.height = rect.size.height;
}
RectEdge::MinY => {
slice.origin.x = rect.origin.x;
slice.origin.y = rect.origin.y;
slice.size.width = rect.size.width;
slice.size.height = amount;
remainder.origin.x = rect.origin.x;
remainder.origin.y = rect.origin.y + amount;
remainder.size.width = rect.size.width;
remainder.size.height = rect.size.height - amount;
}
RectEdge::MaxX => {
slice.origin.x = rect.origin.x + rect.size.width - amount;
slice.origin.y = rect.origin.y;
slice.size.width = amount;
slice.size.height = rect.size.height;
remainder.origin.x = rect.origin.x;
remainder.origin.y = rect.origin.y;
remainder.size.width = rect.size.width - amount;
remainder.size.height = rect.size.height;
}
RectEdge::MaxY => {
slice.origin.x = rect.origin.x;
slice.origin.y = rect.origin.y + rect.size.height - amount;
slice.size.width = rect.size.width;
slice.size.height = amount;
remainder.origin.x = rect.origin.x;
remainder.origin.y = rect.origin.y;
remainder.size.width = rect.size.width;
remainder.size.height = rect.size.height - amount;
}
}
return (slice, remainder);
}
pub fn inset(self, dx:T, dy:T) -> Rect<T> {
let mut r = self.standardize();
r.origin.x = r.origin.x - dx;
r.origin.y = r.origin.y - dy;
r.size.width = r.size.width - dx * T::from(2).unwrap();
r.size.height = r.size.height - dy * T::from(2).unwrap();
if r.size.width < T::zero() || r.size.height < T::zero() {
return Rect::null();
}
return r;
}
pub fn integral(self) -> Rect<T> {
let r = self.standardize();
Rect::new_pp(r.min_x().floor(), r.min_y().floor(),
r.max_x().ceil() , r.max_y().ceil() )
}
pub fn intersection(self, other:Rect<T>) -> Rect<T> {
let r1 = self.standardize();
let r2 = other.standardize();
let x0 = r1.min_x().max(r2.min_x());
let x1 = r1.max_x().min(r2.max_x());
if x0 < x1 {
let y0 = r1.min_y().max(r2.min_y());
let y1 = r1.max_y().min(r2.max_y());
if y0 < y1 {
return Rect::new(x0, y0, x1 - x0, y1 - y0);
}
}
return Rect::null();
}
pub fn offset(self, dx:T, dy:T) -> Rect<T> {
Rect::new(self.origin.x + dx,
self.origin.y + dy,
self.size.width,
self.size.height)
}
pub fn union(self, other:Rect<T>) -> Rect<T> {
if self.is_null() { return other; }
if other.is_null() { return self; }
let r1 = self.standardize();
let r2 = other.standardize();
let x1 = r1.min_x().max(r2.min_x());
let y1 = r1.min_y().max(r2.min_y());
let x2 = r1.max_x().min(r2.max_x());
let y2 = r1.max_y().min(r2.max_y());
return Rect::new_pp(x1, y1, x2, y2);
}
pub fn contains_point(self, p:Point<T>) -> bool {
let r = self.standardize();
return
p.x >= r.min_x() &&
p.y >= r.min_y() &&
p.x < r.max_x() &&
p.y < r.max_y();
}
pub fn contains_rect(self, other:Rect<T>) -> bool {
let r1 = self.standardize();
let r2 = other.standardize();
let a = r2.min_x() >= r1.min_x();
let b = r2.max_x() <= r1.max_x();
let c = r2.min_y() >= r1.min_y();
let d = r2.max_y() <= r1.max_y();
return a && b && c && d;
}
pub fn intersects_rect(self, other:Rect<T>) -> bool {
let r1 = self.standardize();
let r2 = other.standardize();
let outside = ( r1.max_x() <= r2.min_x() || r1.max_x() <= r2.min_x() ) ||
( r1.max_y() <= r2.min_y() || r1.max_y() <= r2.min_y() );
return !outside;
}
}