笛卡尔坐标算法b题
Cartesian coordinates algorithmb question
在二维网格上,有一个直角坐标C(Cx,Cy),它是正方形的中心,半径为'b'。
并且有两个点P1(x1,y1), P2(x2,y2)。当我直接用线连接P1和P2时,应该是一条直线。
我想做一个伪代码来检测P1和P2之间的直线是否在正方形区域
参数将是中心点和两个不同的点和半径。
正方形中心:(Cx,Cy)
两点:P1(x1,y1), P2(x2,y2)
半径:'b'
函数直线 ((x1,y1),(x2,y2),(Cx,Cy),b)
如果直线不在正方形区域上,它应该return true,如果它在正方形区域上,它应该return false。
您可以将此问题(通过投影坐标)转换为位于 (0, 0) 的正方形 "radius" 1.
判断线段(p1,p2)是否穿过正方形的顶边,可以先测试这些条件:
(y2 - 1) * (y2 - 1) > 0. 如果这是真的,表示线段完全在正方形顶部之上,或者完全在正方形顶部之下。
y1 = y2。如果为真,则线段与正方形平行。
在所有其他情况下,交点的 x 坐标为:
x = x1 - y1 * (x2 - x1) / (y2 - y1)
如果这个x不在[-1, 1]范围内,则线段不与正方形顶部相交
其他三边也可以做类似的操作
如果其中任何一个给出了 [-1, 1] 范围内的交点坐标,函数 straight
应该 return true
,否则 false
。
这是一个交互式 JavaScript 实现,您可以使用它在正方形附近绘制线段(通过 "dragging" 鼠标)。当调用 straight
returns true
:
时,方块将突出显示
function intersectionWithXaxis(x1, y1, x2, y2) {
if (y1 * y2 > 0 || y1 === y2) return Infinity; // No intersection
return x1 - y1 * (x2 - x1) / (y2 - y1); // x-coordinate of intersection
}
function straight(x1, y1, x2, y2, cx, cy, b) {
// Project the coordinates so the square is at (0, 0) with "radius" 1
x1 = (x1-cx)/b;
y1 = (y1-cy)/b;
x2 = (x2-cx)/b;
y2 = (y2-cy)/b;
let z;
// Get intersections with top, bottom, left and right side of box:
z = intersectionWithXaxis(x1, y1-1, x2, y2-1);
if (Math.abs(z) <= 1) return true;
z = intersectionWithXaxis(x1, y1+1, x2, y2+1);
if (Math.abs(z) <= 1) return true;
// We can use the same function for vertical line intersections by swapping x and y
z = intersectionWithXaxis(y1, x1-1, y2, x2-1);
if (Math.abs(z) <= 1) return true;
z = intersectionWithXaxis(y1, x1+1, y2, x2+1);
if (Math.abs(z) <= 1) return true;
return false;
}
let cx = 100;
let cy = 60;
let b = 30;
let x1, y1, x2, y2;
// I/O handling
let canvas = document.querySelector("canvas");
let ctx = canvas.getContext("2d");
ctx.fillStyle = "yellow";
let isMouseDown = false;
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
ctx.rect(cx-b, cy-b, 2*b, 2*b);
ctx.stroke();
if (!isMouseDown) return;
// Call the main function. If true, highlight the square
if (straight(x1, y1, x2, y2, cx, cy, b)) ctx.fill();
ctx.beginPath();
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.stroke();
}
canvas.addEventListener("mousedown", function(e) {
x1 = e.clientX - this.offsetLeft;
y1 = e.clientY - this.offsetTop;
isMouseDown = true;
});
canvas.addEventListener("mousemove", function(e) {
if (!isMouseDown) return;
x2 = e.clientX - this.offsetLeft;
y2 = e.clientY - this.offsetTop;
draw();
});
canvas.addEventListener("mouseup", function(e) {
isMouseDown = false;
});
draw();
<canvas width="400" height="180"></canvas>
在二维网格上,有一个直角坐标C(Cx,Cy),它是正方形的中心,半径为'b'。
并且有两个点P1(x1,y1), P2(x2,y2)。当我直接用线连接P1和P2时,应该是一条直线。
我想做一个伪代码来检测P1和P2之间的直线是否在正方形区域
参数将是中心点和两个不同的点和半径。
正方形中心:(Cx,Cy)
两点:P1(x1,y1), P2(x2,y2)
半径:'b'
函数直线 ((x1,y1),(x2,y2),(Cx,Cy),b)
如果直线不在正方形区域上,它应该return true,如果它在正方形区域上,它应该return false。
您可以将此问题(通过投影坐标)转换为位于 (0, 0) 的正方形 "radius" 1.
判断线段(p1,p2)是否穿过正方形的顶边,可以先测试这些条件:
(y2 - 1) * (y2 - 1) > 0. 如果这是真的,表示线段完全在正方形顶部之上,或者完全在正方形顶部之下。
y1 = y2。如果为真,则线段与正方形平行。
在所有其他情况下,交点的 x 坐标为:
x = x1 - y1 * (x2 - x1) / (y2 - y1)
如果这个x不在[-1, 1]范围内,则线段不与正方形顶部相交
其他三边也可以做类似的操作
如果其中任何一个给出了 [-1, 1] 范围内的交点坐标,函数 straight
应该 return true
,否则 false
。
这是一个交互式 JavaScript 实现,您可以使用它在正方形附近绘制线段(通过 "dragging" 鼠标)。当调用 straight
returns true
:
function intersectionWithXaxis(x1, y1, x2, y2) {
if (y1 * y2 > 0 || y1 === y2) return Infinity; // No intersection
return x1 - y1 * (x2 - x1) / (y2 - y1); // x-coordinate of intersection
}
function straight(x1, y1, x2, y2, cx, cy, b) {
// Project the coordinates so the square is at (0, 0) with "radius" 1
x1 = (x1-cx)/b;
y1 = (y1-cy)/b;
x2 = (x2-cx)/b;
y2 = (y2-cy)/b;
let z;
// Get intersections with top, bottom, left and right side of box:
z = intersectionWithXaxis(x1, y1-1, x2, y2-1);
if (Math.abs(z) <= 1) return true;
z = intersectionWithXaxis(x1, y1+1, x2, y2+1);
if (Math.abs(z) <= 1) return true;
// We can use the same function for vertical line intersections by swapping x and y
z = intersectionWithXaxis(y1, x1-1, y2, x2-1);
if (Math.abs(z) <= 1) return true;
z = intersectionWithXaxis(y1, x1+1, y2, x2+1);
if (Math.abs(z) <= 1) return true;
return false;
}
let cx = 100;
let cy = 60;
let b = 30;
let x1, y1, x2, y2;
// I/O handling
let canvas = document.querySelector("canvas");
let ctx = canvas.getContext("2d");
ctx.fillStyle = "yellow";
let isMouseDown = false;
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
ctx.rect(cx-b, cy-b, 2*b, 2*b);
ctx.stroke();
if (!isMouseDown) return;
// Call the main function. If true, highlight the square
if (straight(x1, y1, x2, y2, cx, cy, b)) ctx.fill();
ctx.beginPath();
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.stroke();
}
canvas.addEventListener("mousedown", function(e) {
x1 = e.clientX - this.offsetLeft;
y1 = e.clientY - this.offsetTop;
isMouseDown = true;
});
canvas.addEventListener("mousemove", function(e) {
if (!isMouseDown) return;
x2 = e.clientX - this.offsetLeft;
y2 = e.clientY - this.offsetTop;
draw();
});
canvas.addEventListener("mouseup", function(e) {
isMouseDown = false;
});
draw();
<canvas width="400" height="180"></canvas>