如果我有一条线,有点x,y,endx和endy,我如何检测另一个点是否在线上?一个简单的等式,或JavaScript或伪代码中的示例函数将是最有帮助的。
编辑: 这是我正在研究的游戏,我正在尝试检测激光是否与物体碰撞,以下是样本http://jefnull.com/references/lasers/最具描述性的文件是http://jefnull.com/references/lasers/lasers.js
答案 0 :(得分:12)
由于我之前的回答是如何确定一个点是否 该行,并且真正的问题似乎是“我怎么能判断该点是否 行段“,我正在添加新答案。
这是诀窍:首先找到障碍物到线段两个端点的距离。这两个距离不能唯一地确定障碍物的位置,但它们确实唯一地确定了具有三个特定边长的三角形,然后我们可以立即使用一堆几何体。
我摆弄了一点颜色。无论如何,我在上面的评论中提到你应该使用point-line distance公式来找到障碍物和线之间的距离。但那实际上并不奏效。原因是点 - 线距离。因此,对于下面的两个示例,公式将计算图片中的粗体距离 H 。
那不对!!
相反,这里是用于找到从障碍物到激光形成的线段的距离的伪代码:
Find the distance from my point to the line segment!
if the angle at (x,y) is obtuse
return A
else if the angle at (endx,endy) is obtuse
return B
else
return H
以下是可用于实现上述伪代码的数学运算:
(x,y)
处的角度是否为钝角,请查找B^2 > A^2 + C^2
。如果是这样,角度就会变钝。(endx, endy)
处的角度是否为钝角,请查找A^2 > B^2 + C^2
。如果是这样,角度就会变钝。H
,请使用两种不同的方法来查找三角形的区域 - 通常为base*height/2
和Heron's Formula。 这意味着你应该:
set s = (A+B+C)/2
The area of the triangle is C*H/2
The area of the triangle is also sqrt(s*(s-A)*(s-B)*(s-C))
So H = 2/C * sqrt(s*(s-A)*(s-B)*(s-C)).
最终结果如下:
if B^2 > A^2 + C^2
return A
else if A^2 > B^2 + C^2
return B
else
s = (A+B+C)/2
return 2/C * sqrt(s*(s-A)*(s-B)*(s-C))
我认为这应该足以让你完成你实际要做的事情。祝你好运,不要放弃!
答案 1 :(得分:7)
您想要检查点对之间的斜率是否相同。但是你应该注意不要除以零,所以检查方程的交叉乘法版本来检查。
更明确地说,如果您的积分是A = (Ax, Ay)
,B = (Bx, By)
,C = (Cx, Cy)
,那么您想检查一下
(Cy - Ay) / (Cx - Ax) = (By - Ay) / (Bx - Ax)
但你应该检查
(Cy - Ay) * (Bx - Ax) = (By - Ay) * (Cx - Ax).
答案 2 :(得分:2)
function isOnLine(x, y, endx, endy, px, py) {
var f = function(somex) { return (endy - y) / (endx - x) * (somex - x) + y; };
return Math.abs(f(px) - py) < 1e-6 // tolerance, rounding errors
&& px >= x && px <= endx; // are they also on this segment?
}
x, y, endx and endy
是定义线的点,使用它可以构建该线的等式。然后,填写px
并查看是否f(px) = py
(实际上由于舍入错误而检查得足够小)。最后,检查是否在x ... endx
区间定义了线段。
答案 3 :(得分:1)
根据直线方程y = mx + b,其中m是斜率,x是x轴处的点的值,b是y截距(线截距y轴的点)。
m(坡度)= endy - y / endx - x; 例如如果一条线从(0,0)开始并且结束(4,2)那么m = 4-0 / 2-0 = 2;
b(y截距)= 0;
现在例如,您将获得一个点(1,2),以查看它是否在线。好的,在x坐标的帮助下计算你的y坐标。即
y = mx + b
y = 2(1)+ 0; //这里x是给定点的x坐标 y = 2;这与您给定点的y坐标完全相同,因此我们可以得出结论。如果该点具有根据等式的值(2,2),则它将评估为y = 4,其不等于您给出的点的y坐标,因此它不在线上。
function isOnLine(initial_x, initial_y, endx, endy, pointx, pointy, tolerate) {
var slope = (endy-initial_y)/(endx-initial_x);
var y = slope * pointx + initial_y;
if((y <= pointy+tolerate && y >= pointy-tolerate) && (pointx >= initial_x && pointx <= endx)) {
return true;
}
return false;
}
答案 4 :(得分:1)
function is_point_on_segment (startPoint, checkPoint, endPoint) {
return ((endPoint.y - startPoint.y) * (checkPoint.x - startPoint.x)).toFixed(0) === ((checkPoint.y - startPoint.y) * (endPoint.x - startPoint.x)).toFixed(0) &&
((startPoint.x > checkPoint.x && checkPoint.x > endPoint.x) || (startPoint.x < checkPoint.x && checkPoint.x < endPoint.x)) &&
((startPoint.y >= checkPoint.y && checkPoint.y >= endPoint.y) || (startPoint.y <= checkPoint.y && checkPoint.y <= endPoint.y));
}
测试:
var startPoint = {x:30,y:30};
var checkPoint = {x:40,y:40};
var endPoint = {x:50,y:50};
console.log(is_point_on_segment(startPoint ,checkPoint ,endPoint ));
答案 5 :(得分:0)
设点为C(Cx,Cy),线为AB(Ax,Ay)至(Bx,By)。 设P是C在AB上的垂直投影点。参数 r表示P沿AB的位置,由点积计算 AC和AB除以AB长度的平方:
(1) AC dot AB
r = ---------
||AB||^2
r has the following meaning:
r=0 P = A
r=1 P = B
r<0 P is on the backward extension of AB
r>1 P is on the forward extension of AB
0<r<1 P is interior to AB
The length of a line segment in d dimensions, AB is computed by:
L = sqrt( (Bx-Ax)^2 + (By-Ay)^2 + ... + (Bd-Ad)^2)
so in 2D:
L = sqrt( (Bx-Ax)^2 + (By-Ay)^2 )
and the dot product of two vectors in d dimensions, U dot V is computed:
D = (Ux * Vx) + (Uy * Vy) + ... + (Ud * Vd)
so in 2D:
D = (Ux * Vx) + (Uy * Vy)
So (1) expands to:
(Cx-Ax)(Bx-Ax) + (Cy-Ay)(By-Ay)
r = -------------------------------
L^2
The point P can then be found:
Px = Ax + r(Bx-Ax)
Py = Ay + r(By-Ay)
And the distance from A to P = r*L.
Use another parameter s to indicate the location along PC, with the
following meaning:
s<0 C is left of AB
s>0 C is right of AB
s=0 C is on AB
Compute s as follows:
(Ay-Cy)(Bx-Ax)-(Ax-Cx)(By-Ay)
s = -----------------------------
L^2
Then the distance from C to P = |s|*L.
答案 6 :(得分:0)
这是我对isOnLine的实现
function isOnLine(a, b, p, tolerance) {
var dy = a.y - b.y;
var dx = a.x - b.x;
if(dy == 0) { //horizontal line
if(p.y == a.y) {
if(a.x > b.x) {
if(p.x <= a.x && p.x >= b.x)
return true;
}
else {
if(p.x >= a.x && p.x <= b.x)
return true;
}
}
}
else if(dx == 0) { //vertical line
if(p.x == a.x) {
if(a.y > b.y) {
if(p.y <= a.y && p.y >= b.y)
return true;
}
else {
if(p.y >= a.y && p.y <= b.y)
return true;
}
}
}
else { //slope line
var p = dy/dx;
var py = p * p.x;
if(py <= p.y + tolerance && py >= p.y - tolerance) {
if(a.x > b.x) {
if(p.x <= a.x && p.x >= b.x)
return true;
}
else {
if(p.x >= a.x && p.x <= b.x)
return true;
}
}
}
return false;
}