An axis-aligned bounding box (AABB) of a rotated plygon
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 },
];
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}`);