I have a rectangle that rotated 45° degree as shown below, I have the points of all four corners, I need to find out if given point is within the boundary of the rotated rectangle. Note that rotation will change to any number, so somehow rotation need to be part of the formula.
So we have:
Width: 10
Height: 10
Rotation degree: 45°
Coordinates of rotated rectangle: A B C D
Given coordinates: E
Appreciate any help.
I have a rectangle that rotated 45° degree as shown below, I have the points of all four corners, I need to find out if given point is within the boundary of the rotated rectangle. Note that rotation will change to any number, so somehow rotation need to be part of the formula.
So we have:
Width: 10
Height: 10
Rotation degree: 45°
Coordinates of rotated rectangle: A B C D
Given coordinates: E
Appreciate any help.
Share Improve this question edited May 28, 2021 at 21:20 AbdelAziz AbdelLatef 3,7547 gold badges26 silver badges53 bronze badges asked May 27, 2021 at 9:10 cyrus-dcyrus-d 8431 gold badge14 silver badges36 bronze badges 3-
getBoundingClientRect()
might be useful depending on how you create the element. – Geshode Commented May 27, 2021 at 9:16 -
i am afraid the
getBoundingClientRect()
is not a solution, imagine that the pointE
is out side the box betweenA
andB
; usinggetBoundingClientRect
will falsely indicate that the pointE
is within the box, because it will return overall dimension. – cyrus-d Commented May 27, 2021 at 9:37 - What are width and height? – AbdelAziz AbdelLatef Commented May 27, 2021 at 15:06
3 Answers
Reset to default 6Assuming you don't have the transform matrix for the rectangle.
If you do have the matrix then multiply the point by the inverse transform matrix. Then just test the point against the bounds of the rectangle top,left, right, and bottom
Point inside convex polygon
Consider a convex polygon with points going around in a clockwise direction.
A point is inside that polygon if it is to the left of every edge (line) of the polygon.
If the point is right of one or more edges it is outside the polygon.
Left is defined as your left as if standing at the start of the line looking along its length.
Cross product
To find out which side a point is of a line you get the cross product of the vector from the line start to end, and the vector from the line start to the point. If the cross product is positive the point is to the left, if zero it is on the line, else it is to the right.
Is left
const Point = (x, y) => ({x, y});
const Line = (p1, p2) => ({p1, p2});
function isPointLeft(l, p) { // l is line, p is point
return 0 < (l.p2.x - l.p1.x) * (p.y - l.p1.y) - (l.p2.y - l.p1.y) * (p.x - l.p1.x);
}
Clockwise check
Thus give a set of points in clockwise order that represent a rectangle check each side against the point. If all left you are inside.
Function returns true if point is inside polygon. Assumes points for polygon are in clockwise order
function isPointInsidePoly(point, poly) {
var i = 0;
const line = Line(poly[poly.length - 1]);
while (i < poly.length) {
line.p2 = poly[i++];
if (!isPointLeft(line, point)) { return false }
line.p1 = line.p2;
}
return true;
}
Demo
Simple demo creates a set of points and rotates a rectangle.
Renders each point. If point is inside rectangle then point is drawn a little larger.
const Point = (x = 0, y = 0) => ({x, y});
const Line = (p1, p2) => ({p1, p2});
function isPointLeft(l, p) { // l is line, p is point
return 0 < (l.p2.x - l.p1.x) * (p.y - l.p1.y) - (l.p2.y - l.p1.y) * (p.x - l.p1.x);
}
function isPointInsidePoly(point, poly) {
var i = 0;
const line = Line(poly[poly.length - 1]);
while (i < poly.length) {
line.p2 = poly[i++];
if (!isPointLeft(line, point)) { return false }
line.p1 = line.p2;
}
return true;
}
requestAnimationFrame(renderLoop);
const ctx = canvas.getContext("2d");
const [W, H] = [canvas.width, canvas.height];
const rand = (m, M) => Math.random() * (M - m) + m;
const setOf = (count, cb, i = 0, a = []) => {while (i < count) { a.push(cb(i++)) } return a}
function drawPoint(p, size) {
ctx.strokeStyle = "#000";
ctx.beginPath();
ctx.arc(p.x, p.y, size, 0, Math.PI * 2);
ctx.stroke();
}
const rect = {
x: W / 2, y: H / 2,// x,y center of rectangle
w: 80, h: 20, // w h from center
points: [Point(), Point(), Point(), Point()],
update(angle) {
const transform = (x, y, res) => {
res.x = x * ax - y * ay + this.x;
res.y = x * ay + y * ax + this.y;
}
const [ax, ay] = [Math.cos(angle), Math.sin(angle)];
const p = this.points;
transform( this.w, this.h, p[0]);
transform(-this.w, this.h, p[1]);
transform(-this.w, -this.h, p[2]);
transform( this.w, -this.h, p[3]);
},
draw(ctx) {
ctx.lineWidth = 1;
ctx.strokeStyle = "red";
ctx.beginPath();
for (const p of this.points) { ctx.lineTo(p.x, p.y) }
ctx.closePath();
ctx.stroke();
}
};
const testPoints = setOf(20, () => Point(rand(20, W - 20), rand(20, H - 20)));
function renderLoop(time) {
ctx.clearRect(0, 0, W, H);
rect.update(time / 2300);
rect.draw(ctx);
for (const p of testPoints) {
if (isPointInsidePoly(p, rect.points)) { drawPoint(p, 3) }
drawPoint(p, 1);
}
requestAnimationFrame(renderLoop);
}
<canvas id="canvas" width="200" height="200"></canvas>
Any polytope can be represented as a finite intersection of closed half-spaces. Halfspaces are given by linear inequalities such as x+y+5<=0 which is the lower part of the line going through (-5,0) and (0,-5).
See any book on convexity or the Wikipedia link for details:
https://en.wikipedia/wiki/Polytope#Properties https://en.wikipedia/wiki/Half-space_(geometry)
You will need first to get the center of the rectangle by calculating the average coordinates of any two opposite corners. Then, you will need also to get the two dimensions of the rectangle which can be achieved by determinering the point with the largest y value along with the two points of the smallest and largest x values. The horizontal dimension, before rotation, is the distance between the first and second points, and the vertical dimension, before rotation, is the distance between the first and third points.
The next step is to check if point E is close enough to the center of the rectangle to be inside it or not. The simplest way is to check its horizontal and vertical distances, before rotation, from the center, if they are less than, or equal to if you are good with being on edges, half the respective dimension, then it is inside the rectangle. You can get the original horizontal and vertical distances before rotation using the appropriate rotation matrix for any rotation angle.
// center of rectangle
xO = (xA + xC) / 2;
yO = (yA + yC) / 2;
// point of largest y value
xPymax = xA;
yPymax = yA;
if (yB > yPymax)
{
xPymax = xB;
yPymax = yB;
}
if (yC > yPymax)
{
xPymax = xC;
yPymax = yC;
}
if (yD > yPymax)
{
xPymax = xD;
yPymax = yD;
}
// point of smallest x value
xPxmin = xA;
yPxmin = yA;
if (xB < xPxmin)
{
xPxmin = xB;
yPxmin = yB;
}
if (xC < xPxmin)
{
xPxmin = xC;
yPxmin = yC;
}
if (xD < xPxmin)
{
xPxmin = xD;
yPxmin = yD;
}
// point of largest x value
xPxmax = xA;
yPxmax = yA;
if (xB > xPxmax)
{
xPxmax = xB;
yPxmax = yB;
}
if (xC > xPxmax)
{
xPxmax = xC;
yPxmax = yC;
}
if (xD > xPxmax)
{
xPxmax = xD;
yPxmax = yD;
}
// dimensions of the rectangle
H = Math.sqrt((xPymax - xPxmin) * (xPymax - xPxmin) + (yPymax - yPxmin) * (yPymax - yPxmin));
V = Math.sqrt((xPymax - xPxmax) * (xPymax - xPxmax) + (yPymax - yPxmax) * (yPymax - yPxmax));
// calculating the original distances of point E from center
xdE = (xE - xO) * Math.cos(rot) + (yE - yO) * Math.sin(rot);
ydE = -(xE - xO) * Math.sin(rot) + (yE - yO) * Math.cos(rot);
// paring to the dimentions of the rectangle
if (Math.abs(xdE) <= H / 2 && Math.abs(ydE) <= V / 2) // this will consider a point on any edge as inside the rectangle, if you don't want this, just remove "="
// the point is inside the rectangle
else
// the point is outside the rectangle