[英]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))
但是, x
和y
值不再適用於這種左上角的情況。 起初我認為它可能是一樣的,只是這個:
x0 = rXCenter - W/2
y0 = rYCenter - H/2
但它似乎不起作用。 我認為答案涉及某種sin
和cos
函數,但我無法弄清楚哪種組合提供了正確的輸出。 再次,我已經包含了以下問題的完整再現:
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.