From c9143bf4b5bd843ec2641632db121627df3d0977 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 23 Dec 2014 11:09:27 -0800 Subject: [PATCH] Implement a method `transform_rect` that transforms a rectangle and returns its bounding rect. Because it returns the bounding rect, this is well-defined for rotations and skew. This is useful for creating temporary draw targets. --- src/matrix2d.rs | 37 +++++++++++++++++++++++++++++++++++++ src/rect.rs | 15 +++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/src/matrix2d.rs b/src/matrix2d.rs index 5f54d9f..a2bb2fb 100644 --- a/src/matrix2d.rs +++ b/src/matrix2d.rs @@ -8,6 +8,9 @@ // except according to those terms. use num::{One, Zero}; +use point::Point2D; +use rect::Rect; +use size::Size2D; use std::ops::{Add, Mul}; #[derive(Clone, Copy)] @@ -63,5 +66,39 @@ impl + Copy + Clone + Mul + One + Zero> Matrix2D self.m31.clone(), self.m32.clone() ] } + + /// Returns the given point transformed by this matrix. + #[inline] + pub fn transform_point(&self, point: &Point2D) -> Point2D { + Point2D(point.x * self.m11 + point.y * self.m21 + self.m31, + point.x * self.m12 + point.y * self.m22 + self.m32) + } + + /// Returns a rectangle that encompasses the result of transforming the given rectangle by this + /// matrix. + #[inline] + pub fn transform_rect(&self, rect: &Rect) -> Rect { + let top_left = self.transform_point(&rect.origin); + let top_right = self.transform_point(&rect.top_right()); + let bottom_left = self.transform_point(&rect.bottom_left()); + let bottom_right = self.transform_point(&rect.bottom_right()); + let (mut min_x, mut min_y) = (top_left.x.clone(), top_left.y.clone()); + let (mut max_x, mut max_y) = (min_x.clone(), min_y.clone()); + for point in [ top_right, bottom_left, bottom_right ].iter() { + if point.x < min_x { + min_x = point.x.clone() + } + if point.x > max_x { + max_x = point.x.clone() + } + if point.y < min_y { + min_y = point.y.clone() + } + if point.y > max_y { + max_y = point.y.clone() + } + } + Rect(Point2D(min_x.clone(), min_y.clone()), Size2D(max_x - min_x, max_y - min_y)) + } } diff --git a/src/rect.rs b/src/rect.rs index 8e3996d..504d8fd 100644 --- a/src/rect.rs +++ b/src/rect.rs @@ -117,6 +117,21 @@ impl + Sub> Rect } } + #[inline] + pub fn top_right(&self) -> Point2D { + Point2D(self.max_x(), self.origin.y.clone()) + } + + #[inline] + pub fn bottom_left(&self) -> Point2D { + Point2D(self.origin.x.clone(), self.max_y()) + } + + #[inline] + pub fn bottom_right(&self) -> Point2D { + Point2D(self.max_x(), self.max_y()) + } + #[inline] pub fn translate_by_size(&self, size: &Size2D) -> Rect { Rect(Point2D(self.origin.x + size.width, self.origin.y + size.height), self.size.clone())