Search code examples
c#.netmathaspect-ratio

Resizing a rectangle and snapping to a fixed ratio


I currently have code which resizes a rectangle based on mouse movement when the user clicks on multiple anchors which correspond to the following areas: Left, Top, Right, Bottom, TopLeft, TopRight, BottomLeft, BottomRight.

So the user can click and drag the top anchor and it will adjust the Top coordinate of the rectangle based on where the mouse is. Same for all the other anchors.

After the fact I want to enforce a fixed ratio (such as 2:3 or 5:7) by snapping the appropriate sides of the rectangle based on the action. I have done this for the Left, Top, Right, and Bottom anchors because it's easy, if I'm resizing the width I just need to auto-size the height based on the ratio, and vice-versa.

The difficulty I'm having is when the user is dragging a corner such as the Bottom Right or the Top Left anchor. I need to figure out how to choose which side to snap. I have the mouse coordinate and the left, top, right, and bottom of the rectangle.

Here's the code I've tried:

case Anchor.BottomRight:
    float maxRight = CursorPosition.X;
    float maxBottom = CursorPosition.Y;

    float newRight = Bounds.Left + (Bounds.Width * widthRatio);
    float newBottom = Bounds.Top + (Bounds.Height * heightRatio);

    if (newRight < maxRight)
    {
        Width = Height * widthRatio;
    }
    else
    {
        Height = Width * heightRatio;
    }

    break;

In an example of a fixed ratio of 2:3 the widthRatio would be 0.666 and the heightRatio would be 1.5.

This code works half of the time but of course it's basically a 50/50 chance of working. I have to identify a proper condition to snap either the width or the height.


Solution

  • I figured it out.

    if (Height * widthRatio <= Width)
        Width = Height * widthRatio;
    else if (Width * heightRatio <= Height)
        Height = Width * heightRatio;
    

    This will emulate the functionality in Photoshop with a Fixed Ratio.