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.
Assuming 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
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.
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.
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);
}
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;
}
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>