Check if a point is in a rotated rectangle (C#)

15,679

Solution 1

Is it possible to apply the same rotation applied to the rectangle to the point in reverse?

For example, Rectangle A is rotated 45 degrees clockwise from its origin (upper left corner), you would then just rotate point B around the same origin 45 degrees COUNTER clockwise, then check to see if it falls within Rectangle A pre-rotation

Solution 2

You could keep a second, undisplayed image where you draw duplicates of the rectangles, each uniquely colored. When the user clicks on the picturebox, find the color of the corresponding pixel in the 2nd image, which will identify which rectangle was clicked.

Solution 3

Edit: After looking back, I'm using MonoGame and the OP is using Windows Forms. The following is for MonoGame.

I've been messing this for a while now and have found a couple answers, just none of them actually worked. Here is a C# function that does exactly as OP describes, if not for OP then other people Googling like I was.

It was a headache to figure this out. A lot of the typical guesswork.

    bool PointIsInRotatedRectangle(Vector2 P, Rectangle rect, float rotation)
    {
        Matrix rotMat = Matrix.CreateRotationZ(-rotation);
        Vector2 Localpoint = P - (rect.Location).ToVector2();
        Localpoint = Vector2.Transform(Localpoint, rotMat);
        Localpoint += (rect.Location).ToVector2();

        if (rect.Contains(Localpoint)) { return true; }
        return false;
    }

And here it is in a single line of code. Probably faster to use.

    bool PointIsInRotatedRectangle(Vector2 P, Rectangle rect, float rotation)
    {
        return rect.Contains(Vector2.Transform(P - (rect.Location).ToVector2(), Matrix.CreateRotationZ(-rotation)) + (rect.Location).ToVector2());
    }

Solution 4

I know this was already answered but I had to do something similar a while ago. I created an extension method for the System.Windows.Point class that helped do exactly what Neil suggested:

    public static double GetAngle(this Point pt)
    {
        return Math.Atan2(pt.X, -pt.Y) * 180 / Math.PI;
    }

    public static Point SetAngle(this Point pt, double angle)
    {
        var rads = angle * (Math.PI / 180);
        var dist = Math.Sqrt(pt.X * pt.X + pt.Y * pt.Y);
        pt.X = Math.Sin(rads) * dist;
        pt.Y = -(Math.Cos(rads) * dist);
        return pt;
    }

This would allow me to work with the angles of points around 0, 0. So if you know the center of the rect that you are testing you would offset the point by the negative of this value (for example: pt.X -= 32; pt.Y -= 32) And then you would apply the negative rotation of the rectangle (as suggested by Neil: pt.SetAngle(-45);)...

Now if the point is within 64, 64 you know you hit the rectangle. More specifically I was checking a pixel of a rotated image to make sure I hit a pixel of a specific color.

Solution 5

Would the rectangles be allowed to overlap? If so, would you want all the rectangles in a point, or just the one in the top layer?

Share:
15,679
Ove
Author by

Ove

Updated on June 15, 2022

Comments

  • Ove
    Ove about 2 years

    I have a program in C# (Windows Forms) which draws some rectangles on a picturebox. They can be drawn at an angle too (rotated).

    I know each of the rectangles' start point (upper-left corner), their size(width+height) and their angle. Because of the rotation, the start point is not necessarely the upper-left corner, but that does not matter here. Then when I click the picturebox, I need to check in which rectangle (if any) I have clicked.

    So I need some way of checking if a point is in a rectangle, but I also need to take into account the rotation of each rectangle. Does anybody know of a way to do this in C#?