0

How to draw the red rectangle below black rectangle on canvas such that all 4 vertices of the rotated black rectangle touch all 4 edges of the red rectangle? I am using the following code to add the black rectangle:

const canvas = document.getElementById('myCanvas1');
const ctx = canvas.getContext('2d');

// Rectangle properties
const width = 50;
const height = 200;
const centerX = canvas.width / 2;
const centerY = canvas.height / 2;

// Rotation angle in degrees
const degrees = -10; // Anti-clockwise rotation
const radians = (degrees * Math.PI) / 180;

// Clear the canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);

// Save the canvas state
ctx.save();

// Translate to the center of the rectangle
ctx.translate(centerX, centerY);

// Rotate the canvas
ctx.rotate(radians);

// Draw the rotated rectangle
ctx.fillStyle = 'black';
ctx.fillRect(-width / 2, -height / 2, width, height);

// Restore the canvas state
ctx.restore();
<canvas id="myCanvas1" width="600" height="250"></canvas>

enter image description here

Mushroomator
  • 6,516
  • 1
  • 10
  • 27
dc09
  • 386
  • 2
  • 17
  • 1
    Does this answer your question? [Calculate Bounding box coordinates from a rotated rectangle](https://stackoverflow.com/questions/622140/calculate-bounding-box-coordinates-from-a-rotated-rectangle) – Stefnotch Aug 10 '23 at 17:47

1 Answers1

1

Brute force

The brute force method calculates the position of each corner of the rotated rectangle. Then to get the bounding box get the left top most corner.

As the rectangle is rotated around its center the width and height of the bounding box is double the distance from the rectangle center.

The function drawRect draws the rotated rectangle and returns an object representing the bounding box

requestAnimationFrame(animLoop);
const ctx = canvas.getContext('2d');
const centerX = canvas.width / 2;
const centerY = canvas.height / 2;
const width = Math.min(centerX, centerY) * 1.8;
const height = width * 0.25
var rot = 0.0;

function drawRect(width, height, centerX, centerY, rotate) {

    // compute the x axis vector
    const xAx = Math.cos(rotate);
    const xAy = Math.sin(rotate);
    ctx.setTransform(xAx, xAy, -xAy, xAx, centerX, centerY);
    ctx.fillStyle = "#000";
    const hw = width * 0.5;               // half width and height
    const hh = height * 0.5;
    ctx.fillRect(-hw, -hh, width, height);
    ctx.setTransform(1, 0, 0, 1, 0, 0);   // restore default
    
    // Get 4 corners
    const topLeft =  {x: -hw * xAx - -hh * xAy, y: -hw * xAy + -hh * xAx};
    const botLeft =  {x: -hw * xAx -  hh * xAy, y: -hw * xAy +  hh * xAx};
    const topRight = {x:  hw * xAx - -hh * xAy, y:  hw * xAy + -hh * xAx};
    const botRight = {x:  hw * xAx -  hh * xAy, y:  hw * xAy +  hh * xAx};
    
    // Get the left top most corner
    const left = Math.min(topLeft.x, botLeft.x, topRight.x, botRight.x);
    const top =  Math.min(topLeft.y, botLeft.y, topRight.y, botRight.y);
    
    // Return the bounding box
    return {
       left:    left + centerX,
       top:     top + centerY,
       width:  -left * 2,
       height: -top * 2,
    };
}

function animLoop() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    rot += 0.01;
    const bounding = drawRect(width, height, centerX, centerY, rot);
    ctx.globalCompositeOperation = "destination-over";
    ctx.fillStyle = "#F00";
    ctx.fillRect(bounding.left, bounding.top, bounding.width, bounding.height);
    ctx.globalCompositeOperation = "source-over";
    requestAnimationFrame(animLoop);
}
<canvas id="canvas" width="400" height="180"></canvas>
Blindman67
  • 51,134
  • 11
  • 73
  • 136