我得到了一个矩形的点数组,从左上角位置到每个 Angular 顺时针排序。我需要找到从矩形的 Angular 到每条边的每个特定 Angular 长度的线的起点和终点。我的代码将点旋转一些随机 Angular 只是为了说明问题,但在我的实际场景中,我只有 Angular 点,需要起点和终点来绘制每个 Angular 。我目前正在偏移每个点,就好像使用方向值数组的点在矩形未旋转时与数组中点的顺序匹配,但它不起作用,因为可以在该点旋转点顺序也会改变。我确信我无法掌握正弦和余弦的应用。如何获得每个 Angular 点的值,该值向其每条边偏移给定的长度,以便所有东西都均匀地一起旋转?
function rotate(cx, cy, x, y, angle) {
var radians = (Math.PI / 180) * angle,
cos = Math.cos(radians),
sin = Math.sin(radians),
nx = (cos * (x - cx)) + (sin * (y - cy)) + cx,
ny = (cos * (y - cy)) - (sin * (x - cx)) + cy;
return {x: nx, y: ny};
}
const colors =["red","blue", "green","black"];
const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
let centroid = {};
let points = [{x:30,y:30},{x:110, y:30},{x:110,y:110},{x:30, y:110}];
function update() {
const randAngle = Math.random() * 180 * (Math.random() > 0.5 ? -1:1);
const length = points.length;
centroid = points.reduce((last, current)=> {
last.x += current.x / length;
last.y += current.y / length;
return last;
}, {x: 0, y:0});
points =
points.map(point=> rotate(centroid.x,
centroid.y,
point.x,
point.y,
randAngle));
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
// draw centroid
ctx.beginPath();
ctx.arc(centroid.x, centroid.y, 4, 0, Math.PI * 2);
ctx.stroke();
// draw Square
ctx.beginPath();
ctx.moveTo(points[0].x, points[0].y);
for(let i=1;i<points.length;i++) {
ctx.lineTo(points[i].x, points[i].y);
}
ctx.closePath();
ctx.stroke();
// draw corner points
for(let i=0;i < points.length;i++) {
ctx.beginPath();
ctx.fillStyle = colors[i%colors.length];
ctx.arc(points[i].x, points[i].y, 3, 0, Math.PI * 2);
ctx.fill();
}
const cornerLength = 10;
const startPointDirections = [{ x: 0, y: 1 },
{ x: -1, y: 0 },
{ x: 0, y: -1 },
{ x: 1, y: 0 }];
const endPointDirections = [{ x: 1, y: 0 },
{ x: 0, y: 1 },
{ x: -1, y: 0 },
{ x: 0, y: -1 }];
// draw corner start points and endpoints
for(let i=0;i < points.length;i++) {
ctx.beginPath();
ctx.fillStyle = colors[i%colors.length];
ctx.arc(startPointDirections[i].x * cornerLength + points[i].x, startPointDirections[i].y * cornerLength + points[i].y, 3, 0, Math.PI * 2);
ctx.arc(endPointDirections[i].x * cornerLength + points[i].x, endPointDirections[i].y * cornerLength + points[i].y, 3, 0, Math.PI * 2);
ctx.fill();
}
}
setInterval(()=> {
update();
draw();
}, 2000);
<canvas></canvas>
最佳答案
似乎您需要将rotate
函数应用于相对于旋转 Angular 的偏移点,但此时您没有 Angular 值。所以你可以从旋转的边获得方向向量。
function rotate(cx, cy, x, y, angle) {
var radians = (Math.PI / 180) * angle,
cos = Math.cos(radians),
sin = Math.sin(radians),
nx = (cos * (x - cx)) + (sin * (y - cy)) + cx,
ny = (cos * (y - cy)) - (sin * (x - cx)) + cy;
return {x: nx, y: ny};
}
const colors =["red","blue", "green","black"];
const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
let centroid = {};
let points = [{x:30,y:30},{x:110, y:30},{x:110,y:110},{x:30, y:110}];
function update() {
const randAngle = Math.random() * 180 * (Math.random() > 0.5 ? -1:1);
const length = points.length;
centroid = points.reduce((last, current)=> {
last.x += current.x / length;
last.y += current.y / length;
return last;
}, {x: 0, y:0});
points =
points.map(point=> rotate(centroid.x,
centroid.y,
point.x,
point.y,
randAngle));
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
// draw centroid
ctx.beginPath();
ctx.arc(centroid.x, centroid.y, 4, 0, Math.PI * 2);
ctx.stroke();
// draw Square
ctx.beginPath();
ctx.moveTo(points[0].x, points[0].y);
for(let i=1;i<points.length;i++) {
ctx.lineTo(points[i].x, points[i].y);
}
ctx.closePath();
ctx.stroke();
// draw corner points
for(let i=0;i < points.length;i++) {
ctx.beginPath();
ctx.fillStyle = colors[i%colors.length];
ctx.arc(points[i].x, points[i].y, 3, 0, Math.PI * 2);
ctx.fill();
}
const cornerLength = 10;
// draw corner start points and endpoints
for(let i=0;i < points.length;i++) {
ctx.beginPath();
ctx.fillStyle = colors[i%colors.length];
let dx = points[i].x - points[(i+3)%4].x //previous index in cyclic manner
let dy = points[i].y - points[(i+3)%4].y
let len = Math.sqrt(dx*dx+dy*dy) //really you know side length so use known value
dx = cornerLength * dx/len //normalized vector multiplied by magnitude
dy = cornerLength * dy/len
startx = points[i].x + dx
starty = points[i].y + dy
endx = points[i].x + dy //here apply rotated by -Pi/2 offset vector
endy = points[i].y - dx
ctx.arc(startx, starty, 3, 0, Math.PI * 2);
ctx.arc(endx, endy, 3, 0, Math.PI * 2);
ctx.fill();
}
}
setInterval(()=> {
update();
draw();
}, 2000);
<canvas></canvas>
(实际上,dx/len
和 dy/len
等于 cos(angle)
和 sin(angle )
或反之亦然,使用不同的符号组合)
关于javascript - 获取矩形的 Angular 点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70934872/