我的程序中目前有以下行。我有两个其他整数变量x
和y
。
我希望看到这一新点(x, y)
是否在这一行上。我一直在看以下帖子:
Given a start and end point, and a distance, calculate a point along a line
我想出了以下内容:
if(x >= x1 && x <= x2 && (y >= y1 && y <= y2 || y <= y1 && y >= y2))
{
float vx = x2 - x1;
float vy = y2 - y1;
float mag = sqrt(vx*vx + vy*vy);
// need to get the unit vector (direction)
float dvx = vx/mag; // this would be the unit vector (direction) x for the line
float dvy = vy/mag; // this would be the unit vector (direction) y for the line
float vcx = x - x1;
float vcy = y - y1;
float magc = sqrt(vcx*vcx + vcy*vcy);
// need to get the unit vector (direction)
float dvcx = vcx/magc; // this would be the unit vector (direction) x for the point
float dvcy = vcy/magc; // this would be the unit vector (direction) y for the point
// I was thinking of comparing the direction of the two vectors, if they are the same then the point must lie on the line?
if(dvcx == dvx && dvcy == dvy)
{
// the point is on the line!
}
}
它似乎没有工作,或者这个想法是什么?
答案 0 :(得分:4)
浮点数的精度有限,因此您将从计算中得到舍入误差,结果是数学上应该相等的值最终会略有不同。
您需要与错误的小容差进行比较:
if (std::abs(dvcx-dvx) < tolerance && std::abs(dvcy-dvy) < tolerance)
{
// the point is (more or less) on the line!
}
困难的部分是选择那种宽容。如果你不能接受任何错误,那么你需要使用除固定精度浮点值以外的东西 - 也许是整数,重新安排计算以避免分裂和其他不精确的操作。
在任何情况下,你都可以更简单地做到这一点,没有像平方根这样的东西。你想知道两个向量是否平行;如果矢量乘积为零,或等效地,如果它们具有相等的切线,则它们是。所以你只需要
if (vx * vcy == vy * vcx) // might still need a tolerance for floating-point
{
// the point is on the line!
}
如果你的输入是整数,小到足以使乘法不会溢出,那么就根本不需要浮点运算。
答案 1 :(得分:1)
解决此问题的有效方法是使用三角形的有符号区域。当点{x1,y1}
,{x2,y2}
和{x,y}
创建的三角形的有符号区域接近于零时,您可以认为{x,y}
在线上。正如其他人所提到的,如果使用浮点值,选择一个良好的容差值是其中的一个重要部分。
bool isPointOnLine (xy p1, xy p2, xy p3) // returns true if p3 is on line p1, p2
{
xy va = p1 - p2;
xy vb = p3 - p2;
area = va.x * vb.y - va.y * vb.x;
if (abs (area) < tolerance)
return true;
return false;
}
这会告诉您{x,y}
是否在线上,但不会确定线段是否包含{x,y}
。为此,您还需要针对线段的边界检查{x,y}
。
答案 2 :(得分:0)
首先,您需要计算线的等式。然后看看这个等式是否适用于你拥有的x和y的值。要计算线的方程,需要计算出它与y轴交叉的位置以及它的梯度。方程将是y = mx + c的形式,其中m是梯度,c是截距&#39; (该线穿过y轴)。
答案 3 :(得分:0)
对于浮动值,不要使用==,而是测试小差异:
if (fabs(dvcx-dvx) < delta && fabs(dvcy-dvy) < delta)
另外,你真的不需要单位矢量,只需切线:
float originalTangent = (y2 - y1) / (x2 - x1);
float newTangent = (y - y1) / (x - x1);
if (fabs(newTangent - originalTangent) < delta) { ... }
( delta 应该是一些小数字,取决于您期望的准确度。)
答案 4 :(得分:0)
鉴于(x,y)实际上是一个点,这项工作似乎比你做的更简单。
您可能希望首先检查完美的水平线或垂直线。在这些情况下,您只需检查x
是否介于x1
和x2
之间(或y
与y1
之间的y2
垂直)。< / p>
否则,您可以在x
上使用线性插值,看看它是否为y提供了正确的值(在一些可能的舍入容差范围内)。为此,您可以执行以下操作:
slope = (y2-y1)/(x2-x1);
if (abs(slope * (x - x1) - y) < tolerance)
// (x,y) is on the line
else
// (x,y) isn't on the line