[英]How can I tell if a point belongs to a certain line?
如何判斷一個點是否屬於某一行?
如果可能的話,可以理解例子。
在最簡單的形式中,只需將坐標插入線方程並檢查是否相等。
鑒於:
Point p (X=4, Y=5)
Line l (Slope=1, YIntersect=1)
插入X和Y:
Y = Slope * X + YIntersect
=> 5 = 1 * 4 + 1
=> 5 = 5
所以,是的,重點是在線。
如果您的線條以(X1,Y1),(X2,Y2)形式表示,那么您可以使用以下公式計算坡度:
Slope = (y1 - y2) / (x1-x2)
然后得到Y-Intersect:
YIntersect = - Slope * X1 + Y1;
編輯:我修復了Y-Intersect(已經是X1 / Y1 ......)
你必須檢查x1 - x2
不是0
。 如果是,則檢查點是否在線是一個簡單的問題,檢查點中的Y值是否等於x1
或x2
。 另外,檢查點的X不是'x1'或'x2'。
我剛剛寫了一個函數來處理一些額外的要求,因為我在繪圖應用程序中使用了這個檢查:
private const double SELECTION_FUZZINESS = 3;
internal override bool ContainsPoint(Point point)
{
LineGeometry lineGeo = geometry as LineGeometry;
Point leftPoint;
Point rightPoint;
// Normalize start/end to left right to make the offset calc simpler.
if (lineGeo.StartPoint.X <= lineGeo.EndPoint.X)
{
leftPoint = lineGeo.StartPoint;
rightPoint = lineGeo.EndPoint;
}
else
{
leftPoint = lineGeo.EndPoint;
rightPoint = lineGeo.StartPoint;
}
// If point is out of bounds, no need to do further checks.
if (point.X + SELECTION_FUZZINESS < leftPoint.X || rightPoint.X < point.X - SELECTION_FUZZINESS)
return false;
else if (point.Y + SELECTION_FUZZINESS < Math.Min(leftPoint.Y, rightPoint.Y) || Math.Max(leftPoint.Y, rightPoint.Y) < point.Y - SELECTION_FUZZINESS)
return false;
double deltaX = rightPoint.X - leftPoint.X;
double deltaY = rightPoint.Y - leftPoint.Y;
// If the line is straight, the earlier boundary check is enough to determine that the point is on the line.
// Also prevents division by zero exceptions.
if (deltaX == 0 || deltaY == 0)
return true;
double slope = deltaY / deltaX;
double offset = leftPoint.Y - leftPoint.X * slope;
double calculatedY = point.X * slope + offset;
// Check calculated Y matches the points Y coord with some easing.
bool lineContains = point.Y - SELECTION_FUZZINESS <= calculatedY && calculatedY <= point.Y + SELECTION_FUZZINESS;
return lineContains;
}
確定點R =(rx,ry)是否位於連接點P =(px,py)和Q =(qx,qy)的線上的最佳方法是檢查矩陣的行列式
{{qx - px, qy - py}, {rx - px, ry - py}},
即(qx - px)*(ry - py) - (qy - py)*(rx - px)接近0.此解決方案與其他方案相比具有幾個相關的優點:首先,它不需要垂直線的特殊情況,第二,它不分(通常是慢速操作),第三,當線幾乎但不是很垂直時,它不會觸發不良的浮點行為。
給出L0
和L1
線上的兩個點以及測試P
的點。
(L1 - L0) * (P - L0)
n = (P - L0) - --------------------- (L1 - L0)
(L1 - L0) * (L1 - L0)
向量n
的范數是點P
從線到L0
和L1
的距離。 如果該距離為零或足夠小(在舍入誤差的情況下),則該點位於該線上。
符號*
表示點積。
例
P = (5, 5)
L0 = (0, 10)
L1 = (20, -10)
L1 - L0 = (20, -20)
P - L0 = (5, -5)
(20, -20) * (5, -5)
n = (5, -5) - --------------------- (20, -20)
(20, -20) * (20, -20)
200
= (5, -5) - --- (20, -20)
800
= (5, -5) - (5, -5)
= (0, 0)
我認為帕特里克麥克唐納先生提出了幾乎正確的答案,這是對他答案的更正:
public bool IsOnLine(Point endPoint1, Point endPoint2, Point checkPoint)
{
return (((double)checkPoint.Y - endPoint1.Y)) / ((double)(checkPoint.X - endPoint1.X))
== ((double)(endPoint2.Y - endPoint1.Y)) / ((double)(endPoint2.X - endPoint1.X));
}
當然還有許多其他正確答案,尤其是Mr.Josh,但我發現這是最好的答案。
感謝evryone。
y = m * x + c
這是一條線的等式。 x&y是坐標。 每條線的特征在於其斜率(m)和與y軸(c)相交的位置。
因此,給定一條線的m&c,你可以通過檢查方程是否適用於x = x1和y = y1來確定點(x1,y1)是否在線上
如果您的端點定義了一條線
PointF pt1, pt2;
你有一個想要檢查的觀點
PointF checkPoint;
然后你可以定義一個函數如下:
bool IsOnLine(PointF endPoint1, PointF endPoint2, PointF checkPoint)
{
return (checkPoint.Y - endPoint1.Y) / (endPoint2.Y - endPoint1.Y)
== (checkPoint.X - endPoint1.X) / (endPoint2.X - endPoint1.X);
}
並將其稱為如下:
if (IsOnLine(pt1, pt2, checkPoint) {
// Is on line
}
您需要檢查除以零。
2D線通常使用兩個變量x和y中的等式來表示,這里是眾所周知的等式
現在想象你的GDI +線是從(0,0)到(100,100),然后是m =(0-100)/(0-100)= 1的值,因此你的線的等式是y-0 = 1 *(x-0)=> y = x
既然我們有一個有問題的線的等式,它很容易測試一個點是否屬於這一行。 如果在替換x = x3和y = y3時滿足線方程,則給定點(x3,y3)屬於此線。 例如,點(10,10)屬於這一行,因為10 = 10但是(10,12)不屬於這一行,因為12!= 10。
注意:對於垂直線,斜率(m)的值是無限的,但對於這種特殊情況,您可以直接使用垂直線的公式x = c,其中c = x1 = x2。
雖然我不得不說我不確定這是否是最有效的方法。 當我有更多時間時,我會嘗試找到一種更有效的方法。
希望這可以幫助。
該方程是:
y = mx + c
因此,如果滿足該等式,即b = ma + c
,則該點(a,b)在該線上
作為slope/y-intercept
方法的替代方法,我使用Math.Atan2
選擇了這種方法:
// as an extension method
public static bool Intersects(this Vector2 v, LineSegment s) {
// check from line segment start perspective
var reference = Math.Atan2(s.Start.Y - s.End.Y, s.Start.X - s.End.X);
var aTanTest = Math.Atan2(s.Start.Y - v.Y, s.Start.X - v.X);
// check from line segment end perspective
if (reference == aTanTest) {
reference = Math.Atan2(s.End.Y - s.Start.Y, s.End.X - s.Start.X);
aTanTest = Math.Atan2(s.End.Y - v.Y, s.End.X - v.X);
}
return reference == aTanTest;
}
第一個檢查reference
確定從線段起點到其終點的arcTan。 然后從起點角度,我們確定arcTan到向量v
。
如果這些值相等,我們從終點的角度進行檢查。
簡單,處理水平,垂直和其他所有。
你可以再詳細一點嗎?
你在談論什么編程語言?
你在說什么環境?
你在說什么“線”? 文本? 什么點? 屏幕上的XY?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.