提问人:Victor Lundgren 提问时间:10/29/2023 最后编辑:Victor Lundgren 更新时间:10/29/2023 访问量:35
旋转内矩形锚定在左上角,考虑大小
Rotate inner rectangles anchoring on top-left considering size
问:
所以我有一个矩形 R,锚定在它的左上角。在矩形内部,我有内部矩形,每个矩形都有宽度和高度。我有一个算法可以将 R 旋转 alpha 度,并且需要计算每个内部矩形的新左上角位置,但这些矩形没有旋转。
我有这个函数,可以计算内部矩形的新左上角坐标,但它不适用于不同大小的内部矩形。
static rotatePoint(x0, y0, xi, yi, degrees) {
// Calculate the coordinates of the point relative to the top-left corner of the box
let x = xi - x0;
let y = yi - y0;
const rad = degrees * (Math.PI/180);
const cos_rad = Math.cos(rad);
const sin_rad = Math.sin(rad);
// Calculate the transformed coordinates after rotation
let qx = x0 + cos_rad * x + sin_rad * y
let qy = y0 + -sin_rad * x + cos_rad * y
return { x: qx, y: qy };
}
例如,下图显示了一个 0º 的阵型,有 5 个内部矩形,一个是宽度和高度 ~2,四个是宽度和高度 ~1。红点代表原点,它是恒定的。
将编队旋转 90º,我得到以下结果:
请注意,如果 2x2 矩形的大小为 1x1,则该矩形的左上角坐标位于应有的位置。考虑到每个内部矩形的大小,我如何调整该函数以正确计算每个内部矩形的位置?
编辑: 这不是普通的 Javascript,它是针对 foundry vtt 的,但由于问题与 foundrt vtt 本身无关,我觉得这样标记它会使它变得不必要的利基。
内部矩形实际上从原点矩形中心开始,但它也不会改变计算。我正在更改一些铸造厂特定的属性,但这里有一个片段,它给出了与 froundy 相同的输出:
编辑2:我已将该片段替换为视觉片段。
class Rect {
static rotateUnit(origin, inner, direction) {
const angle = origin.rotation + ((direction > 0) ? 45 : -45);
const delta_angle = origin.rotation - angle;
origin.rotation = angle
const box_x = origin.x + (origin.width / 2);
const box_y = origin.y + (origin.height / 2);
for (var i of inner) {
var new_pos = Rect.rotatePoint(box_x, box_y,
i.x,
i.y,
delta_angle);
i.x = new_pos.x;
i.y = new_pos.y;
}
}
static rotatePoint(x0, y0, xi, yi, degrees) {
// Calculate the coordinates of the point relative to the top-left corner of the box
let x = xi - x0;
let y = yi - y0;
const rad = degrees * (Math.PI/180);
const cos_rad = Math.cos(rad);
const sin_rad = Math.sin(rad);
// Calculate the transformed coordinates after rotation
let qx = x0 + cos_rad * x + sin_rad * y
let qy = y0 + -sin_rad * x + cos_rad * y
return { x: qx, y: qy };
}
static printCoordinates(origin, inner, offset) {
const ratio = 5
var canvas = document.getElementById("canvas");
if (canvas.getContext) {
var ctx = canvas.getContext("2d");
ctx.fillStyle = "rgb(0,0,0)";
ctx.fillRect(origin.x/ratio+offset/ratio, origin.y/ratio+offset/ratio, 70*origin.width/ratio, 70*origin.height/ratio);
ctx.fillStyle = "rgb(200,0,0)";
for (var i of inner) {
ctx.fillRect(i.x/ratio+offset/ratio, i.y/ratio+offset/ratio, 70*i.width/ratio, 70*i.height/ratio);
}
}
}
}
/*
* SIZE (WIDTH AND HEIGHT) CORRELATES TO
* PIXELS BY A CONSTANT OF 1:70
*/
const rect_origin = {
rotation: 0,
x: 2302.492125,
y: 1700.492125,
width: 0.9842500000000001,
height: 0.9842500000000001
}
const inner = [
{
x: 2336,
y: 1734,
width: 1.9685000000000001,
height: 1.9685000000000001
},
{
x: 2336,
y: 1872,
width: 0.9842500000000001,
height: 0.9842500000000001
},
{
x: 2405,
y: 1872,
width: 0.9842500000000001,
height: 0.9842500000000001
},
{
x: 2336,
y: 1941,
width: 0.9842500000000001,
height: 0.9842500000000001
},
{
x: 2405,
y: 1941,
width: 0.9842500000000001,
height: 0.9842500000000001
}
]
Rect.printCoordinates(rect_origin, inner, -1500);
Rect.rotateUnit(rect_origin, inner, 1);
Rect.printCoordinates(rect_origin, inner, -1100);
Rect.rotateUnit(rect_origin, inner, 1);
Rect.printCoordinates(rect_origin, inner, -700);
Rect.rotateUnit(rect_origin, inner, 1);
Rect.printCoordinates(rect_origin, inner, -300);
Rect.rotateUnit(rect_origin, inner, 1);
Rect.printCoordinates(rect_origin, inner, 100);
Rect.rotateUnit(rect_origin, inner, 1);
Rect.printCoordinates(rect_origin, inner, 500);
Rect.rotateUnit(rect_origin, inner, 1);
Rect.printCoordinates(rect_origin, inner, 900);
Rect.rotateUnit(rect_origin, inner, 1);
Rect.printCoordinates(rect_origin, inner, 1300);
<canvas id="canvas" width="1000" height="1000"></canvas>
答: 暂无答案
评论
box_x
box_y
x
y
width
height