SWHarden.com

The personal website of Scott W Harden

Point Inside Rectangle

How to determine if a point is inside a rotated rectangle with C#

I recently had the need to determine if a point is inside a rotated rectangle. This need arose when I wanted to make a rotated rectangular textbox draggable, but I wanted to determine if the mouse was over the rectangle. I know the rectangle’s location, size, and rotation, and the position of the mouse cursor, and my goal is to tell if the mouse is inside the rotated rectangle. In this example I’ll use Maui.Graphics to render a test image in a Windows Forms application (with SkiaSharp and OpenGL), but the same could be achieved with System.Drawing or other similar 2D graphics libraries.

I started just knowing the width and height of my rectangle. I created an array of points representing its corners.

float rectWidth = 300;
float rectHeight = 150;

PointF[] rectCorners =
{
    new(0, 0),
    new(rectWidth, 0),
    new(rectWidth, rectHeight),
    new(0, rectHeight),
};

I then rotated the rectangle around an origin point by applying a rotation transformation to each corner.

PointF origin = new(200, 300); // center of rotation
double angleRadians = 1.234;
PointF[] rotatedCorners = rectCorners.Select(x => Rotate(origin, x, angleRadians)).ToArray();
private PointF Rotate(PointF origin, PointF point, double radians)
{
	double dx = point.X * Math.Cos(radians) - point.Y * Math.Sin(radians);
	double dy = point.X * Math.Sin(radians) + point.Y * Math.Cos(radians);
	return new PointF(origin.X + (float)dx, origin.Y + (float)dy);
}

To determine if a given point is inside the rotated rectangle I called this method which accepts the point of interest and an array containing the four corners of the rotated rectangle.

public bool IsPointInsideRectangle(PointF pt, PointF[] rectCorners)
{
    double x1 = rectCorners[0].X;
    double x2 = rectCorners[1].X;
    double x3 = rectCorners[2].X;
    double x4 = rectCorners[3].X;

    double y1 = rectCorners[0].Y;
    double y2 = rectCorners[1].Y;
    double y3 = rectCorners[2].Y;
    double y4 = rectCorners[3].Y;

    double a1 = Math.Sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
    double a2 = Math.Sqrt((x2 - x3) * (x2 - x3) + (y2 - y3) * (y2 - y3));
    double a3 = Math.Sqrt((x3 - x4) * (x3 - x4) + (y3 - y4) * (y3 - y4));
    double a4 = Math.Sqrt((x4 - x1) * (x4 - x1) + (y4 - y1) * (y4 - y1));

    double b1 = Math.Sqrt((x1 - pt.X) * (x1 - pt.X) + (y1 - pt.Y) * (y1 - pt.Y));
    double b2 = Math.Sqrt((x2 - pt.X) * (x2 - pt.X) + (y2 - pt.Y) * (y2 - pt.Y));
    double b3 = Math.Sqrt((x3 - pt.X) * (x3 - pt.X) + (y3 - pt.Y) * (y3 - pt.Y));
    double b4 = Math.Sqrt((x4 - pt.X) * (x4 - pt.X) + (y4 - pt.Y) * (y4 - pt.Y));

    double u1 = (a1 + b1 + b2) / 2;
    double u2 = (a2 + b2 + b3) / 2;
    double u3 = (a3 + b3 + b4) / 2;
    double u4 = (a4 + b4 + b1) / 2;

    double A1 = Math.Sqrt(u1 * (u1 - a1) * (u1 - b1) * (u1 - b2));
    double A2 = Math.Sqrt(u2 * (u2 - a2) * (u2 - b2) * (u2 - b3));
    double A3 = Math.Sqrt(u3 * (u3 - a3) * (u3 - b3) * (u3 - b4));
    double A4 = Math.Sqrt(u4 * (u4 - a4) * (u4 - b4) * (u4 - b1));

    double difference = A1 + A2 + A3 + A4 - a1 * a2;
    return difference < 1;
}

How does it work?

Consider 4 triangles formed by lines between the point and the 4 corners…

If the point is inside the rectangle, the area of the four triangles will equal the area of the rectangle.

If the point is outside the rectangle, the area of the four triangles will be greater than the area of the rectangle.

The code above calculates the area of the 4 rectangles and returns true if it is approximately equal to the area of the rectangle.

Notes

Resources