简体   繁体   中英

How to calculate a bounding box for a rectangle rotated around its corner?

I asked this question several days ago and the answer works perfectly for when a rectangle is rotated around its center.

However, I'm now trying to get it working in the case that the rectangle is rotated around its top left corner.

These lines from the linked answer are still correct and working for calculating the width and height of the bounding box:

H = w * Abs(Sin(Fi)) + h * Abs(Cos(Fi))
W = w * Abs(Cos(Fi)) + h * Abs(Sin(Fi))

However, the x and y values are no longer working for this top-left case. At first I thought it may just be the same and just this:

x0  = rXCenter - W/2
y0  = rYCenter - H/2

But it doesn't seem to work. I think the answer involves some sort of sin and cos functions, but I can't figure out which combination provides the correct output. Again, I've included a full reproduction of the issue below:

 let canvas = document.querySelector("canvas"); let ctx = canvas.getContext("2d"); function drawRectangle(rX, rY, rW, rH) { ctx.beginPath(); ctx.rect(rX, rY, rW, rH); ctx.stroke(); } function degreesToRadians(degrees) { return degrees * (Math.PI / 180); } function rotateCanvas(radians, centerX, centerY) { ctx.translate(centerX, centerY); ctx.rotate(radians); ctx.translate(-centerX, -centerY); } function drawRotatedRectangle(rX, rY, rW, rH, rAngle, rOX, rOY) { rotateCanvas(rAngle, rOX, rOY); drawRectangle(rX, rY, rW, rH); rotateCanvas(-rAngle, rOX, rOY); } function computeBB(x, y, w, h, a) { let sinA = Math.abs(Math.sin(a)); let cosA = Math.abs(Math.cos(a)); let bbH = w * sinA + h * cosA; let bbW = w * cosA + h * sinA; let bbX = x - bbW / 2; let bbY = y - bbH / 2; return { x: bbX, y: bbY, w: bbW, h: bbH }; } let rX = 100; let rY = 100; let rW = 100; let rH = 50; let rA = degreesToRadians(45); let rOX = rX; let rOY = rY; drawRotatedRectangle(rX, rY, rW, rH, rA, rOX, rOY); let bb = computeBB(rX, rY, rW, rH, rA); ctx.strokeStyle = "#ff0000"; drawRectangle(bb.x, bb.y, bb.w, bb.h);
 body { margin: 0; overflow: hidden; }
 <canvas width="600" height="600"></canvas>

As you can see, when trying to use the same code, the bounding box (red rectangle) does not properly enclose the black rectangle, and I am trying to get it to do so for all values of rA .

The only two lines that I believe need to be changed in the snippet to get it to work are these two:

let bbX = x - bbW / 2;
let bbY = y - bbH / 2;

But I can't quite figure out what I have to change them to in order to fix the problem.

After rotation about corner x0, y0 by angle Fi rectangle center has coordinates

cx = x0 + w/2*Cos(Fi) - h/2*Sin(Fi)
cy = y0 + w/2*Sin(Fi) + h/2*Cos(Fi)

Same coordinates are for bounding box center. So bounding box base corner is

bbx = cx - bbW/2
bby = cy - bbH/2

 let canvas = document.querySelector("canvas"); let ctx = canvas.getContext("2d"); function drawRectangle(rX, rY, rW, rH) { ctx.beginPath(); ctx.rect(rX, rY, rW, rH); ctx.stroke(); } function degreesToRadians(degrees) { return degrees * (Math.PI / 180); } function rotateCanvas(radians, centerX, centerY) { ctx.translate(centerX, centerY); ctx.rotate(radians); ctx.translate(-centerX, -centerY); } function drawRotatedRectangle(rX, rY, rW, rH, rAngle, rOX, rOY) { rotateCanvas(rAngle, rOX, rOY); drawRectangle(rX, rY, rW, rH); rotateCanvas(-rAngle, rOX, rOY); } function computeBB(x, y, w, h, a) { let sinA = Math.abs(Math.sin(a)); let cosA = Math.abs(Math.cos(a)); let bbH = w * sinA + h * cosA; let bbW = w * cosA + h * sinA; let cx = x + w/2*Math.cos(a) - h/2*Math.sin(a) let cy = y + w/2*Math.sin(a) + h/2*Math.cos(a) let bbX = cx - bbW / 2; let bbY = cy - bbH / 2; return { x: bbX, y: bbY, w: bbW, h: bbH }; } let rX = 100; let rY = 100; let rW = 100; let rH = 50; let rA = degreesToRadians(45); let rOX = rX; let rOY = rY; drawRotatedRectangle(rX, rY, rW, rH, rA, rOX, rOY); let bb = computeBB(rX, rY, rW, rH, rA); ctx.strokeStyle = "#ff0000"; drawRectangle(bb.x, bb.y, bb.w, bb.h);
 <canvas width="600" height="600"></canvas>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM