[英]See if a point lies on a line(vector)
我的程序中目前有以下行。 我還有另外兩個整數變量, x
和y
。
我想看看這個新點(x, y)
是否在這條線上。 我一直在看以下線程:
我想出了以下幾點:
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!
}
}
似乎沒有用,還是這個想法不對勁?
浮點數的精度有限,因此您會從計算中得出舍入誤差,結果在數學上應該相等的值最終會略有不同。
您需要比較一個小的容錯度:
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!
}
如果您的輸入是整數,足夠小以至於乘法不會溢出,那么根本就不需要浮點運算。
解決此問題的有效方法是使用三角形的有符號區域。 當由點{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}
。
首先,您需要計算直線方程。 然后查看該方程式對您擁有的x和y的值是否成立。 要計算您的直線方程,您需要計算出它在y軸上的位置以及其梯度是多少。 該方程的形式為y = mx + c,其中m為梯度,c為“截距”(其中線與y軸交叉)。
對於浮點值,請不要使用==,而應測試微小差異:
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) { ... }
( 增量應為小數,具體取決於您期望的精度。)
鑒於(x,y)實際上是一個要點,這項工作似乎比您要完成的要簡單一些。
您可能首先要檢查一條完美的水平或垂直線。 在那種情況下,您只需檢查x
是否落在x1
和x2
之間(或y
在垂直方向上在y1
和y2
之間)。
否則,您可以在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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.