JSFiddle - React, Tailwind, and code Playground

by m1erickson

HTML

<h4>Fitting rectangle to triangle using transforms</h4>

<canvas id="canvas" width=350 height=350></canvas>

CSS

body {
    background-color: ivory;
}
#canvas {
    border:1px solid red;
}

JavaScript

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");

var pt1 = {
    x: 100,
    y: 100
};
var pt2 = {
    x: 150,
    y: 225
};
var pt3 = {
    x: 250,
    y: 150
};


drawTriangle();

drawRectangle();


function drawRectangle() {

    // calc transform info
    var info = analyzeTriangle();

    ctx.save();
    ctx.translate(info.translate.x, info.translate.y);
    ctx.rotate(info.rotation);
    ctx.transform(1, 0, info.skewX, 1, 0, 0);
    ctx.beginPath();
    // since rects origin is top left, must offset y by -height
    ctx.rect(0, -info.rectHeight, info.rectWidth, info.rectHeight);
    ctx.strokeStyle = "purple";
    ctx.stroke();
    ctx.restore();
}


function drawTriangle() {
    ctx.beginPath();
    ctx.strokeStyle = "blue";
    ctx.moveTo(pt1.x, pt1.y);
    ctx.lineTo(pt2.x, pt2.y);
    ctx.lineTo(pt3.x, pt3.y);
    ctx.closePath();
    ctx.stroke();
    ctx.fillStyle = "rgba(255,255,0,0.10)";
    ctx.fill();
}


function analyzeTriangle() {

    // segment lengths
    var AB = Math.sqrt(Math.pow(pt2.x - pt1.x, 2) + Math.pow(pt2.y - pt1.y, 2));
    var BC = Math.sqrt(Math.pow(pt2.x - pt3.x, 2) + Math.pow(pt2.y - pt3.y, 2));
    var AC = Math.sqrt(Math.pow(pt3.x - pt1.x, 2) + Math.pow(pt3.y - pt1.y, 2));

    // angleB = using law of cosines
    var angleB = Math.acos((BC * BC + AB * AB - AC * AC) / (2 * BC * AB));

    // transform translate = pt2
    var translate = pt2;

    // transform rotation = angleBC (based on slope of BC)
    var rotation = Math.atan2((pt3.y - pt2.y), (pt3.x - pt2.x));

    // transform skewX, based on angleB 
    var skewX = Math.tan(angleB - Math.PI / 2);

    // rectangle height = triangle altitude
    var rectHeight = AB * Math.sin(angleB);

    // rectangle width = triangle BC
    var rectWidth = BC;

    return ({
        translate: translate,
        rotation: rotation,
        skewX: skewX,
        rectHeight: rectHeight,
        rectWidth: rectWidth
    });

}