簡體   English   中英

如何判斷一個點是否屬於某一行?

[英]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值是否等於x1x2 另外,檢查點的X不是'x1'或'x2'。

我剛剛寫了一個函數來處理一些額外的要求,因為我在繪圖應用程序中使用了這個檢查:

  • 模糊性 - 必須有一些錯誤的余地,因為該功能用於通過單擊來選擇線條。
  • 該線有一個EndPoint和一個StartPoint,沒有無限的線。
  • 必須處理直的垂直和水平線,(x2 - x1)== 0導致在其他答案中除以零。
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.此解決方案與其他方案相比具有幾個相關的優點:首先,它不需要垂直線的特殊情況,第二,它不分(通常是慢速操作),第三,當線幾乎但不是很垂直時,它不會觸發不良的浮點行為。

給出L0L1線上的兩個點以及測試P的點。

               (L1 - L0) * (P - L0)
n = (P - L0) - --------------------- (L1 - L0)
               (L1 - L0) * (L1 - L0)

向量n的范數是點P從線到L0L1的距離。 如果該距離為零或足夠小(在舍入誤差的情況下),則該點位於該線上。

符號*表示點積。

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中的等式來表示,這里是眾所周知的等式

y-y1 =(y1-y2)/(x1-x2)(x-x1)

現在想象你的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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM