Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

261
Vistas
How to calculate a bounding box for a rectangle rotated around its center?

I am looking to calculate the bounding box of a rectangle rotated around its center. I have read this question and while MarkusQ's answer works in general, it is not efficient enough for my needs. I am trying to get Troubadour's answer working, but it seems to only work when the origin of rotation is around a corner, not the center.

Is it possible to adapt his solution to work with rectangles that have their origin of rotation around their center?

I've developed a full recreation of the problem 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) {
  let rXCenter = rX + rW / 2;
  let rYCenter = rY + rH / 2;

  rotateCanvas(rAngle, rXCenter, rYCenter);
  drawRectangle(rX, rY, rW, rH);
  rotateCanvas(-rAngle, rXCenter, rYCenter);
}

function computeAABBCenter(x, y, w, h, theta) {
  const ux = Math.cos(theta) * 0.5; // half unit vector along w
  const uy = Math.sin(theta) * 0.5;
  const wx = w * ux;
  const wy = w * uy; // vector along w
  const hx = h * -uy;
  const hy = h * ux; // vector along h
  
  // all point from top left CW
  const x1 = x - wx - hx;
  const y1 = y - wy - hy;
  const x2 = x + wx - hx;
  const y2 = y + wy - hy;
  const x3 = x + wx + hx;
  const y3 = y + wy + hy;
  const x4 = x - wx + hx;
  const y4 = y - wy + hy;
  
  return {
    x1: Math.min(x1, x2, x3, x4),
    y1: Math.min(y1, y2, y3, y4),
    x2: Math.max(x1, x2, x3, x4),
    y2: Math.max(y1, y2, y3, y4),
  };
}

let rX = 100;
let rY = 100;
let rW = 100;
let rH = 50;
let rA = 0.707;

drawRotatedRectangle(rX, rY, rW, rH, rA);

let bb = computeAABBCenter(rX, rY, rW, rH, rA);

drawRectangle(bb.x1, bb.y1, bb.x2 - bb.x1, bb.y2 - bb.y1);
body { margin: 0; overflow: hidden; }
<canvas width="800" height="800"></canvas>

As you can see, the bounding box rectangle is not correct. Here's what it currently looks like, and what it should look like:

enter image description here

about 4 years ago · Juan Pablo Isaza
2 Respuestas
Responde la pregunta

0

Size of bounding box (description here)

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

Having rXCenter, rYCenter, you can find get bounds coordinates

x0  = rXCenter - W/2
y0  = rYCenter - H/2
about 4 years ago · Juan Pablo Isaza Denunciar

0

It feels like you are over thinking this. Here I show how to draw three rectangles rotated around a center pointt I made blue.

const wrapper = document.getElementById('wrapper');
const canvas = document.getElementById('canvas');
const wCS = window.getComputedStyle(wrapper, null)
const pl = parseFloat(wCS.getPropertyValue('padding-left'));
const pt = parseFloat(wCS.getPropertyValue('padding-top'));
const pr = parseFloat(wCS.getPropertyValue('padding-right'));
const pb = parseFloat(wCS.getPropertyValue('padding-bottom'));
canvas.width = wrapper.clientWidth - pl - pr;
canvas.height = wrapper.clientHeight - pt - pb;

const ctx = canvas.getContext('2d');
// setup a rectangle
let cornerLeft = 70;
let cornerTop = 70;
let width = 180;
let height = 60;
let horizontalCenter = cornerTop + (width / 2);
let verticalCenter = cornerTop + (height / 2);
let centerPoint = {
  horz: horizontalCenter,
  vert: verticalCenter
};
let colorBlue = '#0000FF';
let colorLime = '#40FF40';
let colorPurple = '#4040FF';
let colorOrange = '#FFA500';

ctx.fillStyle = colorBlue;
ctx.fillRect(centerPoint.horz, centerPoint.vert, 8, 8); // fill in the pixels at center point

ctx.strokeStyle = colorPurple;
ctx.strokeRect(cornerTop, cornerLeft, width, height); // horizontal purple box

ctx.strokeStyle = colorOrange;
ctx.translate(centerPoint.horz, centerPoint.vert); // center point note positive
ctx.rotate(Math.PI / 2); // vertical
ctx.translate(-centerPoint.horz, -centerPoint.vert); // center point - note negative
ctx.strokeRect(cornerTop, cornerLeft, width, height); // vertical orange box

ctx.strokeStyle = colorLime;
ctx.translate(-centerPoint.horz * (1.375), -centerPoint.vert * (0.5)); // center point - note negative
ctx.rotate((Math.PI / 2) / -2); //back left by 45 deg left
ctx.translate(centerPoint.horz * (.025), centerPoint.vert * (2.75)); // center point note positive
ctx.strokeRect(cornerTop, cornerLeft, width, height);
#wrapper {
  width: 400px;
  height: 400px;
  padding: 2rem;
  border: 1px solid blue;
}

#canvas {
  border: 1px solid orange;
}
<div id="wrapper"><canvas id="canvas"></canvas></div>

about 4 years ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda