获取矩形角的点
Get the points for the corners of a rectangle
我得到了一个矩形的点数组,从左上角位置开始顺时针排序到每个角。我需要找到从角落到矩形每一边的每个特定角落长度的直线的起点和终点。我的代码将点旋转某个随机角度只是为了说明问题,但在我的实际场景中我只有角点并且需要起点和终点来映射每个角。我目前正在偏移每个点,就好像使用方向值数组的点一样,当矩形不旋转时,该点与数组中点的顺序相匹配,但它不起作用,因为点可以在该点旋转顺序也变了。我确定我没有掌握正弦和余弦的应用。我怎样才能得到每个角点的值向它的每一边偏移一个给定的长度,以便所有的东西一起均匀地旋转?
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
函数来偏移相对于旋转角的点,但此时您没有角度值。所以你可以从旋转的边得到方向向量。
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)
,反之亦然,符号组合不同)
我得到了一个矩形的点数组,从左上角位置开始顺时针排序到每个角。我需要找到从角落到矩形每一边的每个特定角落长度的直线的起点和终点。我的代码将点旋转某个随机角度只是为了说明问题,但在我的实际场景中我只有角点并且需要起点和终点来映射每个角。我目前正在偏移每个点,就好像使用方向值数组的点一样,当矩形不旋转时,该点与数组中点的顺序相匹配,但它不起作用,因为点可以在该点旋转顺序也变了。我确定我没有掌握正弦和余弦的应用。我怎样才能得到每个角点的值向它的每一边偏移一个给定的长度,以便所有的东西一起均匀地旋转?
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
函数来偏移相对于旋转角的点,但此时您没有角度值。所以你可以从旋转的边得到方向向量。
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)
,反之亦然,符号组合不同)