以下是如何计算将矩形拟合到三角形所需的变换:
- 平移到三角形的“枢轴点”——B 点。
- 旋转 BC 边的角度。
- 在 X 方向上倾斜角 B 的角度。
所以,首先翻译:
// 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));
最后skewX:
// transform skewX, based on angleB
var skewX = Math.tan(angleB-Math.PI/2);
以下是获取 angleB 以在 skewX 中使用的方法:
// calculate 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));
// calculate angleB using law of cosines
var angleB = Math.acos((BC*BC+AB*AB-AC*AC)/(2*BC*AB));
您还需要绘制矩形的宽度和高度:
// rectangle height = triangle altitude
var rectHeight = AB * Math.sin(angleB);
// rectangle width = triangle BC
var rectWidth = BC;
一个小“陷阱”:
您的平移点是 B,但矩形是从左上角开始绘制的。
这意味着您必须将矩形垂直偏移 rectHeight:
ctx.rect(0, -rectHeight, rectWidth, rectHeight);
此外,并不是真正的“陷阱”,而是更多的自然限制:
角 B 处的角度必须小于 180。
所以,如果你的三角形“倒置”,你将不得不通过翻转点 A 和 C 来补偿。
你那里有有趣的项目!
完成后你会分享一点吗?
这是代码和小提琴:http: //jsfiddle.net/m1erickson/KKELu/
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; }
#canvas{border:1px solid red;}
</style>
<script>
$(function(){
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
});
}
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="canvas" width=350 height=350></canvas>
</body>
</html>