如何将直线转换为旋转的矩形?
How to convert a line to a rotated rectangle?
假设我有一行表格:x1, y1, x2, y2
和给定的 thickness
.
我正在寻找一种方法将该线转换为围绕其原点旋转的矩形,这样如果您将它们都绘制在 canvas 上,它们将完全重叠。
我已经完全重现了我面临的问题:
const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
const thickness = 7;
const lineX1 = 25, lineY1 = 50;
const lineX2 = 100, lineY2 = 100;
function rotateCanvas(x, y, a) {
ctx.translate(x, y);
ctx.rotate(a);
ctx.translate(-x, -y);
}
function drawRectangle(rX, rY, rW, rH, rA, color) {
ctx.beginPath();
ctx.fillStyle = "#dd3333";
rotateCanvas(rX + rW / 2, rY + rH / 2, rA);
ctx.rect(rX, rY, rW, rH);
rotateCanvas(rX + rW / 2, rY + rH / 2, -rA);
ctx.fill();
}
function drawLine(x1, y1, x2, y2) {
ctx.lineWidth = thickness;
ctx.strokeStyle = "#33dd33";
ctx.beginPath();
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.stroke();
}
function calcRectFromLine(x1, y1, x2, y2) {
const dx = x2 - x1;
const dy = y2 - y1;
const mag = Math.sqrt(dx * dx + dy * dy);
const angle = Math.atan2(dy, dx);
return { x: x1, y: y1, w: mag, h: thickness, a: angle };
}
drawLine(lineX1, lineY1, lineX2, lineY2);
const r = calcRectFromLine(lineX1, lineY1, lineX2, lineY2);
drawRectangle(r.x, r.y, r.w, r.h, r.a);
<canvas></canvas>
如果您 运行 代码,您会看到红色矩形不在绿线上方。我想以某种方式解决这个问题。
我认为唯一需要修复的函数是 calcRectFromLine
。理想情况下,return 一个矩形,当传递给 drawRectangle
时,会导致绿线不再可见,因为它会被红色矩形完全覆盖。
我还认为我需要使用某种 sin
和 cos
来抵消红色矩形,但我不确定完成该操作的确切数学。
您使用旋转线的坐标计算矩形的左侧和顶部不正确。更正:
return { x: (x1+x2)/2 - mag/2, y: (y1+y2)/2 - thickness/2,
w: mag, h: thickness, a: angle };`
const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
const thickness = 7;
const lineX1 = 25, lineY1 = 50;
const lineX2 = 100, lineY2 = 100;
function rotateCanvas(x, y, a) {
ctx.translate(x, y);
ctx.rotate(a);
ctx.translate(-x, -y);
}
function drawRectangle(rX, rY, rW, rH, rA, color) {
ctx.beginPath();
ctx.fillStyle = "#dd3333";
rotateCanvas(rX + rW / 2, rY + rH / 2, rA);
ctx.rect(rX, rY, rW, rH);
rotateCanvas(rX + rW / 2, rY + rH / 2, -rA);
ctx.fill();
}
function drawLine(x1, y1, x2, y2) {
ctx.lineWidth = thickness;
ctx.strokeStyle = "#33dd33";
ctx.beginPath();
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.stroke();
}
function calcRectFromLine(x1, y1, x2, y2) {
const dx = x2 - x1;
const dy = y2 - y1;
const mag = Math.sqrt(dx * dx + dy * dy);
const angle = Math.atan2(dy, dx);
return { x: (x1+x2)/2 - mag/2, y: (y1+y2)/2 - thickness/2, w: mag, h: thickness, a: angle };
}
drawLine(lineX1, lineY1, lineX2, lineY2);
const r = calcRectFromLine(lineX1, lineY1, lineX2, lineY2);
drawRectangle(r.x, r.y, r.w, r.h, r.a);
<canvas><\canvas>
假设我有一行表格:x1, y1, x2, y2
和给定的 thickness
.
我正在寻找一种方法将该线转换为围绕其原点旋转的矩形,这样如果您将它们都绘制在 canvas 上,它们将完全重叠。
我已经完全重现了我面临的问题:
const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
const thickness = 7;
const lineX1 = 25, lineY1 = 50;
const lineX2 = 100, lineY2 = 100;
function rotateCanvas(x, y, a) {
ctx.translate(x, y);
ctx.rotate(a);
ctx.translate(-x, -y);
}
function drawRectangle(rX, rY, rW, rH, rA, color) {
ctx.beginPath();
ctx.fillStyle = "#dd3333";
rotateCanvas(rX + rW / 2, rY + rH / 2, rA);
ctx.rect(rX, rY, rW, rH);
rotateCanvas(rX + rW / 2, rY + rH / 2, -rA);
ctx.fill();
}
function drawLine(x1, y1, x2, y2) {
ctx.lineWidth = thickness;
ctx.strokeStyle = "#33dd33";
ctx.beginPath();
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.stroke();
}
function calcRectFromLine(x1, y1, x2, y2) {
const dx = x2 - x1;
const dy = y2 - y1;
const mag = Math.sqrt(dx * dx + dy * dy);
const angle = Math.atan2(dy, dx);
return { x: x1, y: y1, w: mag, h: thickness, a: angle };
}
drawLine(lineX1, lineY1, lineX2, lineY2);
const r = calcRectFromLine(lineX1, lineY1, lineX2, lineY2);
drawRectangle(r.x, r.y, r.w, r.h, r.a);
<canvas></canvas>
如果您 运行 代码,您会看到红色矩形不在绿线上方。我想以某种方式解决这个问题。
我认为唯一需要修复的函数是 calcRectFromLine
。理想情况下,return 一个矩形,当传递给 drawRectangle
时,会导致绿线不再可见,因为它会被红色矩形完全覆盖。
我还认为我需要使用某种 sin
和 cos
来抵消红色矩形,但我不确定完成该操作的确切数学。
您使用旋转线的坐标计算矩形的左侧和顶部不正确。更正:
return { x: (x1+x2)/2 - mag/2, y: (y1+y2)/2 - thickness/2,
w: mag, h: thickness, a: angle };`
const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
const thickness = 7;
const lineX1 = 25, lineY1 = 50;
const lineX2 = 100, lineY2 = 100;
function rotateCanvas(x, y, a) {
ctx.translate(x, y);
ctx.rotate(a);
ctx.translate(-x, -y);
}
function drawRectangle(rX, rY, rW, rH, rA, color) {
ctx.beginPath();
ctx.fillStyle = "#dd3333";
rotateCanvas(rX + rW / 2, rY + rH / 2, rA);
ctx.rect(rX, rY, rW, rH);
rotateCanvas(rX + rW / 2, rY + rH / 2, -rA);
ctx.fill();
}
function drawLine(x1, y1, x2, y2) {
ctx.lineWidth = thickness;
ctx.strokeStyle = "#33dd33";
ctx.beginPath();
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.stroke();
}
function calcRectFromLine(x1, y1, x2, y2) {
const dx = x2 - x1;
const dy = y2 - y1;
const mag = Math.sqrt(dx * dx + dy * dy);
const angle = Math.atan2(dy, dx);
return { x: (x1+x2)/2 - mag/2, y: (y1+y2)/2 - thickness/2, w: mag, h: thickness, a: angle };
}
drawLine(lineX1, lineY1, lineX2, lineY2);
const r = calcRectFromLine(lineX1, lineY1, lineX2, lineY2);
drawRectangle(r.x, r.y, r.w, r.h, r.a);
<canvas><\canvas>