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
});
}