From 27e648a3359d560c37a9088317c613982cb250b8 Mon Sep 17 00:00:00 2001 From: zk Date: Mon, 15 Jul 2024 18:54:35 +0100 Subject: [PATCH] Add `Rect::scale_from_center` (#4673) I find myself wanting this API quite a lot, and I imagine it'll probably be useful for others. # What? This PR adds `Rect::scale` and `Rect::scale2` functions, which work a lot like `expand`, but instead multiply by a scale. i.e. ```rs rect.scale(2.0); // rect is 2x as big, still in same center rect.scale2(vec2(1.5, 2.0)); // rect is 1.5x as big on x axis, 2.0x as big on y axis. still in same center ``` # Why? Before this you either had to write this yourself or use a `expand` in a cumbersome way: ```rs rect.expand2(vec2(rect.width() * scale.x / 2.0, rect.height() * scale.y / 2.0)); ``` I find myself wanting to scale things up by a factor frequently enough, and it seems like a useful addition to have a multiply-based variant of `expand`. I realise this is pretty minor, but it seems useful enough to me! --------- Co-authored-by: zkldi <20380519+zkldi@users.noreply.github.com> Co-authored-by: Emil Ernerfeldt --- crates/emath/src/rect.rs | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/crates/emath/src/rect.rs b/crates/emath/src/rect.rs index 28ca2ec464d..c3e6ad934c1 100644 --- a/crates/emath/src/rect.rs +++ b/crates/emath/src/rect.rs @@ -200,6 +200,18 @@ impl Rect { Self::from_min_max(self.min - amnt, self.max + amnt) } + /// Scale up by this factor in each direction, keeping the center + #[must_use] + pub fn scale_from_center(self, scale_factor: f32) -> Self { + self.scale_from_center2(Vec2::splat(scale_factor)) + } + + /// Scale up by this factor in each direction, keeping the center + #[must_use] + pub fn scale_from_center2(self, scale_factor: Vec2) -> Self { + Self::from_center_size(self.center(), self.size() * scale_factor) + } + /// Shrink by this much in each direction, keeping the center #[must_use] pub fn shrink(self, amnt: f32) -> Self { @@ -740,6 +752,25 @@ mod tests { assert_eq!(r.distance_sq_to_pos(pos2(25.0, 5.0)), 50.0); // right and above } + #[test] + fn scale_rect() { + let c = pos2(100.0, 50.0); + let r = Rect::from_center_size(c, vec2(30.0, 60.0)); + + assert_eq!( + r.scale_from_center(2.0), + Rect::from_center_size(c, vec2(60.0, 120.0)) + ); + assert_eq!( + r.scale_from_center(0.5), + Rect::from_center_size(c, vec2(15.0, 30.0)) + ); + assert_eq!( + r.scale_from_center2(vec2(2.0, 3.0)), + Rect::from_center_size(c, vec2(60.0, 180.0)) + ); + } + #[test] fn test_ray_intersection() { let rect = Rect::from_min_max(pos2(1.0, 1.0), pos2(3.0, 3.0));