简体   繁体   English

如何判断一个点是否属于某一行?

[英]How can I tell if a point belongs to a certain line?

How can I tell if a point belongs to a certain line? 如何判断一个点是否属于某一行?

Examples are appreciated, if possible. 如果可能的话,可以理解例子。

In the simplest form, just plug the coordinates into the line equation and check for equality. 在最简单的形式中,只需将坐标插入线方程并检查是否相等。

Given: 鉴于:

Point p (X=4, Y=5)
Line l (Slope=1, YIntersect=1)

Plug in X and Y: 插入X和Y:

   Y = Slope * X + YIntersect
=> 5 = 1 * 4 + 1
=> 5 = 5

So yes, the point is on the line. 所以,是的,重点是在线。

If your lines are represented in (X1,Y1),(X2,Y2) form, then you can calculate slope with: 如果您的线条以(X1,Y1),(X2,Y2)形式表示,那么您可以使用以下公式计算坡度:

 Slope = (y1 - y2) / (x1-x2)

And then get the Y-Intersect with this: 然后得到Y-Intersect:

 YIntersect = - Slope * X1 + Y1;

Edit: I fixed the Y-Intersect (which has been X1 / Y1 ...) 编辑:我修复了Y-Intersect(已经是X1 / Y1 ......)

You'll have to check that x1 - x2 is not 0 . 你必须检查x1 - x2不是0 If it is, then checking if the point is on the line is a simple matter of checking if the Y value in your point is equal to either x1 or x2 . 如果是,则检查点是否在线是一个简单的问题,检查点中的Y值是否等于x1x2 Also, check that the X of the point is not 'x1' or 'x2'. 另外,检查点的X不是'x1'或'x2'。

I just wrote an function which handles a few extra requirements since I use this check in a drawing application: 我刚刚写了一个函数来处理一些额外的要求,因为我在绘图应用程序中使用了这个检查:

  • Fuzziness - There must be some room for error since the function is used to select lines by clicking on them. 模糊性 - 必须有一些错误的余地,因为该功能用于通过单击来选择线条。
  • The line got an EndPoint and a StartPoint, no infinite lines. 该线有一个EndPoint和一个StartPoint,没有无限的线。
  • Must handle straight vertical and horizontal lines, (x2 - x1) == 0 causes division by zero in the other answers. 必须处理直的垂直和水平线,(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;            
}

The best way to determine if a point R = (rx, ry) lies on the line connecting points P = (px, py) and Q = (qx, qy) is to check whether the determinant of the matrix 确定点R =(rx,ry)是否位于连接点P =(px,py)和Q =(qx,qy)的线上的最佳方法是检查矩阵的行列式

{{qx - px, qy - py}, {rx - px, ry - py}},

namely (qx - px) * (ry - py) - (qy - py) * (rx - px) is close to 0. This solution has several related advantages over the others posted: first, it requires no special case for vertical lines, second, it doesn't divide (usually a slow operation), third, it doesn't trigger bad floating-point behavior when the line is almost, but not quite vertical. 即(qx - px)*(ry - py) - (qy - py)*(rx - px)接近0.此解决方案与其他方案相比具有几个相关的优点:首先,它不需要垂直线的特殊情况,第二,它不分(通常是慢速操作),第三,当线几乎但不是很垂直时,它不会触发不良的浮点行为。

Given two points on the line L0 and L1 and the point to test P . 给出L0L1线上的两个点以及测试P的点。

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

The norm of the vector n is the distance of the point P from the line through L0 and L1 . 向量n的范数是点P从线到L0L1的距离。 If this distance is zero or small enough (in the case of rounding errors), the point lies on the line. 如果该距离为零或足够小(在舍入误差的情况下),则该点位于该线上。

The symbol * represents the dot product. 符号*表示点积。

Example

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)

I think Mr.Patrick McDonald put the nearly correct answer and this is the correction of his answer: 我认为帕特里克麦克唐纳先生提出了几乎正确的答案,这是对他答案的更正:

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));
}

and of course there are many other correct answers especially Mr.Josh but i found this is the best one. 当然还有许多其他正确答案,尤其是Mr.Josh,但我发现这是最好的答案。

Thankx for evryone. 感谢evryone。

y = m * x + c

This is the equation of a line. 这是一条线的等式。 x & y are the co-ordinates. x&y是坐标。 Each line is characterized by its slope (m ) and where it intersects the y-axis (c). 每条线的特征在于其斜率(m)和与y轴(c)相交的位置。

So given m & c for a line, you can determine if the point (x1, y1) is on the line by checking if the equation holds for x = x1 and y = y1 因此,给定一条线的m&c,你可以通过检查方程是否适用于x = x1和y = y1来确定点(x1,y1)是否在线上

If you have a line defined by its endpoints 如果您的端点定义了一条线

PointF pt1, pt2;

and you have a point that you want to check 你有一个想要检查的观点

PointF checkPoint;

then you could define a function as follows: 然后你可以定义一个函数如下:

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);
}

and call it as follows: 并将其称为如下:

if (IsOnLine(pt1, pt2, checkPoint) {
    // Is on line
}

You will need to check for division by zero though. 您需要检查除以零。

A 2D line is generally represented using an equation in two variables x and y here is a well known equation 2D线通常使用两个变量x和y中的等式来表示,这里是众所周知的等式

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

Now imagine your GDI+ line is drawn from (0,0) to (100, 100) then the value of m=(0-100)/(0-100) = 1 thus the equation for your line is y-0=1*(x-0) => y=x 现在想象你的GDI +线是从(0,0)到(100,100),然后是m =(0-100)/(0-100)= 1的值,因此你的线的等式是y-0 = 1 *(x-0)=> y = x

Now that we have an equation for the line in question its easy to test if a point belongs to this line. 既然我们有一个有问题的线的等式,它很容易测试一个点是否属于这一行。 A given point (x3, y3) belongs to this line if it satisfies the line equation when you substitute x=x3 and y=y3. 如果在替换x = x3和y = y3时满足线方程,则给定点(x3,y3)属于此线。 For example the point (10, 10) belongs to this line since 10=10 but (10,12) does not belong to this line since 12 != 10. 例如,点(10,10)属于这一行,因为10 = 10但是(10,12)不属于这一行,因为12!= 10。

NOTE: For a vertical line the value of the slope (m) is infinite but for this special case you may use the equation for a vertical line directly x=c where c = x1 = x2. 注意:对于垂直线,斜率(m)的值是无限的,但对于这种特殊情况,您可以直接使用垂直线的公式x = c,其中c = x1 = x2。

Though I have to say I am not sure if this is the most efficient way of doing this. 虽然我不得不说我不确定这是否是最有效的方法。 I will try and find a more efficient way when I have some more time on hand. 当我有更多时间时,我会尝试找到一种更有效的方法。

Hope this helps. 希望这可以帮助。

Equation of the line is: 该方程是:

y = mx + c

So a point(a,b) is on this line if it satisfies this equation ie b = ma + c 因此,如果满足该等式,即b = ma + c ,则该点(a,b)在该线上

As an alternative to the slope/y-intercept method, I chose this approach using Math.Atan2 : 作为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;
}

The first check reference determines the arcTan from the start point of the line segment to it's end-point. 第一个检查reference确定从线段起点到其终点的arcTan。 Then from the start point perspective, we determine the arcTan to the vector v . 然后从起点角度,我们确定arcTan到向量v

If those values are equal, we check from the perspective of the end-point. 如果这些值相等,我们从终点的角度进行检查。

Simple and handles horizontal, vertical and all else in between. 简单,处理水平,垂直和其他所有。

Could you be more specific? 你可以再详细一点吗?

What programming language are you talking about? 你在谈论什么编程语言?

What environment are you talking about? 你在说什么环境?

What "lines" are you talking about? 你在说什么“线”? Text? 文本? What point? 什么点? XY on the screen? 屏幕上的XY?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何判断一个点是否在某条线附近? - How can I tell if a point is nearby a certain line? 我如何知道给定类的名称空间属于什么? - How can I tell which namespace agiven class belongs to? 我怎么知道什么时候/什么加载某些程序集? - How can I tell when/what is loading certain Assemblies? 选择错误答案后如何告诉我的程序 go 回到某个点? - How do I tell my program to go back to a certain point after the wrong answer is selected? 有没有办法判断一个帐户是否属于某个OU? - Is there a way to tell if an account belongs in a certain OU? 我可以告诉NHibernate不要保存某些对象吗? - Can I tell NHibernate not to save certain objects? 如何判断一个点是在线的右侧还是左侧 - How to tell whether a point is to the right or left side of a line 如何判断Unicode代码点是否是一个完整的可打印字形(或字形簇)? - How can I tell if a Unicode code point is one complete printable glyph(or grapheme cluster)? 如何显示只有1个数据点的折线图 - How can I display a line chart with only 1 data point 如何告诉 C# 中的 DateTime 将日期设置为某种语言? - How can I tell DateTime in C# to set the date to a certain language?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM