簡體   English   中英

如何計算圍繞其角旋轉的矩形的邊界框?

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

幾天前我問了這個問題,當一個矩形圍繞其中心旋轉時,這個答案非常有效。

但是,我現在試圖讓它在矩形圍繞其左上角旋轉的情況下工作。

鏈接答案中的這些行仍然正確,可用於計算邊界框的寬度和高度:

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

但是, xy值不再適用於這種左上角的情況。 起初我認為它可能是一樣的,只是這個:

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

但它似乎不起作用。 認為答案涉及某種sincos函數,但我無法弄清楚哪種組合提供了正確的輸出。 再次,我已經包含了以下問題的完整再現:

 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>

如您所見,當嘗試使用相同的代碼時,邊界框(紅色矩形)沒有正確包圍黑色矩形,我試圖讓它對rA所有值都這樣做。

我認為需要在代碼段中更改以使其工作的唯一兩行是以下兩行:

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

但我無法弄清楚我必須將它們更改為什么才能解決問題。

繞角x0, y0旋轉后x0, y0按角度Fi矩形中心有坐標

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

邊界框中心的坐標相同。 所以邊界框基角是

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>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM