An axis-aligned bounding box (AABB) of a rotated plygon

by Ed Kolosovsky

HTML

<svg height="500" width="500">
  <polygon id='polygon' style="fill: red;" />
  <polygon id='bounding-box' style="fill: transparent; stroke: black; stroke-width: 1" />
</svg>

JavaScript

let points = [
			{ x: 125, y: 50 },
			{ x: 250, y: 65 },
			{ x: 300, y: 125 },
			{ x: 175, y: 175 },
			{ x: 100, y: 125 },
		];
let minX = Math.min(...points.map(point => point.x));
let minY = Math.min(...points.map(point => point.y));
let maxX = Math.max(...points.map(point => point.x));
let maxY = Math.max(...points.map(point => point.y));
let pivot = {
  x: maxX - ((maxX - minX) / 2),
  y: maxY - ((maxY - minY) / 2)
};
let degrees = 90;
let radians = degrees * (Math.PI / 180);
let cos = Math.cos(radians);
let sin = Math.sin(radians);
let polygonElem = document.querySelector('#polygon');

polygonElem.setAttribute('points',  points.reduce((str, point) => `${str} ${point.x}, ${point.y}`, ''));
polygonElem.setAttribute('transform',  `rotate(${degrees} ${pivot.x} ${pivot.y})`);

function rotatePoint(pivot, point, cos, sin) {
  return {
    x: (cos * (point.x - pivot.x)) - (sin * (point.y - pivot.y)) + pivot.x,
    y: (sin * (point.x - pivot.x)) + (cos * (point.y - pivot.y)) + pivot.y
  };
}

let boundingBox = {
	x1: Number.POSITIVE_INFINITY,
	y1: Number.POSITIVE_INFINITY,
	x2: Number.NEGATIVE_INFINITY,
	y2: Number.NEGATIVE_INFINITY,
};

points.forEach((point) => {
  let rotatedPoint = rotatePoint(pivot, point, cos, sin);

  boundingBox.x1 = Math.min(boundingBox.x1, rotatedPoint.x);
  boundingBox.y1 = Math.min(boundingBox.y1, rotatedPoint.y);
  boundingBox.x2 = Math.max(boundingBox.x2, rotatedPoint.x);
  boundingBox.y2 = Math.max(boundingBox.y2, rotatedPoint.y);
});

let boundingBoxElem = document.querySelector('#bounding-box');

boundingBoxElem.setAttribute('points',  `
${boundingBox.x1}, ${boundingBox.y1} 
${boundingBox.x2}, ${boundingBox.y1} 
${boundingBox.x2}, ${boundingBox.y2} 
${boundingBox.x1}, ${boundingBox.y2}`);